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/11/28 13:20:12 UTC

(ranger) branch master updated: RANGER-5335:Test Cases for hive-agent [ranger-hive-plugin] (#681)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 5ecf85f6f RANGER-5335:Test Cases for hive-agent [ranger-hive-plugin] (#681)
5ecf85f6f is described below

commit 5ecf85f6f2c03d3b63d845fce54572a84a477f07
Author: Bhaavesh Amol Amre <am...@gmail.com>
AuthorDate: Fri Nov 28 18:50:07 2025 +0530

    RANGER-5335:Test Cases for hive-agent [ranger-hive-plugin] (#681)
---
 .../${project.build.directory}/hbase_cm_hbase.json |    1 +
 .../hbase_cm_hbase_roles.json                      |    1 +
 hive-agent/pom.xml                                 |   12 +-
 .../TestXaSecureHiveAuthorizerFactory.java         |   40 +
 .../authorizer/TestRangerHiveAccessRequest.java    |  156 +++
 .../authorizer/TestRangerHiveAuditHandler.java     |  297 ++++
 .../hive/authorizer/TestRangerHiveAuthorizer.java  | 1454 ++++++++++++++++++++
 .../authorizer/TestRangerHiveAuthorizerBase.java   |  166 +++
 .../TestRangerHiveAuthorizerFactory.java           |   49 +
 .../authorizer/TestRangerHivePolicyProvider.java   |  128 ++
 .../hive/authorizer/TestRangerHiveResource.java    |  105 ++
 .../authorizer/TestRangerHiveResourceACLs.java     |   61 +
 .../services/hive/TestRangerServiceHive.java       |  230 ++++
 .../services/hive/client/TestHiveClient.java       |  584 ++++++++
 .../hive/client/TestHiveConnectionMgr.java         |  126 ++
 .../services/hive/client/TestHiveResourceMgr.java  |   98 ++
 16 files changed, 3505 insertions(+), 3 deletions(-)

diff --git a/agents-common/${project.build.directory}/hbase_cm_hbase.json b/agents-common/${project.build.directory}/hbase_cm_hbase.json
new file mode 100644
index 000000000..f229ea505
--- /dev/null
+++ b/agents-common/${project.build.directory}/hbase_cm_hbase.json
@@ -0,0 +1 @@
+{"serviceName":"cm_hbase","serviceId":3,"policyVersion":7141,"policies":[{"id":4,"isEnabled":true,"name":"all - table, column-family, column","policyPriority":0,"isAuditEnabled":true,"resources":{"column-family":{"values":["*"],"isExcludes":false,"isRecursive":false},"column":{"values":["*"],"isExcludes":false,"isRecursive":false},"table":{"values":["prospects","invoices"],"isExcludes":false,"isRecursive":false}},"policyItems":[{"accesses":[{"type":"read","isAllowed":true},{"type":"write [...]
\ No newline at end of file
diff --git a/agents-common/${project.build.directory}/hbase_cm_hbase_roles.json b/agents-common/${project.build.directory}/hbase_cm_hbase_roles.json
new file mode 100644
index 000000000..ff0a8cead
--- /dev/null
+++ b/agents-common/${project.build.directory}/hbase_cm_hbase_roles.json
@@ -0,0 +1 @@
+{"serviceName":"cm_hbase","roleVersion":-1,"roleUpdateTime":"20251127-18:38:48.229-+0530"}
\ No newline at end of file
diff --git a/hive-agent/pom.xml b/hive-agent/pom.xml
index feae1f724..a65d29d3a 100644
--- a/hive-agent/pom.xml
+++ b/hive-agent/pom.xml
@@ -268,9 +268,15 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-            <version>${slf4j.version}</version>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <version>${mockito.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-junit-jupiter</artifactId>
+            <version>${mockito.version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/hive-agent/src/test/java/com/xasecure/authorization/hive/authorizer/TestXaSecureHiveAuthorizerFactory.java b/hive-agent/src/test/java/com/xasecure/authorization/hive/authorizer/TestXaSecureHiveAuthorizerFactory.java
new file mode 100644
index 000000000..a32609513
--- /dev/null
+++ b/hive-agent/src/test/java/com/xasecure/authorization/hive/authorizer/TestXaSecureHiveAuthorizerFactory.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 com.xasecure.authorization.hive.authorizer;
+
+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;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for XaSecureHiveAuthorizerFactory
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestXaSecureHiveAuthorizerFactory {
+    @Test
+    public void testConstructor() {
+        XaSecureHiveAuthorizerFactory factory = new XaSecureHiveAuthorizerFactory();
+        assertNotNull(factory);
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAccessRequest.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAccessRequest.java
new file mode 100644
index 000000000..1991f44f4
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAccessRequest.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.authorization.hive.authorizer;
+
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzContext;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzSessionContext;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
+import org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer.HiveAccessType;
+import org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer.HiveObjectType;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+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.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.apache.ranger.authorization.hive.authorizer.RangerHiveAuditHandler.ACTION_TYPE_METADATA_OPERATION;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHiveAccessRequest
+ */
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHiveAccessRequest {
+    @Mock
+    private HiveAuthzContext mockAuthzContext;
+
+    @Mock
+    private HiveAuthzSessionContext mockSessionContext;
+
+    @Test
+    public void test01_setHiveAccessTypeMapsUseToAnyAndOthersToLowercase() {
+        RangerHiveResource resource = new RangerHiveResource(HiveObjectType.DATABASE, "db1");
+
+        RangerHiveAccessRequest useReq = new RangerHiveAccessRequest(resource, "user1", emptySet(), emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.USE, null, null);
+        assertEquals(HiveAccessType.USE, useReq.getHiveAccessType());
+        assertEquals(RangerPolicyEngine.ANY_ACCESS, useReq.getAccessType());
+
+        RangerHiveAccessRequest createReq = new RangerHiveAccessRequest(resource, "user1", emptySet(), emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.CREATE, null, null);
+        assertEquals(HiveAccessType.CREATE, createReq.getHiveAccessType());
+        assertEquals("create", createReq.getAccessType());
+    }
+
+    @Test
+    public void test02_constructorSetsMetadataDefaultsForDatabaseAndTable() {
+        // Database: expect "show databases"
+        RangerHiveResource dbResource = new RangerHiveResource(HiveObjectType.DATABASE, "");
+        when(mockAuthzContext.getCommandString()).thenReturn("");
+        when(mockAuthzContext.getForwardedAddresses()).thenReturn(Collections.singletonList("10.0.0.1"));
+        when(mockAuthzContext.getIpAddress()).thenReturn("127.0.0.1");
+        when(mockSessionContext.getSessionString()).thenReturn("session-1");
+
+        RangerHiveAccessRequest dbReq = new RangerHiveAccessRequest(dbResource, "alice", emptySet(), emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.USE, mockAuthzContext, mockSessionContext);
+        assertEquals("show databases", dbReq.getRequestData());
+        assertEquals("127.0.0.1", dbReq.getRemoteIPAddress());
+        assertEquals("session-1", dbReq.getSessionId());
+        assertNotNull(dbReq.getForwardedAddresses());
+
+        // Table: expect "show tables / views"
+        RangerHiveResource tblResource = new RangerHiveResource(HiveObjectType.TABLE, "db1", "tbl1");
+        when(mockAuthzContext.getCommandString()).thenReturn("");
+
+        RangerHiveAccessRequest tblReq = new RangerHiveAccessRequest(tblResource, "bob", emptySet(), emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.USE, mockAuthzContext, mockSessionContext);
+        assertEquals("show tables / views", tblReq.getRequestData());
+    }
+
+    @Test
+    public void test03_copyClonesAllRelevantFields() {
+        RangerHiveResource resource = new RangerHiveResource(HiveObjectType.TABLE, "dbA", "t1");
+        when(mockAuthzContext.getCommandString()).thenReturn("select 1");
+        when(mockAuthzContext.getForwardedAddresses()).thenReturn(Collections.singletonList("fwd"));
+        when(mockAuthzContext.getIpAddress()).thenReturn("1.2.3.4");
+        when(mockSessionContext.getSessionString()).thenReturn("sid");
+
+        Set<String> groups = new HashSet<>();
+        groups.add("g1");
+        Set<String> roles = new HashSet<>();
+        roles.add("r1");
+
+        RangerHiveAccessRequest req = new RangerHiveAccessRequest(resource, "u1", groups, roles, ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, mockAuthzContext, mockSessionContext);
+        req.setClusterName("cl1");
+        req.setClusterType("test");
+
+        RangerHiveAccessRequest copy = req.copy();
+
+        assertEquals(req.getResource(), copy.getResource());
+        assertEquals(req.getAccessType(), copy.getAccessType());
+        assertEquals(req.getUser(), copy.getUser());
+        assertEquals(req.getUserGroups(), copy.getUserGroups());
+        assertEquals(req.getUserRoles(), copy.getUserRoles());
+        assertEquals(req.getAction(), copy.getAction());
+        assertEquals(req.getClientIPAddress(), copy.getClientIPAddress());
+        assertEquals(req.getRemoteIPAddress(), copy.getRemoteIPAddress());
+        assertEquals(req.getForwardedAddresses(), copy.getForwardedAddresses());
+        assertEquals(req.getRequestData(), copy.getRequestData());
+        assertEquals(req.getClientType(), copy.getClientType());
+        assertEquals(req.getSessionId(), copy.getSessionId());
+        assertEquals(req.getHiveAccessType(), copy.getHiveAccessType());
+        assertEquals(req.getClusterName(), copy.getClusterName());
+        assertEquals(req.getClusterType(), copy.getClusterType());
+    }
+
+    @Test
+    public void test04_hiveOperationTypeConstructorSetsActionAndAccess() {
+        RangerHiveResource resource = new RangerHiveResource(HiveObjectType.TABLE, "db2", "t2");
+
+        RangerHiveAccessRequest req = new RangerHiveAccessRequest(resource, "user2", emptySet(), emptySet(), HiveOperationType.CREATETABLE, HiveAccessType.CREATE, null, null);
+        assertEquals(HiveAccessType.CREATE, req.getHiveAccessType());
+        assertEquals("create", req.getAccessType());
+        assertEquals(HiveOperationType.CREATETABLE.name(), req.getAction());
+    }
+
+    @Test
+    public void test05_shortConstructorSetsMetadataUseDefaults() {
+        RangerHiveResource dbResource = new RangerHiveResource(HiveObjectType.DATABASE, "");
+        when(mockAuthzContext.getCommandString()).thenReturn("");
+        when(mockAuthzContext.getForwardedAddresses()).thenReturn(Collections.singletonList("10.0.0.2"));
+        when(mockAuthzContext.getIpAddress()).thenReturn("127.0.0.2");
+
+        RangerHiveAccessRequest req = new RangerHiveAccessRequest(dbResource, "carol", emptySet(), emptySet(), mockAuthzContext, null);
+        assertEquals(HiveAccessType.USE, req.getHiveAccessType());
+        assertEquals(RangerPolicyEngine.ANY_ACCESS, req.getAccessType());
+        assertEquals(ACTION_TYPE_METADATA_OPERATION, req.getAction());
+        assertEquals("show databases", req.getRequestData());
+    }
+
+    private static Set<String> emptySet() {
+        return Collections.emptySet();
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuditHandler.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuditHandler.java
new file mode 100644
index 000000000..17618a126
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuditHandler.java
@@ -0,0 +1,297 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.authorization.hive.authorizer;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
+import org.apache.ranger.audit.model.AuthzAuditEvent;
+import org.apache.ranger.audit.provider.AuditHandler;
+import org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer.HiveAccessType;
+import org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer.HiveObjectType;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+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.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.apache.ranger.authorization.hive.authorizer.RangerHiveAuditHandler.ACCESS_TYPE_DELETE;
+import static org.apache.ranger.authorization.hive.authorizer.RangerHiveAuditHandler.ACCESS_TYPE_INSERT;
+import static org.apache.ranger.authorization.hive.authorizer.RangerHiveAuditHandler.ACCESS_TYPE_ROWFILTER;
+import static org.apache.ranger.authorization.hive.authorizer.RangerHiveAuditHandler.ACCESS_TYPE_TRUNCATE;
+import static org.apache.ranger.authorization.hive.authorizer.RangerHiveAuditHandler.ACCESS_TYPE_UPDATE;
+import static org.apache.ranger.authorization.hive.authorizer.RangerHiveAuditHandler.ACTION_TYPE_METADATA_OPERATION;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+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.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.RETURNS_DEFAULTS;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHiveAuditHandler
+ */
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHiveAuditHandler {
+    @Test
+    public void test01_requestDataTruncatedByConfigAndUrlLeafReplaced() {
+        Configuration conf = new Configuration(false);
+        conf.setInt(RangerHiveAuditHandler.CONF_AUDIT_QUERY_REQUEST_SIZE, 10);
+        RangerHiveAuditHandler handler = new RangerHiveAuditHandler(conf);
+
+        RangerHiveResource      resource = new RangerHiveResource(HiveObjectType.URI, "/tmp/dir");
+        RangerHiveAccessRequest request  = new RangerHiveAccessRequest(resource, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.USE, null, null);
+        request.setRequestData("this-is-a-very-long-query");
+
+        RangerAccessResult res = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, request);
+        res.setIsAudited(true);
+        res.setIsAllowed(true);
+        res.setPolicyId(1L);
+
+        AuthzAuditEvent event = handler.createAuditEvent(res);
+        assertNotNull(event);
+        assertEquals(ACTION_TYPE_METADATA_OPERATION, event.getAccessType());
+        assertEquals("this-is-a-", event.getRequestData());
+        // Note: Without a service-def, resourcePath/leafName may be null; skip asserting resource path/type here.
+    }
+
+    @Test
+    public void test02_datamaskAndRowfilterAccessType() {
+        RangerHiveAuditHandler handler = new RangerHiveAuditHandler();
+
+        // Data mask
+        RangerHiveResource      tbl     = new RangerHiveResource(HiveObjectType.TABLE, "db", "t");
+        RangerHiveAccessRequest reqMask = new RangerHiveAccessRequest(tbl, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      mask    = new RangerAccessResult(RangerPolicy.POLICY_TYPE_DATAMASK, "svc", null, reqMask);
+        mask.setIsAudited(true);
+        mask.setIsAllowed(true);
+        mask.setPolicyId(11L);
+        mask.setMaskType("redact");
+        AuthzAuditEvent e1 = handler.createAuditEvent(mask);
+        assertEquals("redact", e1.getAccessType());
+
+        // Row filter
+        RangerHiveAccessRequest reqRf     = new RangerHiveAccessRequest(tbl, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      rowFilter = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ROWFILTER, "svc", null, reqRf);
+        rowFilter.setIsAudited(true);
+        rowFilter.setIsAllowed(true);
+        rowFilter.setPolicyId(12L);
+        rowFilter.setFilterExpr("col > 5");
+        AuthzAuditEvent e2 = handler.createAuditEvent(rowFilter);
+        assertEquals(ACCESS_TYPE_ROWFILTER, e2.getAccessType());
+    }
+
+    @Test
+    public void test03_updateAccessTypeDerivedFromCommandString() {
+        RangerHiveAuditHandler  handler = new RangerHiveAuditHandler();
+        RangerHiveResource      tbl     = new RangerHiveResource(HiveObjectType.TABLE, "db", "t");
+        RangerHiveAccessRequest req     = new RangerHiveAccessRequest(tbl, "u", Collections.emptySet(), Collections.emptySet(), "QUERY", HiveAccessType.UPDATE, null, null);
+        req.setRequestData("insert into t values (1)");
+        RangerAccessResult result = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, req);
+        result.setIsAudited(true);
+        result.setIsAllowed(true);
+        result.setPolicyId(21L);
+        AuthzAuditEvent eIns = handler.createAuditEvent(result);
+        assertEquals(ACCESS_TYPE_INSERT, eIns.getAccessType());
+
+        req.setRequestData("update t set c=1");
+        AuthzAuditEvent eUpd = handler.createAuditEvent(result);
+        assertEquals(ACCESS_TYPE_UPDATE, eUpd.getAccessType());
+
+        req.setRequestData("delete from t");
+        AuthzAuditEvent eDel = handler.createAuditEvent(result);
+        assertEquals(ACCESS_TYPE_DELETE, eDel.getAccessType());
+
+        req.setRequestData("truncate table t");
+        AuthzAuditEvent eTrunc = handler.createAuditEvent(result);
+        assertEquals(ACCESS_TYPE_TRUNCATE, eTrunc.getAccessType());
+    }
+
+    @Test
+    public void test04_replAndServiceAdminAccessTypeOverrides() {
+        RangerHiveAuditHandler  handler = new RangerHiveAuditHandler();
+        RangerHiveResource      global  = new RangerHiveResource(HiveObjectType.GLOBAL, null);
+        RangerHiveAccessRequest replReq = new RangerHiveAccessRequest(global, "u", Collections.emptySet(), Collections.emptySet(), "REPL DUMP", HiveAccessType.REPLADMIN, null, null);
+        replReq.setRequestData("REPL DUMP db1 to location");
+        RangerAccessResult replRes = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, replReq);
+        replRes.setIsAudited(true);
+        replRes.setIsAllowed(true);
+        replRes.setPolicyId(31L);
+        AuthzAuditEvent eRepl = handler.createAuditEvent(replRes);
+        assertEquals("REPL DUMP", eRepl.getAccessType());
+
+        RangerHiveAccessRequest saReq = new RangerHiveAccessRequest(global, "u", Collections.emptySet(), Collections.emptySet(), "KILL_QUERY", HiveAccessType.SERVICEADMIN, null, null);
+        saReq.setRequestData("KILL QUERY q123");
+        RangerAccessResult saRes = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, saReq);
+        saRes.setIsAudited(true);
+        saRes.setIsAllowed(true);
+        saRes.setPolicyId(32L);
+        AuthzAuditEvent eSa = handler.createAuditEvent(saRes);
+        assertEquals("KILL QUERY", eSa.getAccessType());
+        assertEquals("QUERY ID = q123", eSa.getRequestData());
+    }
+
+    @Test
+    public void test05_roleOpsUseActionAsAccessTypeForGlobal() {
+        RangerHiveAuditHandler  handler = new RangerHiveAuditHandler();
+        RangerHiveResource      global  = new RangerHiveResource(HiveObjectType.GLOBAL, null);
+        RangerHiveAccessRequest req     = new RangerHiveAccessRequest(global, "u", Collections.emptySet(), Collections.emptySet(), HiveOperationType.CREATEROLE.name(), HiveAccessType.USE, null, null);
+        RangerAccessResult      res     = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, req);
+        res.setIsAudited(true);
+        res.setIsAllowed(true);
+        res.setPolicyId(41L);
+        AuthzAuditEvent e = handler.createAuditEvent(res);
+        assertEquals(HiveOperationType.CREATEROLE.name(), e.getAccessType());
+    }
+
+    @Test
+    public void test06_processResultsAggregatesColumnsAndShortCircuitsOnDeny() {
+        RangerHiveAuditHandler handler = new RangerHiveAuditHandler();
+
+        List<RangerAccessResult> results = new ArrayList<>();
+        // First allowed for column c1 under policy 100
+        RangerHiveResource      col1 = new RangerHiveResource(HiveObjectType.COLUMN, "db", "t", "c1");
+        RangerHiveAccessRequest r1   = new RangerHiveAccessRequest(col1, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      a1   = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, r1);
+        a1.setIsAudited(true);
+        a1.setIsAllowed(true);
+        a1.setPolicyId(100L);
+        results.add(a1);
+        // Second allowed for column c2 under same policy 100 -> should merge columns
+        RangerHiveResource      col2 = new RangerHiveResource(HiveObjectType.COLUMN, "db", "t", "c2");
+        RangerHiveAccessRequest r2   = new RangerHiveAccessRequest(col2, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      a2   = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, r2);
+        a2.setIsAudited(true);
+        a2.setIsAllowed(true);
+        a2.setPolicyId(100L);
+        results.add(a2);
+        // Third is a deny -> list should contain only the deny event
+        RangerHiveAccessRequest r3 = new RangerHiveAccessRequest(col2, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      d1 = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, r3);
+        d1.setIsAudited(true);
+        d1.setIsAllowed(false);
+        d1.setPolicyId(200L);
+        List<AuthzAuditEvent> events = handler.createAuditEvents(results);
+
+        // Before deny added, events should be one (merged). Now add deny and ensure single deny returned
+        assertEquals(1, events.size());
+        AuthzAuditEvent merged = events.get(0);
+        assertTrue(merged.getResourcePath().contains(",") || merged.getResourcePath().contains("db/t"));
+
+        results.add(d1);
+        List<AuthzAuditEvent> onlyDeny = handler.createAuditEvents(results);
+        assertEquals(1, onlyDeny.size());
+        assertEquals(0, onlyDeny.get(0).getAccessResult());
+    }
+
+    @Test
+    public void test07_flushAuditSkipsAllowedWhenDeniedExists() {
+        Configuration          conf    = new Configuration(false);
+        RangerHiveAuditHandler handler = spy(new RangerHiveAuditHandler(conf));
+
+        // Prepare two events: one allow, one deny
+        RangerHiveResource      res   = new RangerHiveResource(HiveObjectType.TABLE, "db", "t");
+        RangerHiveAccessRequest req   = new RangerHiveAccessRequest(res, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      allow = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, req);
+        allow.setIsAudited(true);
+        allow.setIsAllowed(true);
+        allow.setPolicyId(1);
+        AuthzAuditEvent    eAllow = handler.createAuditEvent(allow);
+        RangerAccessResult deny   = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, req);
+        deny.setIsAudited(true);
+        deny.setIsAllowed(false);
+        deny.setPolicyId(2);
+        AuthzAuditEvent eDeny = handler.createAuditEvent(deny);
+
+        // Add both to handler internal queue via processResult
+        handler.processResult(allow);
+        handler.processResult(deny);
+
+        // Intercept calls to base plugin audit provider via static mocking
+        try (MockedStatic<RangerBasePlugin> base = mockStatic(RangerBasePlugin.class)) {
+            AuditHandler mockAudit = mock(AuditHandler.class, RETURNS_DEFAULTS);
+            base.when(() -> RangerBasePlugin.getAuditProvider(anyString())).thenReturn(mockAudit);
+
+            handler.flushAudit();
+
+            // when denied exists, allowed event should be skipped
+            verify(mockAudit, atLeastOnce()).log(any(AuthzAuditEvent.class));
+        }
+    }
+
+    @Test
+    public void test08_processResultsAddsAllAuditEvents() {
+        RangerHiveAuditHandler  handler = new RangerHiveAuditHandler();
+        RangerHiveResource      tbl     = new RangerHiveResource(HiveObjectType.TABLE, "db", "t");
+        RangerHiveAccessRequest r1      = new RangerHiveAccessRequest(tbl, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      a1      = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, r1);
+        a1.setIsAudited(true);
+        a1.setIsAllowed(true);
+        a1.setPolicyId(10L);
+        RangerHiveAccessRequest r2 = new RangerHiveAccessRequest(tbl, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.SELECT, null, null);
+        RangerAccessResult      a2 = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, r2);
+        a2.setIsAudited(true);
+        a2.setIsAllowed(true);
+        a2.setPolicyId(20L);
+
+        List<RangerAccessResult> list = new ArrayList<>();
+        list.add(a1);
+        list.add(a2);
+
+        handler.processResults(list);
+        // if no exception occurs, events were added; flush to ensure no NPEs
+        handler.flushAudit();
+    }
+
+    @Test
+    public void test09_logAuditEventForDfsBuildsEvent() {
+        RangerHiveAuditHandler handler = new RangerHiveAuditHandler();
+        handler.logAuditEventForDfs("u1", "hdfs dfs -ls /tmp", true, 1, "repo");
+        // No exception expected; flush to exercise logging path
+        handler.flushAudit();
+    }
+
+    @Test
+    public void test10_createAuditEventUsesUrlFirstElement() {
+        RangerHiveAuditHandler  handler = new RangerHiveAuditHandler();
+        RangerHiveResource      urlRes  = new RangerHiveResource(HiveObjectType.URI, "/data/path");
+        RangerHiveAccessRequest req     = new RangerHiveAccessRequest(urlRes, "u", Collections.emptySet(), Collections.emptySet(), ACTION_TYPE_METADATA_OPERATION, HiveAccessType.USE, null, null);
+        RangerAccessResult      res     = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, req);
+        res.setIsAudited(true);
+        res.setIsAllowed(true);
+        res.setPolicyId(5L);
+        AuthzAuditEvent ev = handler.createAuditEvent(res);
+        assertNotNull(ev);
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizer.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizer.java
new file mode 100644
index 000000000..7bba1b113
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizer.java
@@ -0,0 +1,1454 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.authorization.hive.authorizer;
+
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.permission.FsAction;
+import org.apache.hadoop.hive.metastore.IMetaStoreClient;
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.hadoop.hive.metastore.api.HiveObjectRef;
+import org.apache.hadoop.hive.metastore.api.HiveObjectType;
+import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
+import org.apache.hadoop.hive.metastore.api.Table;
+import org.apache.hadoop.hive.ql.security.HiveAuthenticationProvider;
+import org.apache.hadoop.hive.ql.security.authorization.AuthorizationUtils;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAccessControlException;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzContext;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzPluginException;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzSessionContext;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzSessionContext.CLIENT_TYPE;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveMetastoreClientFactory;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePolicyProvider;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrincipal;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilege;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeInfo;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivObjectActionType;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveResourceACLs.AccessResult;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveResourceACLs.Privilege;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveRoleGrant;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerRole;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs;
+import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+import org.apache.ranger.plugin.util.GrantRevokeRequest;
+import org.apache.ranger.plugin.util.GrantRevokeRoleRequest;
+import org.apache.ranger.plugin.util.RangerRoles;
+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.junit.jupiter.api.function.Executable;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHiveAuthorizer
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHiveAuthorizer {
+    @Test
+    public void test01_constructorInitializesPluginForHiveCLI() throws Exception {
+        setStaticHivePlugin(null);
+
+        HiveMetastoreClientFactory msFactory      = Mockito.mock(HiveMetastoreClientFactory.class);
+        HiveAuthenticationProvider authenticator  = Mockito.mock(HiveAuthenticationProvider.class);
+        HiveAuthzSessionContext    sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+        Mockito.when(sessionContext.getClientType()).thenReturn(CLIENT_TYPE.HIVECLI);
+
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(msFactory, null, authenticator, sessionContext);
+
+        RangerBasePlugin plugin = getStaticHivePlugin();
+        assertNotNull(plugin);
+        assertEquals("hiveCLI", plugin.getAppId());
+    }
+
+    @Test
+    public void test02_getHivePolicyProviderReturnsProviderWhenPluginPresent() throws Exception {
+        setStaticHivePlugin(null);
+        HiveMetastoreClientFactory msFactory      = Mockito.mock(HiveMetastoreClientFactory.class);
+        HiveAuthzSessionContext    sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+        Mockito.when(sessionContext.getClientType()).thenReturn(CLIENT_TYPE.HIVECLI);
+
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(msFactory, null, null, sessionContext);
+
+        HivePolicyProvider provider = authorizer.getHivePolicyProvider();
+        assertNotNull(provider);
+    }
+
+    @Test
+    public void test03_getHivePolicyProviderThrowsWhenPluginNull() throws Exception {
+        HiveMetastoreClientFactory msFactory  = Mockito.mock(HiveMetastoreClientFactory.class);
+        RangerHiveAuthorizer       authorizer = new RangerHiveAuthorizer(msFactory, null, null, null);
+
+        // Force plugin to null after construction
+        setStaticHivePlugin(null);
+
+        Executable call = authorizer::getHivePolicyProvider;
+        assertThrows(HiveAuthzPluginException.class, call);
+    }
+
+    @Test
+    public void test04_showPrivilegesThrowsWhenPluginNull() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        setStaticHivePlugin(null);
+        HivePrivilegeObject      obj  = new HivePrivilegeObject(HivePrivilegeObjectType.DATABASE, "db1", null);
+        Executable               call = () -> authorizer.showPrivileges(null, obj);
+        HiveAuthzPluginException ex   = assertThrows(HiveAuthzPluginException.class, call);
+        assertEquals("RangerHiveAuthorizer.showPrivileges error: hivePlugin is null", ex.getMessage());
+    }
+
+    @Test
+    public void test05_createHiveResourceMappings() throws Exception {
+        HiveMetastoreClientFactory msFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           msClient  = Mockito.mock(IMetaStoreClient.class);
+        Mockito.when(msFactory.getHiveMetastoreClient()).thenReturn(msClient);
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(msFactory, null, null, null);
+
+        HivePrivilegeObject           db     = new HivePrivilegeObject(HivePrivilegeObjectType.DATABASE, "dbA", null);
+        Map<String, String> owners = new HashMap<>();
+        owners.put("dbA", "ownerA");
+        RangerHiveResource dbRes = authorizer.createHiveResource(db, owners);
+        assertNotNull(dbRes);
+        assertEquals("dbA", dbRes.getDatabase());
+
+        HivePrivilegeObject tbl = new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, "dbB", "t1");
+        owners.put("dbB.t1", "ownerB");
+        RangerHiveResource tblRes = authorizer.createHiveResource(tbl, owners);
+        assertNotNull(tblRes);
+        assertEquals("dbB", tblRes.getDatabase());
+        assertEquals("t1", tblRes.getTable());
+    }
+
+    @Test
+    public void test06_needTransformReturnsTrue() {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        assertTrue(authorizer.needTransform());
+    }
+
+    @Test
+    public void test07_grantAndRevokePrivilegesThrowWhenUpdatesDisabled() throws Exception {
+        HiveMetastoreClientFactory msFactory  = Mockito.mock(HiveMetastoreClientFactory.class);
+        RangerHiveAuthorizer       authorizer = new RangerHiveAuthorizer(msFactory, null, null, null);
+        setStaticHivePlugin(null);
+        // Disable updates
+        setRangerHivePluginUpdateFlag(false);
+
+        HivePrivilegeObject hiveObj    = new HivePrivilegeObject(HivePrivilegeObjectType.DATABASE, "db1", null);
+        List<HivePrincipal> principals = Collections.singletonList(new HivePrincipal("alice", HivePrincipal.HivePrincipalType.USER));
+        List<HivePrivilege> privileges = Collections.emptyList();
+
+        assertThrows(HiveAuthzPluginException.class, () -> authorizer.grantPrivileges(principals, privileges, hiveObj, principals.get(0), true));
+        assertThrows(HiveAuthzPluginException.class, () -> authorizer.revokePrivileges(principals, privileges, hiveObj, principals.get(0), true));
+    }
+
+    @Test
+    public void test08_createRoleAuditsAndUsesReservedCheck() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        // stub createRole to avoid admin client
+        Mockito.doReturn(new RangerRole()).when(pluginSpy).createRole(Mockito.any(RangerRole.class), Mockito.any());
+        setStaticHivePlugin(pluginSpy);
+        HiveMetastoreClientFactory msFactory  = Mockito.mock(HiveMetastoreClientFactory.class);
+        RangerHiveAuthorizer       authorizer = Mockito.spy(new RangerHiveAuthorizer(msFactory, null, null, null));
+        // getGrantorUsername pulls from principal
+        HivePrincipal grantor = new HivePrincipal("bob", HivePrincipal.HivePrincipalType.USER);
+
+        // Success path
+        authorizer.createRole("role1", grantor);
+        // No direct verify; ensure no exception and audit path executed
+
+        // Reserved name path
+        assertThrows(HiveAuthzPluginException.class, () -> authorizer.createRole("all", grantor));
+    }
+
+    @Test
+    public void test09_dropRoleValidatesAndAudits() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doNothing().when(pluginSpy).dropRole(Mockito.anyString(), Mockito.anyString(), Mockito.any());
+        setStaticHivePlugin(pluginSpy);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+
+        UserGroupInformation ugi = UserGroupInformation.createRemoteUser("charlie");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        authorizer.dropRole("roleX");
+        // Success path confirmed by no exception
+
+        assertThrows(HiveAuthzPluginException.class, () -> authorizer.dropRole("all"));
+    }
+
+    @Test
+    public void test10_getPrincipalGrantInfoForRoleRequiresAdmin() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(false).when(pluginSpy).isServiceAdmin("dave");
+        setStaticHivePlugin(pluginSpy);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+
+        UserGroupInformation ugi = UserGroupInformation.createRemoteUser("dave");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        assertThrows(HiveAuthzPluginException.class, () -> authorizer.getPrincipalGrantInfoForRole("r1"));
+    }
+
+    @Test
+    public void test11_getRoleGrantInfoForPrincipalHappyPath() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        setStaticHivePlugin(pluginSpy);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = UserGroupInformation.createRemoteUser("erin");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        List<HiveRoleGrant> grants = authorizer.getRoleGrantInfoForPrincipal(new HivePrincipal("erin", HivePrincipal.HivePrincipalType.USER));
+        assertNotNull(grants);
+    }
+
+    @Test
+    public void test12_grantAndRevokeRoleAuditFlow() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doNothing().when(pluginSpy).grantRole(Mockito.any(GrantRevokeRoleRequest.class), Mockito.any());
+        Mockito.doNothing().when(pluginSpy).revokeRole(Mockito.any(GrantRevokeRoleRequest.class), Mockito.any());
+        setStaticHivePlugin(pluginSpy);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        HivePrincipal        grantor    = new HivePrincipal("frank", HivePrincipal.HivePrincipalType.USER);
+        // Provide group names and session context when asked
+        HiveAuthzSessionContext sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+        Mockito.doReturn(sessionContext).when(authorizer).getHiveAuthzSessionContext();
+
+        authorizer.grantRole(Collections.singletonList(new HivePrincipal("x", HivePrincipal.HivePrincipalType.USER)), Collections.singletonList("r"), true, grantor);
+        // success implies audit + call path executed
+
+        authorizer.revokeRole(Collections.singletonList(new HivePrincipal("x", HivePrincipal.HivePrincipalType.USER)), Collections.singletonList("r"), true, grantor);
+        // success implies audit + call path executed
+    }
+
+    @Test
+    public void test13_checkPrivilegesThrowsWhenUserNull() {
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        Mockito.doReturn(null).when(authorizer).getCurrentUserGroupInfo();
+        assertThrows(HiveAccessControlException.class, () -> authorizer.checkPrivileges(HiveOperationType.QUERY, Collections.emptyList(), Collections.emptyList(), Mockito.mock(HiveAuthzContext.class)));
+    }
+
+    @Test
+    public void test14_checkPrivilegesDfsOperationReturnsEarly() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        setStaticHivePlugin(pluginSpy);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = UserGroupInformation.createRemoteUser("user1");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+        HivePrivilegeObject dfsObj = new HivePrivilegeObject(HivePrivilegeObjectType.DFS_URI, null, "hdfs://namenode/tmp");
+        assertThrows(HiveAccessControlException.class, () -> authorizer.checkPrivileges(HiveOperationType.DFS, Collections.singletonList(dfsObj), Collections.emptyList(), Mockito.mock(HiveAuthzContext.class)));
+    }
+
+    @Test
+    public void test15_checkPrivilegesShowDatabasesAllowed() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(allowedResult()).when(pluginSpy).isAccessAllowed(Mockito.any(RangerAccessRequestImpl.class), Mockito.any());
+        setStaticHivePlugin(pluginSpy);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = UserGroupInformation.createRemoteUser("user2");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+        authorizer.checkPrivileges(HiveOperationType.SHOWDATABASES, Collections.emptyList(), Collections.emptyList(), Mockito.mock(HiveAuthzContext.class));
+    }
+
+    @Test
+    public void test17_filterListCmdObjectsNullReturnsNull() {
+        RangerHiveAuthorizer      authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        List<HivePrivilegeObject> ret        = authorizer.filterListCmdObjects(null, Mockito.mock(HiveAuthzContext.class));
+        assertNull(ret);
+    }
+
+    @Test
+    public void test18_filterListCmdObjectsUserNullReturnsOriginal() {
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        Mockito.doReturn(null).when(authorizer).getCurrentUserGroupInfo();
+        HivePrivilegeObject       obj = new HivePrivilegeObject(HivePrivilegeObjectType.DATABASE, "dbX", null);
+        List<HivePrivilegeObject> in  = Collections.singletonList(obj);
+        List<HivePrivilegeObject> out = authorizer.filterListCmdObjects(in, Mockito.mock(HiveAuthzContext.class));
+        assertEquals(in, out);
+    }
+
+    @Test
+    public void test19_filterListCmdObjectsAllowsWhenPluginAllows() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(allowedResult()).when(pluginSpy).isAccessAllowed(Mockito.any(RangerAccessRequestImpl.class), Mockito.any());
+        setStaticHivePlugin(pluginSpy);
+        HiveMetastoreClientFactory msFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           ms        = Mockito.mock(IMetaStoreClient.class);
+        Mockito.when(msFactory.getHiveMetastoreClient()).thenReturn(ms);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(msFactory, null, null, null));
+        UserGroupInformation ugi        = UserGroupInformation.createRemoteUser("user4");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+        HivePrivilegeObject       obj = new HivePrivilegeObject(HivePrivilegeObjectType.DATABASE, "dbY", null);
+        List<HivePrivilegeObject> out = authorizer.filterListCmdObjects(Collections.singletonList(obj), Mockito.mock(HiveAuthzContext.class));
+        assertNotNull(out);
+        assertEquals(1, out.size());
+    }
+
+    @Test
+    public void test20_getAllRolesThrowsWhenPluginNullOrUserNull() {
+        // Test user null path with valid plugin
+        try {
+            setStaticHivePlugin((RangerBasePlugin) newInstanceRangerHivePlugin("hiveCLI"));
+        } catch (Exception ignored) {
+        }
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        Mockito.doReturn(null).when(authorizer).getCurrentUserGroupInfo();
+        assertThrows(HiveAccessControlException.class, () -> authorizer.getAllRoles());
+    }
+
+    @Test
+    public void test21_getAllRolesUnauthorized() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(false).when(pluginSpy).isServiceAdmin("ua");
+        setStaticHivePlugin(pluginSpy);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = UserGroupInformation.createRemoteUser("ua");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+        assertThrows(HiveAuthzPluginException.class, authorizer::getAllRoles);
+    }
+
+    @Test
+    public void test23_applyRowFilterAndColumnMaskingTransforms() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        // Row filter enabled
+        RangerAccessResult rf = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ROWFILTER, "svc", null, new RangerAccessRequestImpl());
+        rf.setFilterExpr("col > 5");
+        Mockito.doReturn(rf).when(pluginSpy).evalRowFilterPolicies(Mockito.any(RangerHiveAccessRequest.class), Mockito.any());
+        setStaticHivePlugin(pluginSpy);
+
+        HiveMetastoreClientFactory msFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           ms        = Mockito.mock(IMetaStoreClient.class);
+        Mockito.when(msFactory.getHiveMetastoreClient()).thenReturn(ms);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(msFactory, null, null, null));
+        UserGroupInformation ugi        = UserGroupInformation.createRemoteUser("um");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        HivePrivilegeObject       tbl = new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, "dbZ", "tZ");
+        List<HivePrivilegeObject> ret = authorizer.applyRowFilterAndColumnMasking(Mockito.mock(HiveAuthzContext.class), Collections.singletonList(tbl));
+        assertNotNull(ret);
+        assertEquals(1, ret.size());
+    }
+
+    @Test
+    public void test24_getURIAccessTypeAndBuildPathForException() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getURIAccessType", HiveOperationType.class);
+        m.setAccessible(true);
+        Object read  = m.invoke(authorizer, HiveOperationType.LOAD);
+        Object write = m.invoke(authorizer, HiveOperationType.EXPORT);
+        assertEquals(FsAction.READ, read);
+        assertEquals(FsAction.WRITE, write);
+
+        Method m2 = RangerHiveAuthorizer.class.getDeclaredMethod("buildPathForException", String.class, HiveOperationType.class);
+        m2.setAccessible(true);
+        String desc = (String) m2.invoke(authorizer, "db/table", HiveOperationType.DESCTABLE);
+        assertEquals("db/table/*", desc);
+        String q = (String) m2.invoke(authorizer, "db/table/part", HiveOperationType.QUERY);
+        assertTrue(q.endsWith("/*"));
+    }
+
+    @Test
+    public void test25_getAllRolesSuccess() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(true).when(pluginSpy).isServiceAdmin("sa");
+        RangerRoles                                    roles = new RangerRoles();
+        Set<RangerRole> rr    = new HashSet<>();
+        RangerRole      r     = new RangerRole();
+        r.setName("roleX");
+        rr.add(r);
+        roles.setRangerRoles(rr);
+        Mockito.doReturn(roles).when(pluginSpy).getRangerRoles();
+        setStaticHivePlugin(pluginSpy);
+
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = UserGroupInformation.createRemoteUser("sa");
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        List<String> out = authorizer.getAllRoles();
+        assertNotNull(out);
+        assertTrue(out.contains("roleX"));
+    }
+
+    @Test
+    public void test26_setCurrentRoleNoneAndAdmin() throws Exception {
+        // Ensure plugin is initialized for audit handler
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(new HashSet<>(Arrays.asList("admin", "r1")))
+                .when(pluginSpy).getRolesFromUserAndGroups(Mockito.eq("userA"), Mockito.anySet());
+        setStaticHivePlugin(pluginSpy);
+
+        HiveAuthzSessionContext    sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+        HiveAuthenticationProvider authenticator  = Mockito.mock(HiveAuthenticationProvider.class);
+        Mockito.when(authenticator.getUserName()).thenReturn("userA");
+
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, authenticator, sessionContext));
+
+        // Seed fields
+        Field fRoles = RangerHiveAuthorizer.class.getDeclaredField("currentRoles");
+        fRoles.setAccessible(true);
+        Field fFlag = RangerHiveAuthorizer.class.getDeclaredField("isCurrentRoleSet");
+        fFlag.setAccessible(true);
+
+        Set<String> roles = new HashSet<>();
+        roles.add("old");
+        fRoles.set(authorizer, roles);
+
+        // NONE clears roles
+        authorizer.setCurrentRole("NONE");
+        Set<String> afterNone = (Set<String>) fRoles.get(authorizer);
+        assertTrue(afterNone.isEmpty());
+        assertTrue((Boolean) fFlag.get(authorizer));
+
+        // ADMIN fills with admin (adminRole is computed in getCurrentRoleNamesFromRanger)
+        roles.add("x");
+        fRoles.set(authorizer, roles);
+        authorizer.setCurrentRole("admin");
+        Set<String> afterAdmin = (Set<String>) fRoles.get(authorizer);
+        assertTrue(afterAdmin.contains("admin"));
+    }
+
+    @Test
+    public void test27_isPathInFSScheme() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("isPathInFSScheme", String.class);
+        m.setAccessible(true);
+        boolean hdfs = (Boolean) m.invoke(authorizer, "hdfs://nn/tmp");
+        boolean s3a  = (Boolean) m.invoke(authorizer, "s3a://bucket");
+        assertFalse(s3a);
+    }
+
+    @Test
+    public void test28_getCurrentRoleNamesFromRanger_excludesAdmin() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        setStaticHivePlugin(pluginSpy);
+
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = Mockito.mock(UserGroupInformation.class);
+        Mockito.doReturn("bob").when(ugi).getShortUserName();
+        Mockito.doReturn(new String[] {"g1"}).when(ugi).getGroupNames();
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        Set<String> pluginRoles = new HashSet<>();
+        pluginRoles.add("analyst");
+        pluginRoles.add("admin"); // ROLE_ADMIN should be excluded from return set
+        Mockito.doReturn(pluginRoles).when(pluginSpy).getRolesFromUserAndGroups(Mockito.eq("bob"), Mockito.anySet());
+
+        Field fUser = RangerHiveAuthorizer.class.getDeclaredField("currentUserName");
+        fUser.setAccessible(true);
+        fUser.set(authorizer, "bob");
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getCurrentRoleNamesFromRanger");
+        m.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Set<String> ret = (Set<String>) m.invoke(authorizer);
+
+        assertTrue(ret.contains("analyst"));
+        assertFalse(ret.contains("admin"));
+
+        Field fAdmin = RangerHiveAuthorizer.class.getDeclaredField("adminRole");
+        fAdmin.setAccessible(true);
+        Object adminRole = fAdmin.get(authorizer);
+        assertEquals("admin", adminRole);
+    }
+
+    @Test
+    public void test29_getCurrentRoleNamesFromRanger_ugiNullThrows() throws Exception {
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        Mockito.doReturn(null).when(authorizer).getCurrentUserGroupInfo();
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getCurrentRoleNamesFromRanger");
+        m.setAccessible(true);
+        assertThrows(HiveAuthzPluginException.class, () -> {
+            try {
+                m.invoke(authorizer);
+            } catch (Exception e) {
+                if (e.getCause() instanceof HiveAuthzPluginException) {
+                    throw e.getCause();
+                }
+                throw new RuntimeException(e);
+            }
+        });
+    }
+
+    @Test
+    public void test30_getRolesforUserAndGroups_nullPluginReturnsEmpty() throws Exception {
+        setStaticHivePlugin(null);
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getRolesforUserAndGroups", String.class, Set.class);
+        m.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Set<String> ret = (Set<String>) m.invoke(authorizer, "user", new HashSet<>());
+        assertNotNull(ret);
+        assertTrue(ret.isEmpty());
+    }
+
+    @Test
+    public void test31_getHiveRoleGrant_buildsFields() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+
+        RangerRole role = new RangerRole();
+        role.setName("roleA");
+        role.setCreatedByUser("creator1");
+        role.setUpdateTime(new Date(2000L));
+
+        Class<?> roleMemberCls = Class.forName("org.apache.ranger.plugin.model.RangerRole$RoleMember");
+        Object   member        = roleMemberCls.getDeclaredConstructor().newInstance();
+        roleMemberCls.getMethod("setName", String.class).invoke(member, "user1");
+        roleMemberCls.getMethod("setIsAdmin", Boolean.TYPE).invoke(member, true);
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getHiveRoleGrant", RangerRole.class, roleMemberCls, String.class);
+        m.setAccessible(true);
+        Object grant = m.invoke(authorizer, role, member, HivePrincipal.HivePrincipalType.USER.name());
+
+        assertInstanceOf(HiveRoleGrant.class, grant);
+        HiveRoleGrant g = (HiveRoleGrant) grant;
+        assertEquals("roleA", g.getRoleName());
+        assertTrue(g.isGrantOption());
+        assertEquals("creator1", g.getGrantor());
+        assertEquals(HivePrincipal.HivePrincipalType.USER.name(), g.getGrantorType());
+        assertEquals("user1", g.getPrincipalName());
+        assertEquals(HivePrincipal.HivePrincipalType.USER.name(), g.getPrincipalType());
+        assertTrue(g.getGrantTime() > 0);
+    }
+
+    @Test
+    public void test32_getRangerRoleForRoleName_findsAndMissing() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        setStaticHivePlugin(pluginSpy);
+
+        RangerRoles     rr      = new RangerRoles();
+        Set<RangerRole> roleSet = new HashSet<>();
+        RangerRole      r1      = new RangerRole();
+        r1.setName("roleX");
+        RangerRole r2 = new RangerRole();
+        r2.setName("roleY");
+        roleSet.add(r1);
+        roleSet.add(r2);
+        rr.setRangerRoles(roleSet);
+        Mockito.doReturn(rr).when(pluginSpy).getRangerRoles();
+
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getRangerRoleForRoleName", String.class);
+        m.setAccessible(true);
+        Object found = m.invoke(authorizer, "roleX");
+        assertInstanceOf(RangerRole.class, found);
+        assertEquals("roleX", ((RangerRole) found).getName());
+
+        Object missing = m.invoke(authorizer, "nope");
+        assertNull(missing);
+    }
+
+    @Test
+    public void test33_buildRequestForAlterTableSetOwnerFromCommandString_parses() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        HiveAuthzContext     ctx        = Mockito.mock(HiveAuthzContext.class);
+        Mockito.when(ctx.getCommandString()).thenReturn("ALTER TABLE db1.tbl1 SET OWNER USER alice");
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod(
+                "buildRequestForAlterTableSetOwnerFromCommandString",
+                String.class, Set.class, Set.class, String.class, HiveAuthzContext.class, HiveAuthzSessionContext.class);
+        m.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        Object req = m.invoke(authorizer, "bob", new HashSet<>(), new HashSet<>(), "ALTERTABLE_OWNER", ctx, null);
+
+        assertInstanceOf(RangerHiveAccessRequest.class, req);
+        RangerHiveAccessRequest r = (RangerHiveAccessRequest) req;
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.ALTER, r.getHiveAccessType());
+        RangerHiveResource res = (RangerHiveResource) r.getResource();
+        assertEquals("db1", res.getDatabase());
+        assertEquals("tbl1", res.getTable());
+    }
+
+    @Test
+    public void test34_getColumnType_fromMetastore() throws Exception {
+        HivePrivilegeObject hiveObj = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(hiveObj.getType()).thenReturn(HivePrivilegeObjectType.TABLE_OR_VIEW);
+        Mockito.when(hiveObj.getDbname()).thenReturn("db1");
+        Mockito.when(hiveObj.getObjectName()).thenReturn("t1");
+
+        IMetaStoreClient  ms    = Mockito.mock(IMetaStoreClient.class);
+        Table             table = Mockito.mock(Table.class);
+        StorageDescriptor sd    = Mockito.mock(StorageDescriptor.class);
+        Mockito.when(table.getSd()).thenReturn(sd);
+        Mockito.when(sd.getCols()).thenReturn(Arrays.asList(new FieldSchema("c1", "int", null), new FieldSchema("c2", "string", null)));
+        Mockito.when(ms.getTable("db1", "t1")).thenReturn(table);
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getColumnType", HivePrivilegeObject.class, String.class, IMetaStoreClient.class);
+        m.setAccessible(true);
+        Object type = m.invoke(null, hiveObj, "c2", ms);
+        assertEquals("string", type);
+    }
+
+    @Test
+    public void test35_getMetaStoreClient_successAndException() throws Exception {
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+
+        HiveMetastoreClientFactory factory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           client  = Mockito.mock(IMetaStoreClient.class);
+        Mockito.doReturn(client).when(factory).getHiveMetastoreClient();
+        Mockito.doReturn(factory).when(authorizer).getMetastoreClientFactory();
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getMetaStoreClient");
+        m.setAccessible(true);
+        Object ret = m.invoke(authorizer);
+        assertNotNull(ret);
+
+        HiveMetastoreClientFactory badFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        Mockito.doThrow(new HiveAuthzPluginException("x")).when(badFactory).getHiveMetastoreClient();
+        Mockito.doReturn(badFactory).when(authorizer).getMetastoreClientFactory();
+        Object ret2 = m.invoke(authorizer);
+        assertNull(ret2);
+    }
+
+    @Test
+    public void test36_setCurrentRoleAllLoadsRoles() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(new HashSet<>(Arrays.asList("role1", "admin"))).when(pluginSpy)
+                .getRolesFromUserAndGroups(Mockito.eq("bob"), Mockito.anySet());
+
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        setStaticHivePlugin(pluginSpy);
+
+        UserGroupInformation ugi = Mockito.mock(UserGroupInformation.class);
+        Mockito.doReturn("bob").when(ugi).getShortUserName();
+        Mockito.doReturn(new String[] {"g1"}).when(ugi).getGroupNames();
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        HiveAuthenticationProvider auth = Mockito.mock(HiveAuthenticationProvider.class);
+        Mockito.doReturn("bob").when(auth).getUserName();
+        Mockito.doReturn(auth).when(authorizer).getHiveAuthenticator();
+
+        Field fUser = RangerHiveAuthorizer.class.getDeclaredField("currentUserName");
+        fUser.setAccessible(true);
+        fUser.set(authorizer, "bob");
+
+        Field fRoles = RangerHiveAuthorizer.class.getDeclaredField("currentRoles");
+        fRoles.setAccessible(true);
+        fRoles.set(authorizer, new HashSet<String>());
+        Field fFlag = RangerHiveAuthorizer.class.getDeclaredField("isCurrentRoleSet");
+        fFlag.setAccessible(true);
+
+        authorizer.setCurrentRole("ALL");
+        @SuppressWarnings("unchecked")
+        Set<String> roles = (Set<String>) fRoles.get(authorizer);
+        assertTrue(roles.contains("role1"));
+        assertFalse(roles.contains("admin"));
+        assertTrue((Boolean) fFlag.get(authorizer));
+    }
+
+    @Test
+    public void test37_setCurrentRoleSpecificMembership() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(new HashSet<>(Collections.singletonList("role2"))).when(pluginSpy)
+                .getRolesFromUserAndGroups(Mockito.eq("bob"), Mockito.anySet());
+
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        setStaticHivePlugin(pluginSpy);
+
+        UserGroupInformation ugi = Mockito.mock(UserGroupInformation.class);
+        Mockito.doReturn("bob").when(ugi).getShortUserName();
+        Mockito.doReturn(new String[] {"g1"}).when(ugi).getGroupNames();
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        HiveAuthenticationProvider auth = Mockito.mock(HiveAuthenticationProvider.class);
+        Mockito.doReturn("bob").when(auth).getUserName();
+        Mockito.doReturn(auth).when(authorizer).getHiveAuthenticator();
+
+        Field fUser = RangerHiveAuthorizer.class.getDeclaredField("currentUserName");
+        fUser.setAccessible(true);
+        fUser.set(authorizer, "bob");
+
+        Field fRoles = RangerHiveAuthorizer.class.getDeclaredField("currentRoles");
+        fRoles.setAccessible(true);
+        fRoles.set(authorizer, new HashSet<String>());
+        Field fFlag = RangerHiveAuthorizer.class.getDeclaredField("isCurrentRoleSet");
+        fFlag.setAccessible(true);
+
+        authorizer.setCurrentRole("role2");
+        @SuppressWarnings("unchecked")
+        Set<String> roles = (Set<String>) fRoles.get(authorizer);
+        assertTrue(roles.contains("role2"));
+        assertEquals(1, roles.size());
+        assertTrue((Boolean) fFlag.get(authorizer));
+    }
+
+    @Test
+    public void test38_setCurrentRoleNonMemberThrows() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        Mockito.doReturn(new HashSet<>(Collections.singletonList("roleA"))).when(pluginSpy)
+                .getRolesFromUserAndGroups(Mockito.eq("bob"), Mockito.anySet());
+
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        setStaticHivePlugin(pluginSpy);
+
+        UserGroupInformation ugi = Mockito.mock(UserGroupInformation.class);
+        Mockito.doReturn("bob").when(ugi).getShortUserName();
+        Mockito.doReturn(new String[] {"g1"}).when(ugi).getGroupNames();
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        HiveAuthenticationProvider auth = Mockito.mock(HiveAuthenticationProvider.class);
+        Mockito.doReturn("bob").when(auth).getUserName();
+        Mockito.doReturn(auth).when(authorizer).getHiveAuthenticator();
+
+        Field fUser = RangerHiveAuthorizer.class.getDeclaredField("currentUserName");
+        fUser.setAccessible(true);
+        fUser.set(authorizer, "bob");
+        Field fRoles = RangerHiveAuthorizer.class.getDeclaredField("currentRoles");
+        fRoles.setAccessible(true);
+        fRoles.set(authorizer, new HashSet<String>());
+
+        assertThrows(HiveAuthzPluginException.class, () -> authorizer.setCurrentRole("roleB"));
+    }
+
+    @Test
+    public void test39_getCurrentRoleNames_happyPath() throws Exception {
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = Mockito.mock(UserGroupInformation.class);
+        Mockito.doReturn("carol").when(ugi).getShortUserName();
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        RangerBasePlugin plugin = (RangerBasePlugin) newInstanceRangerHivePlugin("hiveCLI");
+        setStaticHivePlugin(plugin);
+
+        Field fRoles = RangerHiveAuthorizer.class.getDeclaredField("currentRoles");
+        fRoles.setAccessible(true);
+        Set<String> roles = new HashSet<>();
+        roles.add("r1");
+        roles.add("r2");
+        fRoles.set(authorizer, roles);
+        Field fFlag = RangerHiveAuthorizer.class.getDeclaredField("isCurrentRoleSet");
+        fFlag.setAccessible(true);
+        fFlag.set(authorizer, true);
+
+        List<String> ret = authorizer.getCurrentRoleNames();
+        assertTrue(ret.contains("r1"));
+        assertTrue(ret.contains("r2"));
+    }
+
+    @Test
+    public void test40_getCurrentRoleNames_ugiNullThrows() throws Exception {
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        Mockito.doReturn(null).when(authorizer).getCurrentUserGroupInfo();
+        assertThrows(HiveAuthzPluginException.class, authorizer::getCurrentRoleNames);
+    }
+
+    @Test
+    public void test41_hiveObj_fetchHiveObj_parsesDbAndTable() throws Exception {
+        Class<?>         hiveObjCls = Class.forName("org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer$HiveObj");
+        Object           hiveObj    = hiveObjCls.getDeclaredConstructor().newInstance();
+        HiveAuthzContext ctx        = Mockito.mock(HiveAuthzContext.class);
+        Mockito.when(ctx.getCommandString()).thenReturn("OP X db1.tbl2 tail");
+
+        Method m = hiveObjCls.getDeclaredMethod("fetchHiveObj", HiveAuthzContext.class);
+        m.setAccessible(true);
+        m.invoke(hiveObj, ctx);
+
+        Method getDb  = hiveObjCls.getDeclaredMethod("getDatabaseName");
+        Method getTbl = hiveObjCls.getDeclaredMethod("getTableName");
+        assertEquals("db1", getDb.invoke(hiveObj));
+        assertEquals("tbl2", getTbl.invoke(hiveObj));
+    }
+
+    @Test
+    public void test42_hiveObj_fetchHiveObj_onlyDb() throws Exception {
+        Class<?>         hiveObjCls = Class.forName("org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer$HiveObj");
+        Object           hiveObj    = hiveObjCls.getDeclaredConstructor().newInstance();
+        HiveAuthzContext ctx        = Mockito.mock(HiveAuthzContext.class);
+        Mockito.when(ctx.getCommandString()).thenReturn("OP X dbonly tail");
+
+        Method m = hiveObjCls.getDeclaredMethod("fetchHiveObj", HiveAuthzContext.class);
+        m.setAccessible(true);
+        m.invoke(hiveObj, ctx);
+
+        Method getDb  = hiveObjCls.getDeclaredMethod("getDatabaseName");
+        Method getTbl = hiveObjCls.getDeclaredMethod("getTableName");
+        assertEquals("dbonly", getDb.invoke(hiveObj));
+        assertNull(getTbl.invoke(hiveObj));
+    }
+
+    @Test
+    public void test43_getDataMaskAndRowFilterResult_delegatesToPlugin() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        setStaticHivePlugin(pluginSpy);
+
+        RangerHiveAuthorizer    authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        RangerHiveResource      resource   = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.TABLE, "db", "t");
+        RangerHiveAccessRequest req        = new RangerHiveAccessRequest(resource, "u", new HashSet<>(), new HashSet<>(), "QUERY", RangerHiveAuthorizer.HiveAccessType.SELECT, null, null);
+
+        RangerAccessResult dm = Mockito.mock(RangerAccessResult.class);
+        RangerAccessResult rf = Mockito.mock(RangerAccessResult.class);
+        Mockito.doReturn(dm).when(pluginSpy).evalDataMaskPolicies(Mockito.eq(req), Mockito.isNull());
+        Mockito.doReturn(rf).when(pluginSpy).evalRowFilterPolicies(Mockito.eq(req), Mockito.isNull());
+
+        Method m1 = RangerHiveAuthorizer.class.getDeclaredMethod("getDataMaskResult", RangerHiveAccessRequest.class);
+        m1.setAccessible(true);
+        Method m2 = RangerHiveAuthorizer.class.getDeclaredMethod("getRowFilterResult", RangerHiveAccessRequest.class);
+        m2.setAccessible(true);
+
+        assertEquals(dm, m1.invoke(authorizer, req));
+        assertEquals(rf, m2.invoke(authorizer, req));
+    }
+
+    @Test
+    public void test44_isDataMaskEnabled_handlesNullAndTrue() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("isDataMaskEnabled", RangerAccessResult.class);
+        m.setAccessible(true);
+        assertFalse((Boolean) m.invoke(authorizer, new Object[] {null}));
+        RangerAccessResult res = Mockito.mock(RangerAccessResult.class);
+        Mockito.when(res.isMaskEnabled()).thenReturn(true);
+        assertTrue((Boolean) m.invoke(authorizer, res));
+    }
+
+    @Test
+    public void test45_addCellValueTransformer_maskNullAndCustomType() throws Exception {
+        RangerBasePlugin pluginSpy = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        setStaticHivePlugin(pluginSpy);
+
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        UserGroupInformation ugi        = Mockito.mock(UserGroupInformation.class);
+        Mockito.doReturn("alice").when(ugi).getShortUserName();
+        Mockito.doReturn(new String[] {"g"}).when(ugi).getGroupNames();
+        Mockito.doReturn(ugi).when(authorizer).getCurrentUserGroupInfo();
+
+        HivePrivilegeObject table = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(table.getType()).thenReturn(HivePrivilegeObjectType.TABLE_OR_VIEW);
+        Mockito.when(table.getDbname()).thenReturn("db1");
+        Mockito.when(table.getObjectName()).thenReturn("t1");
+
+        // First: MASK_TYPE_NULL
+        RangerAccessResult dmNull = Mockito.mock(RangerAccessResult.class);
+        Mockito.when(dmNull.isMaskEnabled()).thenReturn(true);
+        Mockito.when(dmNull.getMaskType()).thenReturn(RangerPolicy.MASK_TYPE_NULL);
+        Mockito.when(dmNull.getMaskTypeDef()).thenReturn(null);
+        Mockito.doReturn(dmNull).when(pluginSpy).evalDataMaskPolicies(Mockito.any(), Mockito.any());
+
+        List<String>     transformers = new ArrayList<>();
+        IMetaStoreClient ms           = Mockito.mock(IMetaStoreClient.class);
+        Map<String, String> owners       = new HashMap<>();
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod(
+                "addCellValueTransformerAndCheckIfTransformed",
+                HiveAuthzContext.class, HivePrivilegeObject.class, String.class, List.class, IMetaStoreClient.class, Map.class);
+        m.setAccessible(true);
+        boolean enabled = (Boolean) m.invoke(authorizer, null, table, "c1", transformers, ms, owners);
+        assertTrue(enabled);
+        assertEquals("NULL", transformers.get(0));
+
+        // Second: custom masked value with {colType}
+        RangerAccessResult dmTx = Mockito.mock(RangerAccessResult.class);
+        Mockito.when(dmTx.isMaskEnabled()).thenReturn(true);
+        Mockito.when(dmTx.getMaskType()).thenReturn(RangerPolicy.MASK_TYPE_CUSTOM);
+        Mockito.when(dmTx.getMaskedValue()).thenReturn("cast({col} as {colType})");
+        Mockito.when(dmTx.getMaskTypeDef()).thenReturn(null);
+        Mockito.doReturn(dmTx).when(pluginSpy).evalDataMaskPolicies(Mockito.any(), Mockito.any());
+
+        // stub column type
+        Table             hiveTable = Mockito.mock(Table.class);
+        StorageDescriptor sd        = Mockito.mock(StorageDescriptor.class);
+        Mockito.when(hiveTable.getSd()).thenReturn(sd);
+        Mockito.when(sd.getCols()).thenReturn(Collections.singletonList(new FieldSchema("c1", "int", null)));
+        Mockito.when(ms.getTable("db1", "t1")).thenReturn(hiveTable);
+
+        List<String> transformers2 = new ArrayList<>();
+        boolean      enabled2      = (Boolean) m.invoke(authorizer, null, table, "c1", transformers2, ms, owners);
+        assertTrue(enabled2);
+        assertEquals("cast(c1 as int)", transformers2.get(0));
+    }
+
+    @Test
+    public void test46_getHiveResource_databaseCreateNoOwnerLookup() throws Exception {
+        RangerHiveAuthorizer       authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        HiveMetastoreClientFactory factory    = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           ms         = Mockito.mock(IMetaStoreClient.class);
+        Mockito.doReturn(ms).when(factory).getHiveMetastoreClient();
+        Mockito.doReturn(factory).when(authorizer).getMetastoreClientFactory();
+        HivePrivilegeObject hiveObj = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(hiveObj.getType()).thenReturn(HivePrivilegeObjectType.DATABASE);
+        Mockito.when(hiveObj.getDbname()).thenReturn("db1");
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getHiveResource", HiveOperationType.class, HivePrivilegeObject.class, List.class, List.class, Map.class);
+        m.setAccessible(true);
+        Object res = m.invoke(authorizer, HiveOperationType.CREATEDATABASE, hiveObj, Collections.emptyList(), Collections.emptyList(), new HashMap<>());
+        assertInstanceOf(RangerHiveResource.class, res);
+        RangerHiveResource r = (RangerHiveResource) res;
+        assertEquals(RangerHiveAuthorizer.HiveObjectType.DATABASE, r.getObjectType());
+        assertEquals("db1", r.getDatabase());
+    }
+
+    @Test
+    public void test47_isCreateOperation_trueAndFalse() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("isCreateOperation", HiveOperationType.class);
+        m.setAccessible(true);
+        assertTrue((Boolean) m.invoke(authorizer, HiveOperationType.CREATETABLE));
+        assertFalse((Boolean) m.invoke(authorizer, HiveOperationType.DROPTABLE));
+    }
+
+    @Test
+    public void test48_getDatabaseObject_outputsThenInputs() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        HivePrivilegeObject  outDb      = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(outDb.getType()).thenReturn(HivePrivilegeObjectType.DATABASE);
+        Mockito.when(outDb.getDbname()).thenReturn("db1");
+        HivePrivilegeObject inDb = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(inDb.getType()).thenReturn(HivePrivilegeObjectType.DATABASE);
+        Mockito.when(inDb.getDbname()).thenReturn("db1");
+
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getDatabaseObject", String.class, List.class, List.class);
+        m.setAccessible(true);
+        Object res1 = m.invoke(authorizer, "db1", Collections.singletonList(inDb), Collections.singletonList(outDb));
+        assertEquals(outDb, res1);
+        Object res2 = m.invoke(authorizer, "db1", Collections.singletonList(inDb), Collections.emptyList());
+        assertEquals(inDb, res2);
+    }
+
+    @Test
+    public void test49_getObjectType_mappings() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getObjectType", HivePrivilegeObject.class, HiveOperationType.class);
+        m.setAccessible(true);
+
+        HivePrivilegeObject db = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(db.getType()).thenReturn(HivePrivilegeObjectType.DATABASE);
+        assertEquals(RangerHiveAuthorizer.HiveObjectType.DATABASE, m.invoke(authorizer, db, HiveOperationType.QUERY));
+
+        HivePrivilegeObject part = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(part.getType()).thenReturn(HivePrivilegeObjectType.PARTITION);
+        assertEquals(RangerHiveAuthorizer.HiveObjectType.PARTITION, m.invoke(authorizer, part, HiveOperationType.QUERY));
+
+        HivePrivilegeObject tableWithCols = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(tableWithCols.getType()).thenReturn(HivePrivilegeObjectType.TABLE_OR_VIEW);
+        Mockito.when(tableWithCols.getColumns()).thenReturn(Collections.singletonList("c1"));
+        assertEquals(RangerHiveAuthorizer.HiveObjectType.COLUMN, m.invoke(authorizer, tableWithCols, HiveOperationType.QUERY));
+
+        HivePrivilegeObject view = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(view.getType()).thenReturn(HivePrivilegeObjectType.TABLE_OR_VIEW);
+        Mockito.when(view.getColumns()).thenReturn(null);
+        assertEquals(RangerHiveAuthorizer.HiveObjectType.VIEW, m.invoke(authorizer, view, HiveOperationType.CREATEVIEW));
+
+        HivePrivilegeObject uri = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(uri.getType()).thenReturn(HivePrivilegeObjectType.DFS_URI);
+        assertEquals(RangerHiveAuthorizer.HiveObjectType.URI, m.invoke(authorizer, uri, HiveOperationType.QUERY));
+    }
+
+    @Test
+    public void test50_isURIAccessAllowed_actionNoneShortCircuits() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("isURIAccessAllowed", String.class, FsAction.class, Path.class, FileSystem.class);
+        m.setAccessible(true);
+        boolean ret = (Boolean) m.invoke(authorizer, "user", FsAction.NONE, new Path("/a"), null);
+        assertTrue(ret);
+    }
+
+    @Test
+    public void test51_resolvePath_successAndException() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        FileSystem           fs         = Mockito.mock(FileSystem.class);
+        Path                 p          = new Path("/x");
+        Path                 resolved   = new Path("/y");
+        Mockito.when(fs.resolvePath(p)).thenReturn(resolved);
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("resolvePath", Path.class, FileSystem.class);
+        m.setAccessible(true);
+        assertEquals(resolved, m.invoke(authorizer, p, fs));
+        Mockito.when(fs.resolvePath(p)).thenThrow(new IOException("x"));
+        assertNull(m.invoke(authorizer, p, fs));
+    }
+
+    @Test
+    public void test52_isMountedFs_trueWhenChildrenPresent() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        FileSystem           fs         = Mockito.mock(FileSystem.class);
+        FileSystem[]         children   = new FileSystem[] {Mockito.mock(FileSystem.class)};
+        Mockito.when(fs.getChildFileSystems()).thenReturn(children);
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod("isMountedFs", FileSystem.class);
+        m.setAccessible(true);
+        assertTrue((Boolean) m.invoke(authorizer, fs));
+        Mockito.when(fs.getChildFileSystems()).thenReturn(null);
+        assertFalse((Boolean) m.invoke(authorizer, fs));
+    }
+
+    @Test
+    public void test53_existsByResourceAndAccessType() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("existsByResourceAndAccessType", Collection.class, RangerHiveResource.class, RangerHiveAuthorizer.HiveAccessType.class);
+        m.setAccessible(true);
+        RangerHiveResource                      r1      = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.TABLE, "db", "t");
+        RangerHiveAccessRequest                 request = new RangerHiveAccessRequest(r1, "u", new HashSet<>(), new HashSet<>(), "QUERY", RangerHiveAuthorizer.HiveAccessType.SELECT, null, null);
+        List<RangerHiveAccessRequest> list    = new ArrayList<>();
+        list.add(request);
+        assertTrue((Boolean) m.invoke(authorizer, list, r1, RangerHiveAuthorizer.HiveAccessType.SELECT));
+        RangerHiveResource r2 = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.TABLE, "db", "t2");
+        assertFalse((Boolean) m.invoke(authorizer, list, r2, RangerHiveAuthorizer.HiveAccessType.SELECT));
+    }
+
+    @Test
+    public void test54_getAccessType_uriReadWrite() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getAccessType", HivePrivilegeObject.class, HiveOperationType.class, RangerHiveAuthorizer.HiveObjectType.class, boolean.class);
+        m.setAccessible(true);
+        HivePrivilegeObject uriObj = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(uriObj.getActionType()).thenReturn(HivePrivObjectActionType.OTHER);
+        Object read  = m.invoke(authorizer, uriObj, HiveOperationType.QUERY, RangerHiveAuthorizer.HiveObjectType.URI, true);
+        Object write = m.invoke(authorizer, uriObj, HiveOperationType.QUERY, RangerHiveAuthorizer.HiveObjectType.URI, false);
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.READ, read);
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.WRITE, write);
+    }
+
+    @Test
+    public void test56_getAccessType_otherMappingsVarious() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getAccessType", HivePrivilegeObject.class, HiveOperationType.class, RangerHiveAuthorizer.HiveObjectType.class, boolean.class);
+        m.setAccessible(true);
+        HivePrivilegeObject dbObj = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(dbObj.getActionType()).thenReturn(HivePrivObjectActionType.OTHER);
+        Mockito.when(dbObj.getType()).thenReturn(HivePrivilegeObjectType.DATABASE);
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.CREATE, m.invoke(authorizer, dbObj, HiveOperationType.CREATEDATABASE, RangerHiveAuthorizer.HiveObjectType.DATABASE, false));
+        HivePrivilegeObject funcObj = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(funcObj.getActionType()).thenReturn(HivePrivObjectActionType.OTHER);
+        Mockito.when(funcObj.getType()).thenReturn(HivePrivilegeObjectType.FUNCTION);
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.CREATE, m.invoke(authorizer, funcObj, HiveOperationType.CREATEFUNCTION, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // CREATE VIEW/TABLE: input -> SELECT, output -> CREATE
+        HivePrivilegeObject tblObj = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(tblObj.getActionType()).thenReturn(HivePrivObjectActionType.OTHER);
+        Mockito.when(tblObj.getType()).thenReturn(HivePrivilegeObjectType.TABLE_OR_VIEW);
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.SELECT, m.invoke(authorizer, tblObj, HiveOperationType.CREATETABLE, RangerHiveAuthorizer.HiveObjectType.TABLE, true));
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.CREATE, m.invoke(authorizer, tblObj, HiveOperationType.CREATETABLE, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // ALTERVIEW_AS: input table -> SELECT; output -> ALTER
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.SELECT, m.invoke(authorizer, tblObj, HiveOperationType.ALTERVIEW_AS, RangerHiveAuthorizer.HiveObjectType.TABLE, true));
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.ALTER, m.invoke(authorizer, tblObj, HiveOperationType.ALTERVIEW_AS, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // ALTER operations map to ALTER
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.ALTER, m.invoke(authorizer, tblObj, HiveOperationType.ALTERTABLE_ADDCOLS, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // DROP operations map to DROP
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.DROP, m.invoke(authorizer, tblObj, HiveOperationType.DROPTABLE, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // IMPORT input -> SELECT, output -> CREATE
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.SELECT, m.invoke(authorizer, tblObj, HiveOperationType.IMPORT, RangerHiveAuthorizer.HiveObjectType.TABLE, true));
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.CREATE, m.invoke(authorizer, tblObj, HiveOperationType.IMPORT, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // EXPORT/LOAD: input -> SELECT; output -> UPDATE
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.SELECT, m.invoke(authorizer, tblObj, HiveOperationType.EXPORT, RangerHiveAuthorizer.HiveObjectType.TABLE, true));
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.UPDATE, m.invoke(authorizer, tblObj, HiveOperationType.EXPORT, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // LOCK
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.LOCK, m.invoke(authorizer, tblObj, HiveOperationType.LOCKTABLE, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // Metadata SELECT
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.SELECT, m.invoke(authorizer, tblObj, HiveOperationType.SHOW_TBLPROPERTIES, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // USE
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.USE, m.invoke(authorizer, tblObj, HiveOperationType.SHOWDATABASES, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // TRUNCATE -> UPDATE
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.UPDATE, m.invoke(authorizer, tblObj, HiveOperationType.TRUNCATETABLE, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // GRANT/REVOKE_PRIVILEGE -> NONE
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.NONE, m.invoke(authorizer, tblObj, HiveOperationType.GRANT_PRIVILEGE, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // REPL* -> REPLADMIN
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.REPLADMIN, m.invoke(authorizer, tblObj, HiveOperationType.REPLDUMP, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // SERVICEADMIN
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.SERVICEADMIN, m.invoke(authorizer, tblObj, HiveOperationType.KILL_QUERY, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+        // TEMPUDFADMIN
+        assertEquals(RangerHiveAuthorizer.HiveAccessType.TEMPUDFADMIN, m.invoke(authorizer, tblObj, HiveOperationType.COMPILE, RangerHiveAuthorizer.HiveObjectType.TABLE, false));
+    }
+
+    @Test
+    public void test57_isPathInFSScheme_trueFalse() throws Exception {
+        Object pluginObj = newInstanceRangerHivePlugin("hiveCLI");
+        setStaticHivePlugin((RangerBasePlugin) pluginObj);
+        Field fsField = pluginObj.getClass().getDeclaredField("fsScheme");
+        fsField.setAccessible(true);
+        fsField.set(pluginObj, new String[] {"hdfs://", "file://"});
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("isPathInFSScheme", String.class);
+        m.setAccessible(true);
+        assertTrue((Boolean) m.invoke(authorizer, "hdfs://nn/tmp"));
+        assertFalse((Boolean) m.invoke(authorizer, "s3a://bucket"));
+    }
+
+    @Test
+    public void test58_createGrantRevokeData_buildsRequest() throws Exception {
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(null, null, null, null));
+        RangerHiveResource   res        = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.TABLE, "db1", "t1");
+        List<HivePrincipal>  principals = Arrays.asList(new HivePrincipal("alice", HivePrincipal.HivePrincipalType.USER), new HivePrincipal("dev", HivePrincipal.HivePrincipalType.GROUP));
+        HivePrivilege        p1         = Mockito.mock(HivePrivilege.class);
+        Mockito.when(p1.getName()).thenReturn("select");
+        HivePrivilege p2 = Mockito.mock(HivePrivilege.class);
+        Mockito.when(p2.getName()).thenReturn("Insert");
+        List<HivePrivilege> privs = Arrays.asList(p1, p2);
+        Method              m     = RangerHiveAuthorizer.class.getDeclaredMethod("createGrantRevokeData", RangerHiveResource.class, List.class, List.class, HivePrincipal.class, boolean.class);
+        m.setAccessible(true);
+        Object out = m.invoke(authorizer, res, principals, privs, principals.get(0), true);
+        assertInstanceOf(GrantRevokeRequest.class, out);
+        GrantRevokeRequest req = (GrantRevokeRequest) out;
+        assertEquals("db1", req.getResource().get("database"));
+        assertEquals("t1", req.getResource().get("table"));
+        assertTrue(req.getUsers().contains("alice"));
+        assertTrue(req.getGroups().contains("dev"));
+        assertTrue(req.getAccessTypes().contains("select"));
+        assertTrue(req.getAccessTypes().contains("update"));
+    }
+
+    @Test
+    public void test59_getPluginPrivilegeObjType_mappingsAndAssertion() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getPluginPrivilegeObjType", HiveObjectType.class);
+        m.setAccessible(true);
+        assertThrows(AssertionError.class, () -> {
+            try {
+                m.invoke(authorizer, HiveObjectType.PARTITION);
+            } catch (Exception e) {
+                if (e.getCause() instanceof AssertionError) {
+                    throw e.getCause();
+                }
+                throw new RuntimeException(e);
+            }
+        });
+    }
+
+    @Test
+    public void test60_isTempUDFOperation_trueAndFalse() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("isTempUDFOperation", String.class, HivePrivilegeObject.class);
+        m.setAccessible(true);
+
+        HivePrivilegeObject objNoDb = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(objNoDb.getDbname()).thenReturn("");
+        assertTrue((Boolean) m.invoke(authorizer, "createfunction", objNoDb));
+        assertTrue((Boolean) m.invoke(authorizer, "dropfunction", objNoDb));
+
+        HivePrivilegeObject objWithDb = Mockito.mock(HivePrivilegeObject.class);
+        Mockito.when(objWithDb.getDbname()).thenReturn("db1");
+        assertFalse((Boolean) m.invoke(authorizer, "createfunction", objWithDb));
+        assertFalse((Boolean) m.invoke(authorizer, "otherop", objNoDb));
+    }
+
+    @Test
+    public void test61_convertRangerACLsToHiveACLs_mapsValues() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("convertRangerACLsToHiveACLs", Map.class);
+        m.setAccessible(true);
+
+        Map<String, Map<String, RangerResourceACLs.AccessResult>> input = new HashMap<>();
+        Map<String, RangerResourceACLs.AccessResult>                                                    alice = new HashMap<>();
+        alice.put("select", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_ALLOWED, null));
+        alice.put("update", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_DENIED, null));
+        alice.put("drop", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_CONDITIONAL, null));
+        input.put("alice", alice);
+
+        @SuppressWarnings("unchecked")
+        Map<String, Map<Privilege, AccessResult>> out = (Map<String, Map<Privilege, AccessResult>>) m.invoke(authorizer, input);
+        assertNotNull(out);
+        Map<Privilege, AccessResult> perms = out.get("alice");
+        assertEquals(AccessResult.ALLOWED, perms.get(Privilege.SELECT));
+        assertEquals(AccessResult.NOT_ALLOWED, perms.get(Privilege.UPDATE));
+        assertEquals(AccessResult.CONDITIONAL_ALLOWED, perms.get(Privilege.DROP));
+    }
+
+    @Test
+    public void test62_getPermission_variants() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               mCheck     = RangerHiveAuthorizer.class.getDeclaredMethod("checkACLIsAllowed", Privilege.class, Map.class);
+        Method               mPerm      = RangerHiveAuthorizer.class.getDeclaredMethod("getPermission", Privilege.class, Map.class, RangerPolicy.class);
+        mCheck.setAccessible(true);
+        mPerm.setAccessible(true);
+
+        Map<String, RangerResourceACLs.AccessResult> map = new HashMap<>();
+        map.put("select", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_ALLOWED, null));
+        map.put("update", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_UNDETERMINED, null));
+        map.put("drop", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_CONDITIONAL, null));
+
+        RangerPolicy policy = new RangerPolicy();
+
+        assertEquals(RangerPolicyEvaluator.ACCESS_ALLOWED, mCheck.invoke(authorizer, Privilege.SELECT, map));
+        String p1 = (String) mPerm.invoke(authorizer, Privilege.SELECT, map, policy);
+        assertEquals("SELECT", p1);
+
+        assertEquals(RangerPolicyEvaluator.ACCESS_UNDETERMINED, mCheck.invoke(authorizer, Privilege.UPDATE, map));
+        String p2 = (String) mPerm.invoke(authorizer, Privilege.UPDATE, map, policy);
+        assertTrue(p2.contains("ACCESS_UNDETERMINED"));
+
+        assertEquals(RangerPolicyEvaluator.ACCESS_CONDITIONAL, mCheck.invoke(authorizer, Privilege.DROP, map));
+        String p3 = (String) mPerm.invoke(authorizer, Privilege.DROP, map, policy);
+        assertTrue(p3.contains("ACCESS_CONDITIONAL"));
+    }
+
+    @Test
+    public void test63_getRangerPolicy_returnsPolicyWhenPresent() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getRangerPolicy", Map.class, String.class);
+        m.setAccessible(true);
+
+        Map<String, RangerResourceACLs.AccessResult> access = new HashMap<>();
+        RangerPolicy                                 policy = new RangerPolicy();
+        policy.setName("p1");
+        access.put("select", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_ALLOWED, policy));
+
+        Object out = m.invoke(authorizer, access, "SELECT");
+        assertInstanceOf(RangerPolicy.class, out);
+        assertEquals("p1", ((RangerPolicy) out).getName());
+    }
+
+    @Test
+    public void test64_createHivePrivilegeInfo_buildsFieldsFromPolicy() throws Exception {
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        Method m = RangerHiveAuthorizer.class.getDeclaredMethod(
+                "createHivePrivilegeInfo",
+                HivePrincipal.class,
+                HivePrivilegeObject.HivePrivilegeObjectType.class,
+                String.class,
+                String.class,
+                String.class,
+                List.class,
+                String.class,
+                RangerPolicy.class);
+        m.setAccessible(true);
+
+        RangerPolicy policy = new RangerPolicy();
+        policy.setCreateTime(new Date(4000));
+        RangerPolicy.RangerPolicyItem item   = new RangerPolicy.RangerPolicyItem();
+        RangerPolicyItemAccess        access = new RangerPolicyItemAccess();
+        access.setType("select");
+        item.setAccesses(Collections.singletonList(access));
+        item.setUsers(Collections.singletonList("alice"));
+        item.setDelegateAdmin(true);
+        policy.setPolicyItems(Collections.singletonList(item));
+
+        HivePrincipal principal = new HivePrincipal("alice", HivePrincipal.HivePrincipalType.USER);
+        Object        out       = m.invoke(authorizer, principal, HivePrivilegeObject.HivePrivilegeObjectType.TABLE_OR_VIEW, "db1", "t1", "", Collections.emptyList(), "SELECT", policy);
+        assertInstanceOf(HivePrivilegeInfo.class, out);
+        HivePrivilegeInfo info = (HivePrivilegeInfo) out;
+        assertEquals("alice", info.getPrincipal().getName());
+        assertEquals("ranger", info.getGrantorPrincipal().getName());
+        assertTrue(info.isGrantOption());
+        assertTrue(info.getGrantTime() > 0);
+    }
+
+    @Test
+    public void test65_getRangerResourceACLs_delegatesToPlugin() throws Exception {
+        RangerBasePlugin   plugin = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        RangerResourceACLs acls   = new RangerResourceACLs();
+        Mockito.doReturn(acls).when(plugin).getResourceACLs(Mockito.any(RangerAccessRequestImpl.class));
+        setStaticHivePlugin(plugin);
+
+        HiveMetastoreClientFactory msFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           ms        = Mockito.mock(IMetaStoreClient.class);
+        Mockito.when(msFactory.getHiveMetastoreClient()).thenReturn(ms);
+
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(msFactory, null, null, null);
+        Method               m          = RangerHiveAuthorizer.class.getDeclaredMethod("getRangerResourceACLs", HivePrivilegeObject.class);
+        m.setAccessible(true);
+        HivePrivilegeObject obj = new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, "db1", "t1");
+        Object              out = m.invoke(authorizer, obj);
+        assertInstanceOf(RangerResourceACLs.class, out);
+    }
+
+    @Test
+    public void test67_getHivePrivilegeInfos_userPrincipal() throws Exception {
+        RangerBasePlugin   plugin = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        RangerResourceACLs acls   = new RangerResourceACLs();
+        RangerPolicy       pUser  = new RangerPolicy();
+        pUser.setPolicyItems(Collections.emptyList());
+        RangerPolicy pGrp = new RangerPolicy();
+        pGrp.setPolicyItems(Collections.emptyList());
+        acls.setUserAccessInfo("alice", "select", RangerPolicyEvaluator.ACCESS_ALLOWED, pUser);
+        acls.setGroupAccessInfo("dev", "update", RangerPolicyEvaluator.ACCESS_ALLOWED, pGrp);
+        Mockito.doReturn(acls).when(plugin).getResourceACLs(Mockito.any(RangerAccessRequestImpl.class));
+        setStaticHivePlugin(plugin);
+
+        HiveMetastoreClientFactory msFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           ms        = Mockito.mock(IMetaStoreClient.class);
+        Mockito.when(msFactory.getHiveMetastoreClient()).thenReturn(ms);
+        RangerHiveAuthorizer authorizer = Mockito.spy(new RangerHiveAuthorizer(msFactory, null, null, null));
+
+        // Prepare AuthorizationUtils response
+        HiveObjectRef ref = Mockito.mock(HiveObjectRef.class);
+        Mockito.when(ref.getDbName()).thenReturn("db1");
+        Mockito.when(ref.getObjectName()).thenReturn("t1");
+        Mockito.when(ref.getColumnName()).thenReturn(null);
+        Mockito.when(ref.getPartValues()).thenReturn(null);
+        Mockito.when(ref.getObjectType()).thenReturn(HiveObjectType.TABLE);
+
+        try (MockedStatic<AuthorizationUtils> stat = Mockito.mockStatic(AuthorizationUtils.class)) {
+            stat.when(() -> AuthorizationUtils.getThriftHiveObjectRef(Mockito.any(HivePrivilegeObject.class))).thenReturn(ref);
+
+            // Seed UGI with dev group
+            UserGroupInformation.setLoginUser(UserGroupInformation.createUserForTesting("alice", new String[] {"dev"}));
+
+            Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getHivePrivilegeInfos", HivePrincipal.class, HivePrivilegeObject.class);
+            m.setAccessible(true);
+
+            HivePrivilegeObject resource  = new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, "db1", "t1");
+            HivePrincipal       principal = new HivePrincipal("alice", HivePrincipal.HivePrincipalType.USER);
+
+            @SuppressWarnings("unchecked")
+            List<HivePrivilegeInfo> infos = (List<HivePrivilegeInfo>) m.invoke(authorizer, principal, resource);
+
+            assertFalse(infos.isEmpty());
+            assertTrue(infos.stream().anyMatch(i -> i.getPrivilege().getName().toLowerCase().startsWith("select")));
+            assertTrue(infos.stream().anyMatch(i -> i.getPrivilege().getName().toLowerCase().startsWith("update")));
+        }
+    }
+
+    @Test
+    public void test68_getHivePrivilegeInfos_rolePrincipal() throws Exception {
+        RangerBasePlugin   plugin = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        RangerResourceACLs acls   = new RangerResourceACLs();
+        RangerPolicy       pRole  = new RangerPolicy();
+        pRole.setPolicyItems(Collections.emptyList());
+        acls.setRoleAccessInfo("analyst", "drop", RangerPolicyEvaluator.ACCESS_ALLOWED, pRole);
+        Mockito.doReturn(acls).when(plugin).getResourceACLs(Mockito.any(RangerAccessRequestImpl.class));
+        setStaticHivePlugin(plugin);
+
+        HiveMetastoreClientFactory msFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           ms        = Mockito.mock(IMetaStoreClient.class);
+        Mockito.when(msFactory.getHiveMetastoreClient()).thenReturn(ms);
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(msFactory, null, null, null);
+
+        HiveObjectRef ref = Mockito.mock(HiveObjectRef.class);
+        Mockito.when(ref.getDbName()).thenReturn("db1");
+        Mockito.when(ref.getObjectName()).thenReturn("t1");
+        Mockito.when(ref.getColumnName()).thenReturn(null);
+        Mockito.when(ref.getPartValues()).thenReturn(null);
+        Mockito.when(ref.getObjectType()).thenReturn(HiveObjectType.TABLE);
+
+        try (MockedStatic<AuthorizationUtils> stat = Mockito.mockStatic(AuthorizationUtils.class)) {
+            stat.when(() -> AuthorizationUtils.getThriftHiveObjectRef(Mockito.any(HivePrivilegeObject.class))).thenReturn(ref);
+
+            Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getHivePrivilegeInfos", HivePrincipal.class, HivePrivilegeObject.class);
+            m.setAccessible(true);
+
+            HivePrivilegeObject resource  = new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, "db1", "t1");
+            HivePrincipal       principal = new HivePrincipal("analyst", HivePrincipal.HivePrincipalType.ROLE);
+
+            @SuppressWarnings("unchecked")
+            List<HivePrivilegeInfo> infos = (List<HivePrivilegeInfo>) m.invoke(authorizer, principal, resource);
+
+            assertFalse(infos.isEmpty());
+            assertTrue(infos.stream().anyMatch(i -> i.getPrivilege().getName().toLowerCase().startsWith("drop")));
+        }
+    }
+
+    @Test
+    public void test69_getHivePrivilegeInfos_allPrincipals() throws Exception {
+        RangerBasePlugin   plugin = (RangerBasePlugin) Mockito.spy(newInstanceRangerHivePlugin("hiveCLI"));
+        RangerResourceACLs acls   = new RangerResourceACLs();
+        RangerPolicy       pUser  = new RangerPolicy();
+        pUser.setPolicyItems(Collections.emptyList());
+        RangerPolicy pGrp = new RangerPolicy();
+        pGrp.setPolicyItems(Collections.emptyList());
+        RangerPolicy pRole = new RangerPolicy();
+        pRole.setPolicyItems(Collections.emptyList());
+        acls.setUserAccessInfo("u1", "select", RangerPolicyEvaluator.ACCESS_ALLOWED, pUser);
+        acls.setGroupAccessInfo("g1", "update", RangerPolicyEvaluator.ACCESS_ALLOWED, pGrp);
+        acls.setRoleAccessInfo("r1", "drop", RangerPolicyEvaluator.ACCESS_ALLOWED, pRole);
+        Mockito.doReturn(acls).when(plugin).getResourceACLs(Mockito.any(RangerAccessRequestImpl.class));
+        setStaticHivePlugin(plugin);
+
+        HiveMetastoreClientFactory msFactory = Mockito.mock(HiveMetastoreClientFactory.class);
+        IMetaStoreClient           ms        = Mockito.mock(IMetaStoreClient.class);
+        Mockito.when(msFactory.getHiveMetastoreClient()).thenReturn(ms);
+        RangerHiveAuthorizer authorizer = new RangerHiveAuthorizer(msFactory, null, null, null);
+
+        HiveObjectRef ref = Mockito.mock(HiveObjectRef.class);
+        Mockito.when(ref.getDbName()).thenReturn("db1");
+        Mockito.when(ref.getObjectName()).thenReturn("t1");
+        Mockito.when(ref.getColumnName()).thenReturn(null);
+        Mockito.when(ref.getPartValues()).thenReturn(null);
+        Mockito.when(ref.getObjectType()).thenReturn(HiveObjectType.TABLE);
+
+        try (MockedStatic<AuthorizationUtils> stat = Mockito.mockStatic(AuthorizationUtils.class)) {
+            stat.when(() -> AuthorizationUtils.getThriftHiveObjectRef(Mockito.any(HivePrivilegeObject.class))).thenReturn(ref);
+
+            Method m = RangerHiveAuthorizer.class.getDeclaredMethod("getHivePrivilegeInfos", HivePrincipal.class, HivePrivilegeObject.class);
+            m.setAccessible(true);
+
+            HivePrivilegeObject resource = new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, "db1", "t1");
+
+            @SuppressWarnings("unchecked")
+            List<HivePrivilegeInfo> infos = (List<HivePrivilegeInfo>) m.invoke(authorizer, null, resource);
+
+            assertFalse(infos.isEmpty());
+            // Ensure entries for user, group and role got included
+            assertTrue(infos.stream().anyMatch(i -> i.getPrincipal().getType() == HivePrincipal.HivePrincipalType.USER));
+            assertTrue(infos.stream().anyMatch(i -> i.getPrincipal().getType() == HivePrincipal.HivePrincipalType.GROUP));
+            assertTrue(infos.stream().anyMatch(i -> i.getPrincipal().getType() == HivePrincipal.HivePrincipalType.ROLE));
+        }
+    }
+
+    private static RangerAccessResult allowedResult() {
+        RangerAccessResult res = new RangerAccessResult(RangerPolicy.POLICY_TYPE_ACCESS, "svc", null, new RangerAccessRequestImpl());
+        res.setIsAudited(true);
+        res.setIsAllowed(true);
+        return res;
+    }
+
+    private static RangerBasePlugin getStaticHivePlugin() throws Exception {
+        Field f = RangerHiveAuthorizer.class.getDeclaredField("hivePlugin");
+        f.setAccessible(true);
+        Object val = f.get(null);
+        return (RangerBasePlugin) val;
+    }
+
+    private static void setStaticHivePlugin(RangerBasePlugin plugin) throws Exception {
+        Field f = RangerHiveAuthorizer.class.getDeclaredField("hivePlugin");
+        f.setAccessible(true);
+        f.set(null, plugin);
+    }
+
+    private static void setRangerHivePluginUpdateFlag(boolean value) throws Exception {
+        Field f = Class.forName("org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer$RangerHivePlugin").getDeclaredField("updateXaPoliciesOnGrantRevoke");
+        f.setAccessible(true);
+        f.set(null, value);
+    }
+
+    private static Object newInstanceRangerHivePlugin(String appType) throws Exception {
+        Class<?>                         c    = Class.forName("org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer$RangerHivePlugin");
+        java.lang.reflect.Constructor<?> ctor = c.getDeclaredConstructor(String.class);
+        ctor.setAccessible(true);
+        return ctor.newInstance(appType);
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizerBase.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizerBase.java
new file mode 100644
index 000000000..80ea2a36c
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizerBase.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.authorization.hive.authorizer;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.ql.security.HiveAuthenticationProvider;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzPluginException;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzSessionContext;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveMetastoreClientFactory;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrincipal;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Assumptions;
+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.junit.jupiter.api.function.Executable;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHiveAuthorizerBase
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHiveAuthorizerBase {
+    @Test
+    public void test01_constructorSetsUgiWhenUserPresent() {
+        HiveMetastoreClientFactory msFactory      = Mockito.mock(HiveMetastoreClientFactory.class);
+        HiveAuthenticationProvider authenticator  = Mockito.mock(HiveAuthenticationProvider.class);
+        HiveAuthzSessionContext    sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+
+        Mockito.when(authenticator.getUserName()).thenReturn("alice");
+
+        RangerHiveAuthorizerBase auth = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(msFactory, null, authenticator, sessionContext).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+
+        UserGroupInformation ugi = auth.getCurrentUserGroupInfo();
+        Assertions.assertNotNull(ugi);
+        Assertions.assertEquals("alice", ugi.getShortUserName());
+        Assertions.assertNull(auth.getHiveConf());
+        Assertions.assertEquals(authenticator, auth.getHiveAuthenticator());
+        Assertions.assertEquals(sessionContext, auth.getHiveAuthzSessionContext());
+        Assertions.assertEquals(msFactory, auth.getMetastoreClientFactory());
+    }
+
+    @Test
+    public void test02_constructorLeavesUgiNullWhenUserMissing() {
+        HiveMetastoreClientFactory msFactory      = Mockito.mock(HiveMetastoreClientFactory.class);
+        HiveAuthenticationProvider authenticator  = Mockito.mock(HiveAuthenticationProvider.class);
+        HiveAuthzSessionContext    sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+
+        Mockito.when(authenticator.getUserName()).thenReturn(null);
+
+        RangerHiveAuthorizerBase auth = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(msFactory, null, authenticator, sessionContext).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+
+        Assertions.assertNull(auth.getCurrentUserGroupInfo());
+    }
+
+    @Test
+    public void test03_getVersionIsV1() {
+        RangerHiveAuthorizerBase auth = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(null, null, null, null).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+        Assertions.assertEquals(RangerHiveAuthorizerBase.VERSION.V1, auth.getVersion());
+    }
+
+    @Test
+    public void test05_getHivePolicyProviderReturnsNull() throws Exception {
+        RangerHiveAuthorizerBase auth = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(null, null, null, null).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+        Assertions.assertNull(auth.getHivePolicyProvider());
+    }
+
+    @Test
+    public void test06_applyAuthorizationConfigPolicy_addsDisallowHookForHS2WithEmptyHooks() throws Exception {
+        assumeHiveAvailable();
+        HiveConf conf = new HiveConf();
+        conf.setVar(HiveConf.getConfVars("hive.exec.pre.hooks"), "");
+
+        HiveAuthzSessionContext sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+        Mockito.when(sessionContext.getClientType()).thenReturn(HiveAuthzSessionContext.CLIENT_TYPE.HIVESERVER2);
+
+        RangerHiveAuthorizerBase auth = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(null, conf, null, sessionContext).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+
+        auth.applyAuthorizationConfigPolicy(conf);
+
+        String hooks = conf.getVar(HiveConf.getConfVars("hive.exec.pre.hooks"));
+        Assertions.assertTrue(hooks.contains("DisallowTransformHook"));
+    }
+
+    @Test
+    public void test07_applyAuthorizationConfigPolicy_appendsDisallowHookForHS2WithExistingHooks() throws Exception {
+        assumeHiveAvailable();
+        HiveConf conf = new HiveConf();
+        conf.setVar(HiveConf.getConfVars("hive.exec.pre.hooks"), "org.example.MyHook");
+
+        HiveAuthzSessionContext sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+        Mockito.when(sessionContext.getClientType()).thenReturn(HiveAuthzSessionContext.CLIENT_TYPE.HIVESERVER2);
+
+        RangerHiveAuthorizerBase auth = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(null, conf, null, sessionContext).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+
+        auth.applyAuthorizationConfigPolicy(conf);
+
+        String hooks = conf.getVar(HiveConf.getConfVars("hive.exec.pre.hooks"));
+        Assertions.assertTrue(hooks.startsWith("org.example.MyHook"));
+        Assertions.assertTrue(hooks.contains("DisallowTransformHook"));
+    }
+
+    @Test
+    public void test08_applyAuthorizationConfigPolicy_noChangeWhenNotHS2() throws Exception {
+        assumeHiveAvailable();
+        HiveConf conf = new HiveConf();
+        conf.setVar(HiveConf.getConfVars("hive.exec.pre.hooks"), "pre.Existing");
+
+        HiveAuthzSessionContext sessionContext = Mockito.mock(HiveAuthzSessionContext.class);
+        Mockito.when(sessionContext.getClientType()).thenReturn(HiveAuthzSessionContext.CLIENT_TYPE.HIVECLI);
+
+        RangerHiveAuthorizerBase auth = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(null, conf, null, sessionContext).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+
+        auth.applyAuthorizationConfigPolicy(conf);
+
+        String hooks = conf.getVar(HiveConf.getConfVars("hive.exec.pre.hooks"));
+        Assertions.assertEquals("pre.Existing", hooks);
+    }
+
+    @Test
+    public void test04_showPrivilegesThrowsNotImplemented() {
+        RangerHiveAuthorizerBase auth      = Mockito.mock(RangerHiveAuthorizerBase.class, Mockito.withSettings().useConstructor(null, null, null, null).defaultAnswer(Mockito.CALLS_REAL_METHODS));
+        HivePrincipal            principal = Mockito.mock(HivePrincipal.class);
+        HivePrivilegeObject      obj       = Mockito.mock(HivePrivilegeObject.class);
+
+        Executable               call = () -> auth.showPrivileges(principal, obj);
+        HiveAuthzPluginException ex   = Assertions.assertThrows(HiveAuthzPluginException.class, call);
+        Assertions.assertTrue(ex.getMessage().contains("showPrivileges() not implemented"));
+    }
+
+    private static boolean canLoad(String cn) {
+        try {
+            Class.forName(cn);
+            return true;
+        } catch (Throwable t) {
+            return false;
+        }
+    }
+
+    private static void assumeHiveAvailable() {
+        Assumptions.assumeTrue(canLoad("org.apache.hadoop.hive.conf.HiveConf"), "HiveConf not available in unit test runtime");
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizerFactory.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizerFactory.java
new file mode 100644
index 000000000..3834d0119
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveAuthorizerFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.authorization.hive.authorizer;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizerFactory;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzPluginException;
+import org.junit.jupiter.api.Assertions;
+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;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHiveAuthorizerFactory
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHiveAuthorizerFactory {
+    @Test
+    public void test01_createHiveAuthorizer_throwsOrCreates() {
+        HiveAuthorizerFactory factory = new RangerHiveAuthorizerFactory();
+
+        try {
+            Assertions.assertNotNull(factory.createHiveAuthorizer(null, new HiveConf(), null, null));
+        } catch (HiveAuthzPluginException | Error e) {
+            Assertions.assertNotNull(e);
+        }
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHivePolicyProvider.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHivePolicyProvider.java
new file mode 100644
index 000000000..5c8e0b96d
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHivePolicyProvider.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.ranger.authorization.hive.authorizer;
+
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePolicyChangeListener;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveResourceACLs;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveResourceACLs.AccessResult;
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveResourceACLs.Privilege;
+import org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer.HiveObjectType;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.policyengine.RangerResourceACLs;
+import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+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.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHivePolicyProvider
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHivePolicyProvider {
+    @Mock
+    private RangerBasePlugin mockPlugin;
+
+    @Mock
+    private RangerHiveAuthorizer mockAuthorizer;
+
+    @Test
+    public void test01_registerListenerWiresThroughBasePlugin() {
+        RangerHivePolicyProvider provider = new RangerHivePolicyProvider(mockPlugin, mockAuthorizer);
+        HivePolicyChangeListener listener = mock(HivePolicyChangeListener.class);
+
+        provider.registerHivePolicyChangeListener(listener);
+
+        verify(mockPlugin, times(1)).registerAuthContextEventListener(any(RangerHivePolicyProvider.RangerHiveAuthContextListener.class));
+    }
+
+    @Test
+    public void test02_getResourceACLsDelegatesToPluginAndConvertsResults() {
+        RangerHivePolicyProvider provider = new RangerHivePolicyProvider(mockPlugin, mockAuthorizer);
+
+        // Build Ranger ACLs
+        RangerResourceACLs                           rangerAcls = new RangerResourceACLs();
+        Map<String, RangerResourceACLs.AccessResult> userPerms  = new HashMap<>();
+        userPerms.put("select", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_ALLOWED, null));
+        userPerms.put("update", new RangerResourceACLs.AccessResult(RangerPolicyEvaluator.ACCESS_DENIED, null));
+        rangerAcls.getUserACLs().put("alice", userPerms);
+
+        when(mockPlugin.getResourceACLs(any(RangerAccessRequestImpl.class))).thenReturn(rangerAcls);
+
+        RangerHiveResource hiveRes  = new RangerHiveResource(HiveObjectType.TABLE, "db", "t");
+        HiveResourceACLs   hiveAcls = provider.getResourceACLs(hiveRes);
+
+        assertNotNull(hiveAcls);
+        Map<Privilege, AccessResult> alice = hiveAcls.getUserPermissions().get("alice");
+        assertEquals(AccessResult.ALLOWED, alice.get(Privilege.SELECT));
+        assertEquals(AccessResult.NOT_ALLOWED, alice.get(Privilege.UPDATE));
+
+        ArgumentCaptor<RangerAccessRequestImpl> captor = ArgumentCaptor.forClass(RangerAccessRequestImpl.class);
+        verify(mockPlugin).getResourceACLs(captor.capture());
+        assertEquals(RangerPolicyEngine.ANY_ACCESS, captor.getValue().getAccessType());
+    }
+
+    @Test
+    public void test03_getResourceACLsFromHivePrivilegeObjectUsesAuthorizerToCreateResource() {
+        RangerHivePolicyProvider provider = new RangerHivePolicyProvider(mockPlugin, mockAuthorizer);
+        HivePrivilegeObject      hiveObj  = new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, "db1", "t1");
+        RangerHiveResource       built    = new RangerHiveResource(HiveObjectType.TABLE, "db1", "t1");
+        when(mockAuthorizer.createHiveResource(eq(hiveObj))).thenReturn(built);
+        when(mockPlugin.getResourceACLs(any(RangerAccessRequestImpl.class))).thenReturn(new RangerResourceACLs());
+
+        HiveResourceACLs hiveAcls = provider.getResourceACLs(hiveObj);
+        assertNotNull(hiveAcls);
+        verify(mockAuthorizer, times(1)).createHiveResource(eq(hiveObj));
+    }
+
+    @Test
+    public void test01_contextChanged_notifiesRegisteredListeners() {
+        RangerBasePlugin         plugin     = mock(RangerBasePlugin.class);
+        RangerHiveAuthorizer     authorizer = new RangerHiveAuthorizer(null, null, null, null);
+        RangerHivePolicyProvider provider   = new RangerHivePolicyProvider(plugin, authorizer);
+        HivePolicyChangeListener listener   = mock(HivePolicyChangeListener.class);
+        provider.registerHivePolicyChangeListener(listener);
+        // trigger context change
+        RangerHivePolicyProvider.RangerHiveAuthContextListener l = new RangerHivePolicyProvider.RangerHiveAuthContextListener();
+        l.providerChangeListeners.add(listener);
+        l.contextChanged();
+        verify(listener, times(1)).notifyPolicyChange(null);
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveResource.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveResource.java
new file mode 100644
index 000000000..84f389b34
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveResource.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.authorization.hive.authorizer;
+
+import org.junit.jupiter.api.Assertions;
+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;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHiveResource
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHiveResource {
+    @Test
+    public void test01_databaseResourceSetsKeysAndType() {
+        RangerHiveAuthorizer.HiveObjectType type     = RangerHiveAuthorizer.HiveObjectType.DATABASE;
+        RangerHiveResource                  resource = new RangerHiveResource(type, "db1");
+
+        Assertions.assertEquals(type, resource.getObjectType());
+        Assertions.assertEquals("db1", resource.getDatabase());
+        Assertions.assertNull(resource.getTable());
+        Assertions.assertNull(resource.getColumn());
+    }
+
+    @Test
+    public void test02_tableResourceSetsKeys() {
+        RangerHiveAuthorizer.HiveObjectType type     = RangerHiveAuthorizer.HiveObjectType.TABLE;
+        RangerHiveResource                  resource = new RangerHiveResource(type, "db1", "tbl1");
+
+        Assertions.assertEquals("db1", resource.getDatabase());
+        Assertions.assertEquals("tbl1", resource.getTable());
+        Assertions.assertNull(resource.getColumn());
+    }
+
+    @Test
+    public void test03_columnResourceSetsKeys() {
+        RangerHiveAuthorizer.HiveObjectType type     = RangerHiveAuthorizer.HiveObjectType.COLUMN;
+        RangerHiveResource                  resource = new RangerHiveResource(type, "db1", "tbl1", "col1");
+
+        Assertions.assertEquals("db1", resource.getDatabase());
+        Assertions.assertEquals("tbl1", resource.getTable());
+        Assertions.assertEquals("col1", resource.getColumn());
+    }
+
+    @Test
+    public void test04_uriResourceContainsUrlKey() {
+        RangerHiveAuthorizer.HiveObjectType type     = RangerHiveAuthorizer.HiveObjectType.URI;
+        RangerHiveResource                  resource = new RangerHiveResource(type, "/tmp/path");
+
+        Assertions.assertTrue(resource.exists(RangerHiveResource.KEY_URL));
+        Assertions.assertNotNull(resource.getAsMap().get(RangerHiveResource.KEY_URL));
+    }
+
+    @Test
+    public void test05_functionResourceSetsDbEmptyAndUdf() {
+        RangerHiveResource resource = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.FUNCTION, null, "myUdf");
+
+        Assertions.assertEquals("", resource.getDatabase());
+        Assertions.assertEquals("myUdf", resource.getUdf());
+    }
+
+    @Test
+    public void test06_serviceNameResourceSetsHiveServiceEmpty() {
+        RangerHiveResource resource = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.SERVICE_NAME, null);
+
+        Assertions.assertEquals("", resource.getHiveService());
+    }
+
+    @Test
+    public void test07_globalResourceSetsDefaultGlobalKey() {
+        RangerHiveResource resource = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.GLOBAL, null);
+
+        Assertions.assertTrue(resource.exists(RangerHiveResource.KEY_GLOBAL));
+        Assertions.assertEquals(RangerHiveResource.KEY_GLOBAL, resource.getAsMap().get(RangerHiveResource.KEY_GLOBAL));
+    }
+
+    @Test
+    public void test08_getUrlReturnsNullWhenNotSet() {
+        RangerHiveResource resource = new RangerHiveResource(RangerHiveAuthorizer.HiveObjectType.DATABASE, "dbx");
+
+        Assertions.assertNull(resource.getUrl());
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveResourceACLs.java b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveResourceACLs.java
new file mode 100644
index 000000000..97218cfb6
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/authorization/hive/authorizer/TestRangerHiveResourceACLs.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.authorization.hive.authorizer;
+
+import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveResourceACLs;
+import org.junit.jupiter.api.Assertions;
+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.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerHiveResourceACLs
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerHiveResourceACLs {
+    @Test
+    public void test01_defaultConstructorReturnsEmptyMaps() {
+        RangerHiveResourceACLs acls = new RangerHiveResourceACLs();
+
+        Assertions.assertTrue(acls.getUserPermissions().isEmpty());
+        Assertions.assertTrue(acls.getGroupPermissions().isEmpty());
+    }
+
+    @Test
+    public void test02_paramConstructorStoresMaps() {
+        Map<String, Map<HiveResourceACLs.Privilege, HiveResourceACLs.AccessResult>> user = new HashMap<>();
+        user.put("u1", new EnumMap<>(HiveResourceACLs.Privilege.class));
+        Map<String, Map<HiveResourceACLs.Privilege, HiveResourceACLs.AccessResult>> group = new HashMap<>();
+        group.put("g1", new EnumMap<>(HiveResourceACLs.Privilege.class));
+
+        RangerHiveResourceACLs acls = new RangerHiveResourceACLs(user, group);
+
+        Assertions.assertEquals(user.keySet(), acls.getUserPermissions().keySet());
+        Assertions.assertEquals(group.keySet(), acls.getGroupPermissions().keySet());
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/services/hive/TestRangerServiceHive.java b/hive-agent/src/test/java/org/apache/ranger/services/hive/TestRangerServiceHive.java
new file mode 100644
index 000000000..be63e38b3
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/services/hive/TestRangerServiceHive.java
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.hive;
+
+import org.apache.ranger.plugin.client.HadoopException;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.apache.ranger.services.hive.client.HiveResourceMgr;
+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.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerServiceHive
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerServiceHive {
+    @Test
+    public void test00_init_setsBaseFields() throws Exception {
+        RangerServiceHive svc     = new RangerServiceHive();
+        RangerServiceDef  def     = new RangerServiceDef();
+        RangerService     service = new RangerService();
+        service.setName("svc");
+        svc.init(def, service);
+        Field fService = RangerServiceHive.class.getSuperclass().getDeclaredField("service");
+        fService.setAccessible(true);
+        Field fSvcDef = RangerServiceHive.class.getSuperclass().getDeclaredField("serviceDef");
+        fSvcDef.setAccessible(true);
+        assertEquals(service, fService.get(svc));
+        assertEquals(def, fSvcDef.get(svc));
+    }
+
+    @Test
+    public void test01_validateConfig_delegatesAndReturns() throws Exception {
+        Map<String, String> cfg = new HashMap<>();
+        cfg.put("k", "v");
+        RangerServiceHive svc = newService("svc", "hive", cfg);
+        try (MockedStatic<HiveResourceMgr> stat = Mockito.mockStatic(HiveResourceMgr.class)) {
+            Map<String, Object> resp = new HashMap<>();
+            resp.put("ok", true);
+            stat.when(() -> HiveResourceMgr.connectionTest(Mockito.eq("svc"), Mockito.eq(cfg))).thenReturn(resp);
+            Map<String, Object> out = svc.validateConfig();
+            assertEquals(resp, out);
+        }
+    }
+
+    @Test
+    public void test02_validateConfig_throwsHadoopException() throws Exception {
+        Map<String, String> cfg = new HashMap<>();
+        RangerServiceHive   svc = newService("svc", "hive", cfg);
+        try (MockedStatic<HiveResourceMgr> stat = Mockito.mockStatic(HiveResourceMgr.class)) {
+            stat.when(() -> HiveResourceMgr.connectionTest(Mockito.eq("svc"), Mockito.eq(cfg))).thenThrow(new HadoopException("x"));
+            assertThrows(HadoopException.class, svc::validateConfig);
+        }
+    }
+
+    @Test
+    public void test03_lookupResource_delegates() throws Exception {
+        Map<String, String>   cfg = new HashMap<>();
+        RangerServiceHive     svc = newService("svc", "hive", cfg);
+        ResourceLookupContext ctx = new ResourceLookupContext();
+        try (MockedStatic<HiveResourceMgr> stat = Mockito.mockStatic(HiveResourceMgr.class)) {
+            List<String> resp = Collections.singletonList("db1");
+            stat.when(() -> HiveResourceMgr.getHiveResources("svc", "hive", cfg, ctx)).thenReturn(resp);
+            List<String> out = svc.lookupResource(ctx);
+            assertEquals(resp, out);
+        }
+    }
+
+    @Test
+    public void test04_lookupResource_nullContextReturnsEmpty() throws Exception {
+        RangerServiceHive svc = newService("svc", "hive", new HashMap<>());
+        List<String>      out = svc.lookupResource(null);
+        assertNotNull(out);
+        assertTrue(out.isEmpty());
+    }
+
+    @Test
+    public void test05_createDefaultDBPolicy_reflection() throws Exception {
+        RangerServiceHive svc = newService("svc", "hive", new HashMap<>());
+        Method            m   = RangerServiceHive.class.getDeclaredMethod("createDefaultDBPolicy");
+        m.setAccessible(true);
+        RangerPolicy p = (RangerPolicy) m.invoke(svc);
+        assertNotNull(p);
+        assertEquals("default database tables columns", p.getName());
+        assertEquals("svc", p.getService());
+        Map<String, RangerPolicy.RangerPolicyResource> res = p.getResources();
+        assertEquals(Collections.singletonList("default"), res.get("database").getValues());
+        assertEquals(Collections.singletonList("*"), res.get("table").getValues());
+        assertEquals(Collections.singletonList("*"), res.get("column").getValues());
+    }
+
+    @Test
+    public void test06_createInformationSchemaPolicy_reflection() throws Exception {
+        RangerServiceHive svc = newService("svc", "hive", new HashMap<>());
+        Method            m   = RangerServiceHive.class.getDeclaredMethod("createInformationSchemaPolicy");
+        m.setAccessible(true);
+        RangerPolicy p = (RangerPolicy) m.invoke(svc);
+        assertNotNull(p);
+        assertEquals("Information_schema database tables columns", p.getName());
+        assertEquals("svc", p.getService());
+        Map<String, RangerPolicy.RangerPolicyResource> res = p.getResources();
+        assertEquals(Collections.singletonList("information_schema"), res.get("database").getValues());
+        assertEquals(Collections.singletonList("*"), res.get("table").getValues());
+        assertEquals(Collections.singletonList("*"), res.get("column").getValues());
+    }
+
+    @Test
+    public void test07_hasWildcardAsteriskResource_trueFalse() throws Exception {
+        RangerServiceHive svc = newService("svc", "hive", new HashMap<>());
+        Method            m   = RangerServiceHive.class.getDeclaredMethod("hasWildcardAsteriskResource", Map.class, String[].class);
+        m.setAccessible(true);
+        Map<String, RangerPolicy.RangerPolicyResource> res = new HashMap<>();
+        res.put("database", new RangerPolicy.RangerPolicyResource(Collections.singletonList("*"), false, false));
+        assertTrue((Boolean) m.invoke(svc, res, new String[] {"database"}));
+    }
+
+    @Test
+    public void test08_getDefaultRangerPolicies_appendsDefaultAndInfo() throws Exception {
+        RangerServiceHive svc = newService("svc", "hive", new HashMap<>());
+        // minimally initialize service and serviceDef so super call doesn't NPE
+        RangerService service = new RangerService();
+        service.setName("svc");
+        Field fService = RangerServiceHive.class.getSuperclass().getDeclaredField("service");
+        fService.setAccessible(true);
+        fService.set(svc, service);
+        Field fSvcDef = RangerServiceHive.class.getSuperclass().getDeclaredField("serviceDef");
+        fSvcDef.setAccessible(true);
+        fSvcDef.set(svc, new RangerServiceDef());
+
+        List<RangerPolicy> out = svc.getDefaultRangerPolicies();
+        assertNotNull(out);
+        boolean hasDefault = out.stream().anyMatch(p -> "default database tables columns".equals(p.getName()));
+        boolean hasInfo    = out.stream().anyMatch(p -> "Information_schema database tables columns".equals(p.getName()));
+        assertTrue(hasDefault);
+        assertTrue(hasInfo);
+    }
+
+    @Test
+    public void test09_getDefaultRangerPolicies_addsLookupUserAndOwnerItems() throws Exception {
+        // Prepare configs to drive additional default policies from base service
+        Map<String, String> cfg = new HashMap<>();
+        cfg.put("setup.additional.default.policies", "true");
+        // policy 1: all databases (database=*) => should add public(create) and owner(all)
+        cfg.put("default-policy.1.name", "all - database");
+        cfg.put("default-policy.1.resource.database", "*");
+        // policy 2: all tables (database=*, table=*) => should add owner(all)
+        cfg.put("default-policy.2.name", "all - database, table");
+        cfg.put("default-policy.2.resource.database", "*");
+        cfg.put("default-policy.2.resource.table", "*");
+        RangerServiceHive svc = newService("svc", "hive", cfg);
+        // set lookUpUser so lookup-user entry is created for policies with name containing "all"
+        Field fLook = RangerServiceHive.class.getSuperclass().getDeclaredField("lookUpUser");
+        fLook.setAccessible(true);
+        fLook.set(svc, "lookupUser");
+        // also initialize service and serviceDef like in test08 to avoid NPEs inside super.getDefaultRangerPolicies
+        RangerService service = new RangerService();
+        service.setName("svc");
+        Field fService = RangerServiceHive.class.getSuperclass().getDeclaredField("service");
+        fService.setAccessible(true);
+        fService.set(svc, service);
+        Field fSvcDef = RangerServiceHive.class.getSuperclass().getDeclaredField("serviceDef");
+        fSvcDef.setAccessible(true);
+        fSvcDef.set(svc, new RangerServiceDef());
+        List<RangerPolicy> out = svc.getDefaultRangerPolicies();
+        assertNotNull(out);
+        // find our additional default policies
+        RangerPolicy allDb  = out.stream().filter(p -> "all - database".equals(p.getName())).findFirst().orElse(null);
+        RangerPolicy allTbl = out.stream().filter(p -> "all - database, table".equals(p.getName())).findFirst().orElse(null);
+        assertNotNull(allDb);
+        assertNotNull(allTbl);
+        // verify lookup-user, public(create), and owner(all) on database=* policy
+        assertTrue(allDb.getPolicyItems().stream().anyMatch(i -> i.getUsers() != null && i.getUsers().contains("lookupUser")));
+        assertTrue(allDb.getPolicyItems().stream().anyMatch(i -> i.getGroups() != null && i.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC)));
+        assertTrue(allDb.getPolicyItems().stream().anyMatch(i -> i.getUsers() != null && i.getUsers().contains(RangerPolicyEngine.RESOURCE_OWNER)));
+        // verify owner(all) on database=* and table=* policy
+        assertTrue(allTbl.getPolicyItems().stream().anyMatch(i -> i.getUsers() != null && i.getUsers().contains(RangerPolicyEngine.RESOURCE_OWNER)));
+    }
+
+    private static RangerServiceHive newService(String name, String type, Map<String, String> configs) throws Exception {
+        RangerServiceHive svc   = new RangerServiceHive();
+        Field             fName = RangerServiceHive.class.getSuperclass().getDeclaredField("serviceName");
+        fName.setAccessible(true);
+        fName.set(svc, name);
+        Field fType = RangerServiceHive.class.getSuperclass().getDeclaredField("serviceType");
+        fType.setAccessible(true);
+        fType.set(svc, type);
+        Field fCfg = RangerServiceHive.class.getSuperclass().getDeclaredField("configs");
+        fCfg.setAccessible(true);
+        fCfg.set(svc, configs);
+        return svc;
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveClient.java b/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveClient.java
new file mode 100644
index 000000000..d850a9541
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveClient.java
@@ -0,0 +1,584 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.hive.client;
+
+import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.ranger.plugin.client.HadoopConfigHolder;
+import org.apache.ranger.plugin.client.HadoopException;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.security.auth.Subject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Permission;
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverPropertyInfo;
+import java.sql.ResultSet;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLTimeoutException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+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.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for HiveClient
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestHiveClient {
+    @Test
+    public void test01_connectionTestEmptyDbListSetsFailureMessage() throws Exception {
+        try (MockedConstruction<HiveClient> cons = Mockito.mockConstruction(HiveClient.class, (mock, ctx) -> {
+            Mockito.when(mock.getDatabaseList("*", null)).thenReturn(Collections.emptyList());
+        })) {
+            Map<String, Object> resp = HiveClient.connectionTest("svc", Collections.emptyMap());
+            assertNotNull(resp);
+            assertNotEquals(Boolean.TRUE, resp.get("connectivityStatus"));
+        }
+    }
+
+    @Test
+    public void test02_connectionTestSuccessSetsSuccessMessageAndCloses() throws Exception {
+        try (MockedConstruction<HiveClient> cons = Mockito.mockConstruction(HiveClient.class, (mock, ctx) -> {
+            Mockito.when(mock.getDatabaseList("*", null)).thenReturn(Collections.singletonList("db1"));
+        })) {
+            Map<String, Object> resp = HiveClient.connectionTest("svc", new HashMap<>());
+            assertNotNull(resp);
+            List<HiveClient> constructed = cons.constructed();
+            if (!constructed.isEmpty()) {
+                Mockito.verify(constructed.get(0), Mockito.times(1)).close();
+            }
+        }
+    }
+
+    @Test
+    public void test03_connectionTestPropagatesException() throws Exception {
+        try (MockedConstruction<HiveClient> cons = Mockito.mockConstruction(HiveClient.class, (mock, ctx) -> {
+            Mockito.when(mock.getDatabaseList("*", null)).thenThrow(new RuntimeException("boom"));
+        })) {
+            assertThrows(Exception.class, () -> HiveClient.connectionTest("svc", Collections.emptyMap()));
+        }
+    }
+
+    @Test
+    public void test04_constructorsInvokeInitHive() throws Exception {
+        NoopHiveClient c1 = new NoopHiveClient("svc");
+        assertTrue(c1.initCalled);
+        NoopHiveClient c2 = new NoopHiveClient("svc", new HashMap<>());
+        assertTrue(c2.initCalled);
+    }
+
+    @Test
+    public void test05_getDatabaseList_usesHMWhenEnabled() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, true);
+        Field fHM = HiveClient.class.getDeclaredField("hiveClient");
+        fHM.setAccessible(true);
+        HiveMetaStoreClient hms = Mockito.mock(HiveMetaStoreClient.class);
+        when(hms.getAllDatabases()).thenReturn(Arrays.asList("db1", "db2"));
+        fHM.set(client, hms);
+        List<String> out = client.getDatabaseList("*", Collections.singletonList("db2"));
+        assertEquals(Collections.singletonList("db1"), out);
+    }
+
+    @Test
+    public void test06_getTableList_usesHMAndRespectsExcludes() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, true);
+        Field fHM = HiveClient.class.getDeclaredField("hiveClient");
+        fHM.setAccessible(true);
+        HiveMetaStoreClient hms = Mockito.mock(HiveMetaStoreClient.class);
+        when(hms.getTables("db1", "tbl*")).thenReturn(Arrays.asList("t1", "t2"));
+        fHM.set(client, hms);
+        List<String> out = client.getTableList("tbl*", Collections.singletonList("db1"), Collections.singletonList("t2"));
+        assertEquals(Collections.singletonList("t1"), out);
+    }
+
+    @Test
+    public void test07_getColumnList_usesHMWithPatternAndExcludes() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, true);
+        Field fHM = HiveClient.class.getDeclaredField("hiveClient");
+        fHM.setAccessible(true);
+        HiveMetaStoreClient hms = Mockito.mock(HiveMetaStoreClient.class);
+        when(hms.getFields("db1", "t1")).thenReturn(Arrays.asList(new FieldSchema("c1", "int", null), new FieldSchema("c2", "string", null)));
+        fHM.set(client, hms);
+        List<String> out = client.getColumnList("c*", Collections.singletonList("db1"), Collections.singletonList("t1"), Collections.singletonList("c2"));
+        assertEquals(Collections.singletonList("c1"), out);
+    }
+
+    @Test
+    public void test08_main_args2_noDatabaseFoundPrintedAndClosed() throws Exception {
+        PrintStream           origOut = System.out;
+        ByteArrayOutputStream bout    = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(bout));
+        try (MockedConstruction<HiveClient> cons = Mockito.mockConstruction(HiveClient.class, (mock, ctx) -> {
+            when(mock.getDatabaseList("db", null)).thenReturn(Collections.emptyList());
+        })) {
+            HiveClient.main(new String[] {"svc", "db"});
+            String out = bout.toString();
+            assertNotNull(out);
+            // ensure constructed mock was closed by try-with-resources
+            List<HiveClient> constructed = cons.constructed();
+            if (!constructed.isEmpty()) {
+                Mockito.verify(constructed.get(0), Mockito.times(1)).close();
+            }
+        } finally {
+            System.setOut(origOut);
+        }
+    }
+
+    @Test
+    public void test09_main_args3_printsTables() throws Exception {
+        PrintStream           origOut = System.out;
+        ByteArrayOutputStream bout    = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(bout));
+        try (MockedConstruction<HiveClient> cons = Mockito.mockConstruction(HiveClient.class, (mock, ctx) -> {
+            when(mock.getTableList("tbl", null, null)).thenReturn(Collections.singletonList("db.tbl1"));
+        })) {
+            HiveClient.main(new String[] {"svc", "db", "tbl"});
+            String out = bout.toString();
+            assertNotNull(out);
+        } finally {
+            System.setOut(origOut);
+        }
+    }
+
+    @Test
+    public void test10_main_args4_printsColumns() throws Exception {
+        PrintStream           origOut = System.out;
+        ByteArrayOutputStream bout    = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(bout));
+        try (MockedConstruction<HiveClient> cons = Mockito.mockConstruction(HiveClient.class, (mock, ctx) -> {
+            when(mock.getColumnList("col", null, null, null)).thenReturn(Collections.singletonList("db.tbl.col1"));
+        })) {
+            HiveClient.main(new String[] {"svc", "db", "tbl", "col"});
+            String out = bout.toString();
+            assertNotNull(out);
+        } finally {
+            System.setOut(origOut);
+        }
+    }
+
+    @Test
+    public void test11_getDatabaseList_jdbcPath() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, false);
+        Field fCon = HiveClient.class.getDeclaredField("con");
+        fCon.setAccessible(true);
+        Connection con  = Mockito.mock(Connection.class);
+        Statement  stat = Mockito.mock(Statement.class);
+        ResultSet  rs   = Mockito.mock(ResultSet.class);
+        when(con.createStatement()).thenReturn(stat);
+        when(stat.executeQuery(Mockito.anyString())).thenReturn(rs);
+        when(rs.next()).thenReturn(true, false);
+        when(rs.getString(1)).thenReturn("db1");
+        fCon.set(client, con);
+        List<String> out = client.getDatabaseList("db*", null);
+        assertEquals(Collections.singletonList("db1"), out);
+    }
+
+    @Test
+    public void test12_close_closesConnection() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fCon   = HiveClient.class.getDeclaredField("con");
+        fCon.setAccessible(true);
+        Connection con = Mockito.mock(Connection.class);
+        fCon.set(client, con);
+        client.close();
+        Mockito.verify(con, Mockito.times(1)).close();
+    }
+
+    @Test
+    public void test13_getTableList_jdbcPath_excludesAndPattern() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, false);
+        Field fCon = HiveClient.class.getDeclaredField("con");
+        fCon.setAccessible(true);
+        Connection con  = Mockito.mock(Connection.class);
+        Statement  stat = Mockito.mock(Statement.class);
+        ResultSet  rs   = Mockito.mock(ResultSet.class);
+        when(con.createStatement()).thenReturn(stat);
+        when(stat.execute(Mockito.eq("use db1"))).thenReturn(true);
+        when(stat.executeQuery(Mockito.anyString())).thenReturn(rs);
+        when(rs.next()).thenReturn(true, true, false);
+        when(rs.getString(1)).thenReturn("t1", "t2");
+        fCon.set(client, con);
+        List<String> out = client.getTableList("t*", Collections.singletonList("db1"), Collections.singletonList("t2"));
+        assertEquals(Collections.singletonList("t1"), out);
+        Mockito.verify(stat, Mockito.atLeastOnce()).execute(Mockito.eq("use db1"));
+    }
+
+    @Test
+    public void test14_getTableList_jdbcPath_timeoutThrowsHadoopException() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, false);
+        Field fCon = HiveClient.class.getDeclaredField("con");
+        fCon.setAccessible(true);
+        Connection con  = Mockito.mock(Connection.class);
+        Statement  stat = Mockito.mock(Statement.class);
+        when(con.createStatement()).thenReturn(stat);
+        when(stat.execute(Mockito.anyString())).thenReturn(true);
+        when(stat.executeQuery(Mockito.anyString())).thenThrow(new SQLTimeoutException("timeout"));
+        fCon.set(client, con);
+        assertThrows(HadoopException.class, () -> client.getTableList("t*", Collections.singletonList("db1"), null));
+    }
+
+    @Test
+    public void test17_getClmList_jdbcPath_excludesAndPattern() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, false);
+        Field fCon = HiveClient.class.getDeclaredField("con");
+        fCon.setAccessible(true);
+        Connection con  = Mockito.mock(Connection.class);
+        Statement  stat = Mockito.mock(Statement.class);
+        ResultSet  rs   = Mockito.mock(ResultSet.class);
+        when(con.createStatement()).thenReturn(stat);
+        when(stat.execute(Mockito.eq("use db1"))).thenReturn(true);
+        when(stat.executeQuery(Mockito.eq("describe  t1"))).thenReturn(rs);
+        when(rs.next()).thenReturn(true, true, false);
+        when(rs.getString(1)).thenReturn("c1", "c2");
+        fCon.set(client, con);
+        List<String> out = client.getColumnList("c*", Collections.singletonList("db1"), Collections.singletonList("t1"), Collections.singletonList("c2"));
+        assertEquals(Collections.singletonList("c1"), out);
+    }
+
+    @Test
+    public void test18_getClmList_jdbcPath_timeoutThrowsHadoopException() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, false);
+        Field fCon = HiveClient.class.getDeclaredField("con");
+        fCon.setAccessible(true);
+        Connection con  = Mockito.mock(Connection.class);
+        Statement  stat = Mockito.mock(Statement.class);
+        when(con.createStatement()).thenReturn(stat);
+        when(stat.execute(Mockito.anyString())).thenReturn(true);
+        when(stat.executeQuery(Mockito.anyString())).thenThrow(new SQLTimeoutException("timeout"));
+        fCon.set(client, con);
+        assertThrows(HadoopException.class, () -> client.getColumnList("c*", Collections.singletonList("db1"), Collections.singletonList("t1"), null));
+    }
+
+    @Test
+    public void test19_main_noArgs_printsUsageAndExits() {
+        PrintStream           origErr = System.err;
+        ByteArrayOutputStream berr    = new ByteArrayOutputStream();
+        System.setErr(new PrintStream(berr));
+        SecurityManager              prev = System.getSecurityManager();
+        ExitInterceptSecurityManager sm   = new ExitInterceptSecurityManager(prev);
+        System.setSecurityManager(sm);
+        try {
+            assertThrows(SecurityException.class, () -> HiveClient.main(new String[] {}));
+            assertEquals(Integer.valueOf(1), sm.status);
+            String err = berr.toString();
+            assertNotNull(err);
+            assertTrue(err.contains("USAGE: java"));
+        } finally {
+            System.setErr(origErr);
+            System.setSecurityManager(prev);
+        }
+    }
+
+    @Test
+    public void test20_getViewListAndUDFListReturnNull() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        assertNull(client.getViewList("db", "v*"));
+        assertNull(client.getUDFList("db", "f*"));
+    }
+
+    @Test
+    public void test21_privateInitConnection_wrapperRethrowsAsHadoopException() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        // Configure holder to take HM path so inner will wrap to HadoopException
+        Field fCfg = Class.forName("org.apache.ranger.plugin.client.BaseClient").getDeclaredField("configHolder");
+        fCfg.setAccessible(true);
+        HadoopConfigHolder cfg = Mockito.mock(HadoopConfigHolder.class);
+        when(cfg.getRangerSection()).thenReturn(new Properties());
+        fCfg.set(client, cfg);
+        Method m = HiveClient.class.getDeclaredMethod("initConnection");
+        m.setAccessible(true);
+        assertThrows(HadoopException.class, () -> {
+            try {
+                m.invoke(client);
+            } catch (InvocationTargetException ite) {
+                throw ite.getCause();
+            }
+        });
+    }
+
+    @Test
+    public void test22_initConnection_hmBranch_success() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, true);
+        Field fSite = HiveClient.class.getDeclaredField("hiveSiteFilePath");
+        fSite.setAccessible(true);
+        fSite.set(client, "/path/does/not/exist/hive-site.xml");
+        try (MockedConstruction<HiveMetaStoreClient> cons = Mockito.mockConstruction(HiveMetaStoreClient.class, (mock, ctx) -> {})) {
+            Method m = HiveClient.class.getDeclaredMethod("initConnection", String.class, String.class);
+            m.setAccessible(true);
+            // should not throw; constructor intercepted and hiveClient set
+            m.invoke(client, null, null);
+            List<HiveMetaStoreClient> constructed = cons.constructed();
+            assertTrue(constructed.size() >= 1);
+        }
+    }
+
+    @Test
+    public void test22b_initConnection_hmBranch_throwableWrapsAsHadoopException() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fFlag  = HiveClient.class.getDeclaredField("enableHiveMetastoreLookup");
+        fFlag.setAccessible(true);
+        fFlag.set(client, true);
+        Field fSite = HiveClient.class.getDeclaredField("hiveSiteFilePath");
+        fSite.setAccessible(true);
+        fSite.set(client, ""); // triggers "property not found" path
+        try (MockedConstruction<HiveMetaStoreClient> cons = Mockito.mockConstruction(HiveMetaStoreClient.class, (mock, ctx) -> {
+            throw new RuntimeException("boom");
+        })) {
+            Method m = HiveClient.class.getDeclaredMethod("initConnection", String.class, String.class);
+            m.setAccessible(true);
+            assertThrows(HadoopException.class, () -> {
+                try {
+                    m.invoke(client, null, null);
+                } catch (InvocationTargetException ite) {
+                    throw ite.getCause();
+                }
+            });
+        }
+    }
+
+    @Test
+    public void test23_initConnection_jdbcBranch_reflectionExceptionPaths() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fCfg   = Class.forName("org.apache.ranger.plugin.client.BaseClient").getDeclaredField("configHolder");
+        fCfg.setAccessible(true);
+        HadoopConfigHolder cfg         = Mockito.mock(HadoopConfigHolder.class);
+        Properties         rangerProps = new Properties();
+        rangerProps.setProperty("jdbc.driverClassName", TestHiveClient.IllegalAccessDriver.class.getName());
+        rangerProps.setProperty("jdbc.url", "jdbc:hive2://localhost:10000");
+        when(cfg.getRangerSection()).thenReturn(rangerProps);
+        fCfg.set(client, cfg);
+        Method m = HiveClient.class.getDeclaredMethod("initConnection", String.class, String.class);
+        m.setAccessible(true);
+        // IllegalAccessException path
+        assertThrows(HadoopException.class, () -> {
+            try {
+                m.invoke(client, null, null);
+            } catch (InvocationTargetException ite) {
+                throw ite.getCause();
+            }
+        });
+        // Class not found -> Throwable path
+        rangerProps.setProperty("jdbc.driverClassName", "com.example.NoSuchDriver");
+        assertThrows(HadoopException.class, () -> {
+            try {
+                m.invoke(client, null, null);
+            } catch (InvocationTargetException ite) {
+                throw ite.getCause();
+            }
+        });
+    }
+
+    @Test
+    public void test24_initHive_kerberosPath_invokesMetastoreInitConnection() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fCfg   = Class.forName("org.apache.ranger.plugin.client.BaseClient").getDeclaredField("configHolder");
+        fCfg.setAccessible(true);
+        HadoopConfigHolder cfg = Mockito.mock(HadoopConfigHolder.class);
+        fCfg.set(client, cfg);
+        try (MockedStatic<Subject> subj = Mockito.mockStatic(Subject.class)) {
+            subj.when(() -> Subject.doAs(Mockito.any(Subject.class), Mockito.any(PrivilegedExceptionAction.class))).thenReturn(null);
+            Method m = HiveClient.class.getDeclaredMethod("initHive");
+            m.setAccessible(true);
+            assertDoesNotThrow(() -> m.invoke(client));
+        }
+    }
+
+    @Test
+    public void test25_initHive_nonKerberosPath_invokesJdbcInitConnectionAndWraps() throws Exception {
+        NoopHiveClient client = new NoopHiveClient("svc", new HashMap<>());
+        Field          fCfg   = Class.forName("org.apache.ranger.plugin.client.BaseClient").getDeclaredField("configHolder");
+        fCfg.setAccessible(true);
+        HadoopConfigHolder cfg = Mockito.mock(HadoopConfigHolder.class);
+        Mockito.when(cfg.isEnableHiveMetastoreLookup()).thenReturn(false);
+        Mockito.when(cfg.getHiveSiteFilePath()).thenReturn("");
+        Mockito.when(cfg.isKerberosAuthentication()).thenReturn(false);
+        Mockito.when(cfg.getUserName()).thenReturn("u");
+        Mockito.when(cfg.getPassword()).thenReturn("p");
+        fCfg.set(client, cfg);
+        try (MockedStatic<Subject> subj = Mockito.mockStatic(Subject.class)) {
+            subj.when(() -> Subject.doAs(Mockito.any(Subject.class), Mockito.any(PrivilegedExceptionAction.class))).thenReturn(null);
+            Method m = HiveClient.class.getDeclaredMethod("initHive");
+            m.setAccessible(true);
+            assertDoesNotThrow(() -> m.invoke(client));
+        }
+    }
+
+    public static class NoopHiveClient extends HiveClient {
+        public boolean initCalled;
+
+        public NoopHiveClient(String serviceName) throws Exception {
+            super(serviceName);
+        }
+
+        public NoopHiveClient(String serviceName, Map<String, String> props) throws Exception {
+            super(serviceName, props);
+        }
+
+        @Override
+        public void initHive() {
+            initCalled = true;
+        }
+
+        @Override
+        protected void login() {
+            /* no-op to avoid real Hadoop auth */
+        }
+
+        @Override
+        protected Subject getLoginSubject() {
+            return new Subject();
+        }
+    }
+
+    public static class BypassLoginHiveClient extends HiveClient {
+        public BypassLoginHiveClient(String serviceName) throws Exception {
+            super(serviceName);
+        }
+
+        public BypassLoginHiveClient(String serviceName, Map<String, String> props) throws Exception {
+            super(serviceName, props);
+        }
+
+        @Override
+        protected void login() { /* no-op to avoid real Hadoop auth */ }
+
+        @Override
+        protected Subject getLoginSubject() {
+            return new Subject();
+        }
+    }
+
+    private static class ExitInterceptSecurityManager extends SecurityManager {
+        private final SecurityManager original;
+        public        Integer         status;
+
+        ExitInterceptSecurityManager(SecurityManager original) {
+            this.original = original;
+        }
+
+        @Override
+        public void checkPermission(Permission perm) {
+            if (original != null) {
+                original.checkPermission(perm);
+            }
+        }
+
+        @Override
+        public void checkExit(int status) {
+            this.status = status;
+            throw new SecurityException("exit");
+        }
+    }
+
+    public static class IllegalAccessDriver implements Driver {
+        private IllegalAccessDriver() {}
+
+        @Override
+        public Connection connect(String url, Properties info) {
+            return null;
+        }
+
+        @Override
+        public boolean acceptsURL(String url) {
+            return false;
+        }
+
+        @Override
+        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
+            return new DriverPropertyInfo[0];
+        }
+
+        @Override
+        public int getMajorVersion() {
+            return 1;
+        }
+
+        @Override
+        public int getMinorVersion() {
+            return 0;
+        }
+
+        @Override
+        public boolean jdbcCompliant() {
+            return false;
+        }
+
+        @Override
+        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+            throw new SQLFeatureNotSupportedException();
+        }
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveConnectionMgr.java b/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveConnectionMgr.java
new file mode 100644
index 000000000..1578855e4
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveConnectionMgr.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.hive.client;
+
+import org.apache.ranger.plugin.util.TimedEventUtil;
+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.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for HiveConnectionMgr
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestHiveConnectionMgr {
+    @Test
+    public void test01_returnsNullWhenServiceTypeNull() {
+        HiveConnectionMgr mgr = new HiveConnectionMgr();
+        HiveClient        ret = mgr.getHiveConnection("svc", null, new HashMap<>());
+        assertNull(ret);
+    }
+
+    @Test
+    public void test02_returnsNullWhenConfigsNullAndCacheEmpty() {
+        HiveConnectionMgr mgr = new HiveConnectionMgr();
+        HiveClient        ret = mgr.getHiveConnection("svc", "hive", null);
+        assertNull(ret);
+    }
+
+    @Test
+    public void test03_returnsCachedAndValidates() throws Exception {
+        HiveConnectionMgr mgr = new HiveConnectionMgr();
+
+        HiveClient client = Mockito.mock(HiveClient.class);
+        Mockito.when(client.getDatabaseList("*", null)).thenReturn(Collections.singletonList("db1"));
+
+        Field f = HiveConnectionMgr.class.getDeclaredField("hiveConnectionCache");
+        f.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        ConcurrentHashMap<String, HiveClient> cache = (ConcurrentHashMap<String, HiveClient>) f.get(mgr);
+        cache.put("svc", client);
+
+        HiveClient ret = mgr.getHiveConnection("svc", "hive", new HashMap<>());
+        assertEquals(client, ret);
+    }
+
+    @Test
+    public void test04_newClientClosedIfOldPresentAtPutIfAbsent() throws Exception {
+        HiveConnectionMgr mgr = new HiveConnectionMgr();
+
+        // Replace cache with a mock to simulate race: get() returns null, putIfAbsent returns existing old
+        @SuppressWarnings("unchecked")
+        ConcurrentMap<String, HiveClient> mockCache = Mockito.mock(ConcurrentMap.class);
+        Field fCache = HiveConnectionMgr.class.getDeclaredField("hiveConnectionCache");
+        fCache.setAccessible(true);
+        fCache.set(mgr, mockCache);
+
+        HiveClient oldClient = Mockito.mock(HiveClient.class);
+        HiveClient newClient = Mockito.mock(HiveClient.class);
+
+        Mockito.when(mockCache.get("svc")).thenReturn(null);
+        Mockito.when(mockCache.putIfAbsent("svc", newClient)).thenReturn(oldClient);
+
+        try (MockedStatic<TimedEventUtil> s = Mockito.mockStatic(TimedEventUtil.class)) {
+            s.when(() -> TimedEventUtil.timedTask(Mockito.any(), Mockito.anyLong(), Mockito.any())).thenReturn(newClient);
+
+            HiveClient ret = mgr.getHiveConnection("svc", "hive", new HashMap<>());
+            assertEquals(oldClient, ret);
+            Mockito.verify(newClient, Mockito.times(1)).close();
+        }
+    }
+
+    @Test
+    public void test05_cachedClientFailureRemovesClosesAndRecreates() throws Exception {
+        HiveConnectionMgr mgr = new HiveConnectionMgr();
+
+        Field fCache = HiveConnectionMgr.class.getDeclaredField("hiveConnectionCache");
+        fCache.setAccessible(true);
+        @SuppressWarnings("unchecked")
+        ConcurrentHashMap<String, HiveClient> cache = (ConcurrentHashMap<String, HiveClient>) fCache.get(mgr);
+
+        HiveClient badClient = Mockito.mock(HiveClient.class);
+        Mockito.when(badClient.getDatabaseList("*", null)).thenThrow(new RuntimeException("boom"));
+        cache.put("svc", badClient);
+
+        HiveClient newClient = Mockito.mock(HiveClient.class);
+        try (MockedStatic<TimedEventUtil> s = Mockito.mockStatic(TimedEventUtil.class)) {
+            s.when(() -> TimedEventUtil.timedTask(Mockito.any(), Mockito.anyLong(), Mockito.any())).thenReturn(newClient);
+
+            HiveClient ret = mgr.getHiveConnection("svc", "hive", new HashMap<>());
+            assertEquals(newClient, ret);
+            Mockito.verify(badClient, Mockito.times(1)).close();
+            assertEquals(newClient, cache.get("svc"));
+        }
+    }
+}
diff --git a/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveResourceMgr.java b/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveResourceMgr.java
new file mode 100644
index 000000000..b1db31555
--- /dev/null
+++ b/hive-agent/src/test/java/org/apache/ranger/services/hive/client/TestHiveResourceMgr.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ranger.services.hive.client;
+
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+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.MockedConstruction;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for HiveResourceMgr
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestHiveResourceMgr {
+    @Test
+    public void test01_connectionTestDelegatesToHiveClient() throws Exception {
+        try (MockedStatic<HiveClient> staticMock = Mockito.mockStatic(HiveClient.class)) {
+            Map<String, Object> resp = new HashMap<>();
+            resp.put("connectivityStatus", true);
+            staticMock.when(() -> HiveClient.connectionTest(Mockito.eq("svc"), Mockito.anyMap())).thenReturn(resp);
+
+            Map<String, Object> out = HiveResourceMgr.connectionTest("svc", Collections.emptyMap());
+            assertEquals(resp, out);
+        }
+    }
+
+    @Test
+    public void test02_getHiveResources_dbTableColumnPaths() throws Exception {
+        HiveClient client = Mockito.mock(HiveClient.class);
+        Mockito.when(client.getDatabaseList("db*", null)).thenReturn(Arrays.asList("db1", "db2"));
+        Mockito.when(client.getTableList("tbl*", null, null)).thenReturn(Arrays.asList("db1.tbl1", "db1.tbl2"));
+        Mockito.when(client.getColumnList("col*", null, null, null)).thenReturn(Collections.singletonList("db1.tbl1.col1"));
+
+        try (MockedConstruction<HiveConnectionMgr> cons = Mockito.mockConstruction(HiveConnectionMgr.class, (mock, ctx) -> {
+            Mockito.when(mock.getHiveConnection(Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())).thenReturn(client);
+        })) {
+            ResourceLookupContext ctx = new ResourceLookupContext();
+            ctx.setUserInput("db");
+            ctx.setResourceName("database");
+            List<String> dbs = HiveResourceMgr.getHiveResources("svc", "hive", Collections.emptyMap(), ctx);
+            assertNotNull(dbs);
+
+            ctx = new ResourceLookupContext();
+            ctx.setUserInput("tbl");
+            ctx.setResourceName("table");
+            List<String> tbls = HiveResourceMgr.getHiveResources("svc", "hive", Collections.emptyMap(), ctx);
+            assertNotNull(tbls);
+
+            ctx = new ResourceLookupContext();
+            ctx.setUserInput("col");
+            ctx.setResourceName("column");
+            List<String> cols = HiveResourceMgr.getHiveResources("svc", "hive", Collections.emptyMap(), ctx);
+            assertNotNull(cols);
+        }
+    }
+
+    @Test
+    public void test03_getHiveResources_nullsReturnNull() throws Exception {
+        ResourceLookupContext ctx = new ResourceLookupContext();
+        ctx.setUserInput(null);
+        ctx.setResourceName("database");
+        List<String> out = HiveResourceMgr.getHiveResources("svc", "hive", Collections.emptyMap(), ctx);
+        assertNull(out);
+    }
+}