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 2026/08/15 19:07:57 UTC

(ranger) branch master updated: RANGER-5348: Test Cases for agents-common Module: Package (plugin.model) (#761)

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 ece62f616 RANGER-5348: Test Cases for agents-common Module: Package (plugin.model) (#761)
ece62f616 is described below

commit ece62f616c52efe6a0d0e474fb68e84edc8b1b92
Author: Rakesh Gupta <ra...@gmail.com>
AuthorDate: Sun Aug 16 00:37:52 2026 +0530

    RANGER-5348: Test Cases for agents-common Module: Package (plugin.model) (#761)
---
 .../ranger/plugin/model/TestAuditFilter.java       |  61 ++
 .../apache/ranger/plugin/model/TestGroupInfo.java  |  56 ++
 .../plugin/model/TestRangerBaseModelObject.java    | 110 +++
 .../plugin/model/TestRangerDatasetHeader.java      |  65 ++
 .../apache/ranger/plugin/model/TestRangerGds.java  | 312 +++++++++
 .../ranger/plugin/model/TestRangerGrant.java       | 145 ++++
 .../ranger/plugin/model/TestRangerHealth.java      |  86 +++
 ...stRangerService.java => TestRangerMetrics.java} |  33 +-
 .../ranger/plugin/model/TestRangerPluginInfo.java  | 153 +++++
 .../ranger/plugin/model/TestRangerPolicy.java      | 173 ++++-
 .../ranger/plugin/model/TestRangerPolicyDelta.java |  82 +++
 .../plugin/model/TestRangerPolicyHeader.java       |  83 +++
 .../model/TestRangerPolicyResourceSignature.java   |  39 +-
 .../ranger/plugin/model/TestRangerPrincipal.java   |  50 ++
 .../apache/ranger/plugin/model/TestRangerRole.java | 121 ++++
 .../plugin/model/TestRangerSecurityZone.java       | 102 +++
 .../model/TestRangerSecurityZoneHeaderInfo.java    |  55 ++
 .../plugin/model/TestRangerSecurityZoneV2.java     | 144 ++++
 .../ranger/plugin/model/TestRangerService.java     |  12 +-
 .../ranger/plugin/model/TestRangerServiceDef.java  | 348 ++++++++++
 .../plugin/model/TestRangerServiceHeaderInfo.java  |  72 ++
 .../plugin/model/TestRangerServiceResource.java    |  83 +++
 .../model/TestRangerServiceResourceWithTags.java   |  59 ++
 .../ranger/plugin/model/TestRangerServiceTags.java | 114 +++
 .../apache/ranger/plugin/model/TestRangerTag.java  |  96 +++
 .../ranger/plugin/model/TestRangerTagDef.java      |  82 +++
 ...rService.java => TestRangerTagResourceMap.java} |  40 +-
 .../plugin/model/TestRangerValidityRecurrence.java |  92 +++
 .../plugin/model/TestRangerValiditySchedule.java   |  71 ++
 .../plugin/model/TestServiceDeleteResponse.java    |  51 ++
 .../apache/ranger/plugin/model/TestUserInfo.java   |  64 ++
 .../RangerSecurityZoneValidatorTest.java           |   4 +
 .../plugin/model/validation/TestDirectedGraph.java |  10 +
 .../validation/TestRangerPolicyValidator.java      | 304 ++++----
 .../model/validation/TestRangerRoleValidator.java  | 284 ++++++++
 .../validation/TestRangerServiceDefHelper.java     | 763 +++++++++++++++++----
 .../validation/TestRangerServiceDefValidator.java  |  51 +-
 .../validation/TestRangerServiceValidator.java     | 123 ++--
 .../validation/TestValidationFailureDetails.java   |  99 +++
 .../model/validation/ValidationTestUtils.java      |  58 +-
 40 files changed, 4325 insertions(+), 425 deletions(-)

diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestAuditFilter.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestAuditFilter.java
new file mode 100644
index 000000000..fe4bead7e
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestAuditFilter.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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+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.Arrays;
+import java.util.HashMap;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for AuditFilter class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestAuditFilter {
+    @Test
+    public void test01_SettersGettersToString() {
+        AuditFilter f = new AuditFilter();
+        f.setAccessResult(AuditFilter.AccessResult.ALLOWED);
+        HashMap<String, RangerPolicyResource> res = new HashMap<>();
+        res.put("db", new RangerPolicyResource("db1"));
+        f.setResources(res);
+        f.setAccessTypes(Arrays.asList("read"));
+        f.setActions(Arrays.asList("OPEN"));
+        f.setUsers(Arrays.asList("u1"));
+        f.setGroups(Arrays.asList("g1"));
+        f.setRoles(Arrays.asList("r1"));
+        f.setAction(Boolean.TRUE); // note: method name is setAction but sets isAudited
+
+        Assertions.assertEquals(AuditFilter.AccessResult.ALLOWED, f.getAccessResult());
+        Assertions.assertTrue(f.getResources().containsKey("db"));
+        Assertions.assertEquals(Boolean.TRUE, f.getIsAudited());
+
+        String s = f.toString();
+        Assertions.assertTrue(s.contains("isAudited=true"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestGroupInfo.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestGroupInfo.java
new file mode 100644
index 000000000..2f9445da5
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestGroupInfo.java
@@ -0,0 +1,56 @@
+/*
+ * 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.plugin.model;
+
+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.HashMap;
+
+/**
+ * @generated by Cursor
+ * @description <Unit Test for GroupInfo class>
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestGroupInfo {
+    @Test
+    public void test01_ConstructorsAndSetters() {
+        GroupInfo g1 = new GroupInfo();
+        Assertions.assertNotNull(g1.getOtherAttributes());
+
+        GroupInfo g2 = new GroupInfo("dev", "desc", new HashMap<String, String>() {
+            {
+                put("k", "v");
+            }
+        });
+        Assertions.assertEquals("dev", g2.getName());
+        Assertions.assertEquals("desc", g2.getDescription());
+        Assertions.assertEquals("v", g2.getOtherAttributes().get("k"));
+
+        String s = g2.toString();
+        Assertions.assertTrue(s.contains("name=dev"));
+        Assertions.assertTrue(s.contains("otherAttributes={k, [v],}"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerBaseModelObject.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerBaseModelObject.java
new file mode 100644
index 000000000..7b5a5a8ba
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerBaseModelObject.java
@@ -0,0 +1,110 @@
+/*
+ * 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.plugin.model;
+
+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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerBaseModelObject class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerBaseModelObject {
+    @Test
+    public void test01_nullSafeSupplierV1() {
+        RangerBaseModelObject.setNullSafeSupplier((RangerBaseModelObject.NullSafeSupplier) null);
+
+        List<String> listCopy = RangerBaseModelObject.nullSafeList(Arrays.asList("a"));
+        Set<String> setCopy = RangerBaseModelObject.nullSafeSet(new HashSet<>(Collections.singleton("b")));
+        Map<String, String> mapCopy = RangerBaseModelObject.nullSafeMap(Collections.singletonMap("k", "v"));
+
+        Assertions.assertEquals(Arrays.asList("a"), listCopy);
+        Assertions.assertEquals(new HashSet<>(Collections.singleton("b")), setCopy);
+        Assertions.assertEquals("v", mapCopy.get("k"));
+
+        Assertions.assertTrue(RangerBaseModelObject.nullSafeList(null).isEmpty());
+        Assertions.assertTrue(RangerBaseModelObject.nullSafeSet(null).isEmpty());
+        Assertions.assertTrue(RangerBaseModelObject.nullSafeMap(null).isEmpty());
+    }
+
+    @Test
+    public void test02_nullSafeSupplierV2() {
+        RangerBaseModelObject.setNullSafeSupplier(RangerBaseModelObject.NULL_SAFE_SUPPLIER_V2);
+
+        List<String> emptyList = RangerBaseModelObject.nullSafeList(null);
+        Set<String> emptySet = RangerBaseModelObject.nullSafeSet(null);
+        Map<String, String> emptyMap = RangerBaseModelObject.nullSafeMap(null);
+        Assertions.assertSame(Collections.emptyList(), emptyList);
+        Assertions.assertSame(Collections.emptySet(), emptySet);
+        Assertions.assertSame(Collections.emptyMap(), emptyMap);
+
+        List<String> base = new ArrayList<>(Arrays.asList("x"));
+        Assertions.assertSame(base, RangerBaseModelObject.nullSafeList(base));
+    }
+
+    @Test
+    public void test03_getUpdatableFactories() {
+        List<String> l1 = RangerBaseModelObject.getUpdatableList(null);
+        List<String> l2 = RangerBaseModelObject.getUpdatableList(Collections.singletonList("a"));
+        List<String> l3 = RangerBaseModelObject.getUpdatableList(new ArrayList<>(Arrays.asList("a")));
+        Assertions.assertTrue(l1.isEmpty());
+        Assertions.assertEquals(Arrays.asList("a"), l2);
+        Assertions.assertSame(l3, RangerBaseModelObject.getUpdatableList(l3));
+
+        Set<String> s1 = RangerBaseModelObject.getUpdatableSet(null);
+        Set<String> s2 = RangerBaseModelObject.getUpdatableSet(new HashSet<>(Collections.singleton("z")));
+        Set<String> s3 = RangerBaseModelObject.getUpdatableSet(new HashSet<>(Collections.singleton("z")));
+        Assertions.assertTrue(s1.isEmpty());
+        Assertions.assertTrue(s2.contains("z"));
+        Assertions.assertTrue(s3.contains("z"));
+
+        Map<String, String> m1 = RangerBaseModelObject.getUpdatableMap(null);
+        Map<String, String> m2 = RangerBaseModelObject.getUpdatableMap(Collections.singletonMap("k", "v"));
+        Map<String, String> m3 = RangerBaseModelObject.getUpdatableMap(new HashMap<>());
+        Assertions.assertTrue(m1.isEmpty());
+        Assertions.assertEquals("v", m2.get("k"));
+        Assertions.assertSame(m3, RangerBaseModelObject.getUpdatableMap(m3));
+    }
+
+    @Test
+    public void test04_updateFromAndDefaults() {
+        RangerBaseModelObject src = new RangerBaseModelObject();
+        src.setIsEnabled(Boolean.FALSE);
+
+        RangerBaseModelObject dest = new RangerBaseModelObject();
+        dest.updateFrom(src);
+        Assertions.assertEquals(Boolean.FALSE, dest.getIsEnabled());
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerDatasetHeader.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerDatasetHeader.java
new file mode 100644
index 000000000..3f2a67e37
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerDatasetHeader.java
@@ -0,0 +1,65 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerGds.GdsShareStatus;
+import org.apache.ranger.plugin.model.RangerPrincipal.PrincipalType;
+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;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerDatasetHeader class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerDatasetHeader {
+    @Test
+    public void test01_headerInfoSettersAndGetters() {
+        RangerDatasetHeader.RangerDatasetHeaderInfo info = new RangerDatasetHeader.RangerDatasetHeaderInfo();
+        info.setGuid("g");
+        info.setName("ds");
+        info.setPermissionForCaller("read");
+        info.setProjectsCount(3L);
+        info.setResourceCount(10L);
+
+        EnumMap<GdsShareStatus, Long> shares = new EnumMap<>(GdsShareStatus.class);
+        shares.put(GdsShareStatus.ACTIVE, 2L);
+        info.setDataSharesCountByStatus(shares);
+
+        EnumMap<PrincipalType, Long> principals = new EnumMap<>(PrincipalType.class);
+        principals.put(PrincipalType.USER, 5L);
+        info.setPrincipalsCountByType(principals);
+
+        Assertions.assertEquals("g", info.getGuid());
+        Assertions.assertEquals("ds", info.getName());
+        Assertions.assertEquals("read", info.getPermissionForCaller());
+        Assertions.assertEquals(3L, info.getProjectsCount());
+        Assertions.assertEquals(10L, info.getResourceCount());
+        Assertions.assertEquals(2L, info.getDataSharesCountByStatus().get(RangerGds.GdsShareStatus.ACTIVE));
+        Assertions.assertEquals(5L, info.getPrincipalsCountByType().get(RangerPrincipal.PrincipalType.USER));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerGds.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerGds.java
new file mode 100644
index 000000000..e616355aa
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerGds.java
@@ -0,0 +1,312 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerGds.DataShareInDatasetSummary;
+import org.apache.ranger.plugin.model.RangerGds.DataShareSummary;
+import org.apache.ranger.plugin.model.RangerGds.DatasetSummary;
+import org.apache.ranger.plugin.model.RangerGds.DatasetsSummary;
+import org.apache.ranger.plugin.model.RangerGds.GdsPermission;
+import org.apache.ranger.plugin.model.RangerGds.GdsShareStatus;
+import org.apache.ranger.plugin.model.RangerGds.RangerDataShare;
+import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset;
+import org.apache.ranger.plugin.model.RangerGds.RangerDataset;
+import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject;
+import org.apache.ranger.plugin.model.RangerGds.RangerGdsBaseModelObject;
+import org.apache.ranger.plugin.model.RangerGds.RangerGdsMaskInfo;
+import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL;
+import org.apache.ranger.plugin.model.RangerGds.RangerProject;
+import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPrincipal.PrincipalType;
+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.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerGds class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerGds {
+    @Test
+    public void test01_baseModelObjectToString() {
+        RangerGdsBaseModelObject base = new RangerGdsBaseModelObject();
+        base.setGuid("g1");
+        base.setDescription("desc");
+        Map<String, String> opts = new HashMap<>();
+        opts.put("k", "v");
+        base.setOptions(opts);
+        Map<String, String> add = new HashMap<>();
+        add.put("a", "b");
+        base.setAdditionalInfo(add);
+
+        String s = base.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("description={desc}"));
+        Assertions.assertTrue(s.contains("options={"));
+        Assertions.assertTrue(s.contains("additionalInfo={"));
+    }
+
+    @Test
+    public void test02_datasetToString() {
+        RangerDataset ds = new RangerDataset();
+        ds.setName("ds1");
+        ds.setAcl(new RangerGdsObjectACL());
+        ds.setValiditySchedule(new RangerValiditySchedule());
+        ds.setTermsOfUse("terms");
+        List<String> labels = new ArrayList<>();
+        labels.add("L1");
+        ds.setLabels(labels);
+        List<String> keywords = new ArrayList<>();
+        keywords.add("K1");
+        ds.setKeywords(keywords);
+
+        String s = ds.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("RangerDataset={"));
+        Assertions.assertTrue(s.contains("name={ds1}"));
+        Assertions.assertTrue(s.contains("termsOfUse={terms}"));
+    }
+
+    @Test
+    public void test03_projectToString() {
+        RangerProject pr = new RangerProject();
+        pr.setName("p1");
+        pr.setAcl(new RangerGdsObjectACL());
+        pr.setValiditySchedule(new RangerValiditySchedule());
+        pr.setTermsOfUse("termsP");
+        String s = pr.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("RangerProject={"));
+        Assertions.assertTrue(s.contains("name={p1}"));
+        Assertions.assertTrue(s.contains("termsOfUse={termsP}"));
+    }
+
+    @Test
+    public void test04_dataShareToString() {
+        RangerDataShare ds = new RangerDataShare();
+        ds.setName("share1");
+        ds.setAcl(new RangerGdsObjectACL());
+        ds.setService("svc");
+        ds.setZone("zone");
+        ds.setConditionExpr("x > 5");
+        List<RangerGdsMaskInfo> masks = new ArrayList<>();
+        RangerGdsMaskInfo mi = new RangerGdsMaskInfo();
+        mi.setValues(new ArrayList<>());
+        mi.setMaskInfo(new RangerPolicyItemDataMaskInfo("MASK", null, null));
+        masks.add(mi);
+        ds.setDefaultTagMasks(masks);
+
+        Set<String> access = new HashSet<>();
+        access.add("read");
+        ds.setDefaultAccessTypes(access);
+        ds.setTermsOfUse("termsS");
+
+        String s = ds.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("RangerDataShare={"));
+        Assertions.assertTrue(s.contains("defaultAccessTypes={"));
+        Assertions.assertTrue(s.contains("defaultTagMasks={"));
+    }
+
+    @Test
+    public void test05_sharedResourceToString() {
+        RangerSharedResource sr = new RangerSharedResource();
+        sr.setName("res1");
+        sr.setDataShareId(9L);
+        Map<String, RangerPolicyResource> res = new HashMap<>();
+        res.put("db", new RangerPolicyResource());
+        sr.setResource(res);
+        sr.setSubResource(new RangerPolicyResource());
+        sr.setSubResourceType("table");
+        sr.setConditionExpr("a=1");
+        Set<String> accessTypes = new HashSet<>();
+        accessTypes.add("use");
+        sr.setAccessTypes(accessTypes);
+        sr.setRowFilter(new RangerPolicyItemRowFilterInfo("dept = 'hr'"));
+        List<RangerGdsMaskInfo> subMasks = new ArrayList<>();
+        subMasks.add(new RangerGdsMaskInfo());
+        sr.setSubResourceMasks(subMasks);
+        Set<String> profiles = new HashSet<>();
+        profiles.add("p1");
+        sr.setProfiles(profiles);
+
+        String s = sr.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("RangerSharedResource={"));
+        Assertions.assertTrue(s.contains("rowFilterInfo={"));
+        Assertions.assertTrue(s.contains("profiles={"));
+    }
+
+    @Test
+    public void test06_maskInfoToString() {
+        RangerGdsMaskInfo mi = new RangerGdsMaskInfo();
+        List<String> vals = new ArrayList<>();
+        vals.add("v");
+        mi.setValues(vals);
+        mi.setMaskInfo(new RangerPolicyItemDataMaskInfo("MASK", "c", "x"));
+        String s = mi.toString();
+        Assertions.assertTrue(s.contains("RangerGdsMaskInfo={"));
+        Assertions.assertTrue(s.contains("values="));
+        Assertions.assertTrue(s.contains("maskInfo="));
+    }
+
+    @Test
+    public void test07_dataShareInDatasetToString() {
+        RangerDataShareInDataset did = new RangerDataShareInDataset();
+        did.setDataShareId(1L);
+        did.setDatasetId(2L);
+        did.setStatus(GdsShareStatus.ACTIVE);
+        did.setValiditySchedule(new RangerValiditySchedule());
+        Set<String> profiles = new HashSet<>();
+        profiles.add("p");
+        did.setProfiles(profiles);
+        did.setApprover("root");
+        String s = did.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("RangerDataShareInDataset={"));
+        Assertions.assertTrue(s.contains("status={ACTIVE}"));
+    }
+
+    @Test
+    public void test08_datasetInProjectToString() {
+        RangerDatasetInProject dip = new RangerDatasetInProject();
+        dip.setDatasetId(3L);
+        dip.setProjectId(4L);
+        dip.setStatus(GdsShareStatus.REQUESTED);
+        dip.setValiditySchedule(new RangerValiditySchedule());
+        Set<String> profiles = new HashSet<>();
+        profiles.add("q");
+        dip.setProfiles(profiles);
+        dip.setApprover("boss");
+        String s = dip.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("RangerDatasetInProject={"));
+        Assertions.assertTrue(s.contains("datasetGuid={"));
+        Assertions.assertTrue(s.contains("projectGuid={"));
+    }
+
+    @Test
+    public void test09_aclToString() {
+        RangerGdsObjectACL acl = new RangerGdsObjectACL();
+        Map<String, GdsPermission> users = new HashMap<>();
+        users.put("u", GdsPermission.ADMIN);
+        Map<String, GdsPermission> groups = new HashMap<>();
+        groups.put("g", GdsPermission.VIEW);
+        Map<String, GdsPermission> roles = new HashMap<>();
+        roles.put("r", GdsPermission.LIST);
+        acl.setUsers(users);
+        acl.setGroups(groups);
+        acl.setRoles(roles);
+        String s = acl.toString();
+        Assertions.assertTrue(s.contains("RangerGdsObjectACL={"));
+        Assertions.assertTrue(s.contains("users={"));
+        Assertions.assertTrue(s.contains("groups={"));
+        Assertions.assertTrue(s.contains("roles={"));
+    }
+
+    @Test
+    public void test10_datasetSummaryToString() {
+        DatasetSummary sum = new DatasetSummary();
+        sum.setName("ds");
+        sum.setDescription("d");
+        sum.setPermissionForCaller(GdsPermission.VIEW);
+        Map<PrincipalType, Integer> pc = new HashMap<>();
+        pc.put(PrincipalType.USER, 2);
+        sum.setPrincipalsCount(pc);
+        Map<PrincipalType, Integer> ap = new HashMap<>();
+        ap.put(PrincipalType.GROUP, 1);
+        sum.setAclPrincipalsCount(ap);
+        sum.setProjectsCount(5L);
+        sum.setTotalResourceCount(7L);
+        sum.setValiditySchedule(new RangerValiditySchedule());
+        List<DataShareInDatasetSummary> shares = new ArrayList<>();
+        shares.add(new DataShareInDatasetSummary());
+        sum.setDataShares(shares);
+        List<String> labels = new ArrayList<>();
+        labels.add("L");
+        sum.setLabels(labels);
+        List<String> keywords = new ArrayList<>();
+        keywords.add("K");
+        sum.setKeywords(keywords);
+        String s = sum.toString();
+        Assertions.assertTrue(s.contains("DatasetSummary={"));
+        Assertions.assertTrue(s.contains("permissionForCaller={VIEW}"));
+    }
+
+    @Test
+    public void test11_datasetsSummaryToStringAndGetters() {
+        Map<String, Map<String, Integer>> info = new HashMap<>();
+        Map<String, Integer> inner = new HashMap<>();
+        inner.put("key", 1);
+        info.put("outer", inner);
+        DatasetsSummary dss = new DatasetsSummary(null, info);
+        Assertions.assertEquals(info, dss.getAdditionalInfo());
+        String s = dss.toString();
+        Assertions.assertTrue(s.contains("DatasetsSummary={"));
+        Assertions.assertTrue(s.contains("additionalInfo={"));
+    }
+
+    @Test
+    public void test12_dataShareSummaryToString() {
+        DataShareSummary sum = new DataShareSummary();
+        sum.setName("s");
+        sum.setDescription("d");
+        sum.setPermissionForCaller(GdsPermission.POLICY_ADMIN);
+        sum.setResourceCount(2L);
+        sum.setServiceId(11L);
+        sum.setServiceName("svc");
+        sum.setServiceType("hive");
+        sum.setZoneId(3L);
+        sum.setZoneName("z");
+        List<DataShareInDatasetSummary> lst = new ArrayList<>();
+        lst.add(new DataShareInDatasetSummary());
+        sum.setDatasets(lst);
+        String s = sum.toString();
+        Assertions.assertTrue(s.contains("DataShareSummary={"));
+        Assertions.assertTrue(s.contains("serviceType={hive}"));
+    }
+
+    @Test
+    public void test13_dataShareInDatasetSummaryToString() {
+        DataShareInDatasetSummary sum = new DataShareInDatasetSummary();
+        sum.setDatasetName("d");
+        sum.setDatasetId(1L);
+        sum.setDataShareId(2L);
+        sum.setDataShareName("s");
+        sum.setServiceId(3L);
+        sum.setServiceName("svc");
+        sum.setZoneId(4L);
+        sum.setZoneName("z");
+        sum.setResourceCount(5L);
+        sum.setShareStatus(GdsShareStatus.GRANTED);
+        sum.setApprover("a");
+        String s = sum.toString();
+        Assertions.assertTrue(s.contains("DataShareInDatasetSummary={"));
+        Assertions.assertTrue(s.contains("shareStatus={GRANTED}"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerGrant.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerGrant.java
new file mode 100644
index 000000000..91d82a605
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerGrant.java
@@ -0,0 +1,145 @@
+/*
+ * 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.plugin.model;
+
+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.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerGrant class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerGrant {
+    @Test
+    public void test01_constructorAndGettersSetters() {
+        RangerPrincipal principal = new RangerPrincipal(RangerPrincipal.PrincipalType.USER, "alice");
+        List<String> access = new ArrayList<>(Arrays.asList("read", "write"));
+        List<RangerGrant.Condition> conditions = new ArrayList<>();
+        conditions.add(new RangerGrant.Condition("ip", new ArrayList<>(Arrays.asList("10.0.0.1"))));
+
+        RangerGrant grant = new RangerGrant(principal, access, conditions);
+
+        Assertions.assertEquals(principal, grant.getPrincipal());
+        Assertions.assertEquals(access, grant.getAccessTypes());
+        Assertions.assertEquals(conditions, grant.getConditions());
+
+        RangerPrincipal bob = new RangerPrincipal(RangerPrincipal.PrincipalType.USER, "bob");
+        grant.setPrincipal(bob);
+        Assertions.assertEquals(bob, grant.getPrincipal());
+    }
+
+    @Test
+    public void test02_setAccessTypes_replacesAndSkipsWhenSameInstance() {
+        RangerGrant grant = new RangerGrant();
+
+        List<String> first = new ArrayList<>(Arrays.asList("a", "b"));
+        grant.setAccessTypes(first);
+        Assertions.assertEquals(first, grant.getAccessTypes());
+
+        // pass the same backing instance to hit the early-return branch
+        List<String> internal = grant.getAccessTypes();
+        grant.setAccessTypes(internal);
+        Assertions.assertEquals(internal, grant.getAccessTypes());
+
+        // replace with a new list and ensure contents are copied (not same ref)
+        List<String> second = new ArrayList<>(Arrays.asList("x", "y", "z"));
+        grant.setAccessTypes(second);
+        Assertions.assertEquals(second, grant.getAccessTypes());
+        Assertions.assertNotSame(second, grant.getAccessTypes());
+    }
+
+    @Test
+    public void test03_setConditions_replacesAndSkipsWhenSameInstance() {
+        RangerGrant grant = new RangerGrant();
+
+        List<RangerGrant.Condition> c1 = new ArrayList<>();
+        c1.add(new RangerGrant.Condition("k1", new ArrayList<>(Arrays.asList("v1"))));
+        grant.setConditions(c1);
+        Assertions.assertEquals(c1, grant.getConditions());
+
+        List<RangerGrant.Condition> internal = grant.getConditions();
+        grant.setConditions(internal);
+        Assertions.assertEquals(internal, grant.getConditions());
+
+        List<RangerGrant.Condition> c2 = new ArrayList<>();
+        c2.add(new RangerGrant.Condition("k2", new ArrayList<>(Arrays.asList("v2", "v3"))));
+        grant.setConditions(c2);
+        Assertions.assertEquals(c2, grant.getConditions());
+        Assertions.assertNotSame(c2, grant.getConditions());
+    }
+
+    @Test
+    public void test04_equalsAndHashCode() {
+        RangerPrincipal principal = new RangerPrincipal(RangerPrincipal.PrincipalType.GROUP, "dev");
+        List<String> access = new ArrayList<>(Arrays.asList("read"));
+        List<RangerGrant.Condition> conditions = new ArrayList<>();
+        conditions.add(new RangerGrant.Condition("loc", new ArrayList<>(Arrays.asList("us"))));
+
+        RangerGrant g1 = new RangerGrant(principal, access, conditions);
+        RangerGrant g2 = new RangerGrant(principal, new ArrayList<>(access), new ArrayList<>(conditions));
+        Assertions.assertEquals(g1, g2);
+        Assertions.assertEquals(g1.hashCode(), g2.hashCode());
+
+        g2.setPrincipal(new RangerPrincipal(RangerPrincipal.PrincipalType.USER, "charlie"));
+        Assertions.assertNotEquals(g1, g2);
+
+        Assertions.assertNotEquals(g1, null);
+        Assertions.assertNotEquals(g1, new Object());
+    }
+
+    @Test
+    public void test05_toStringWithPrincipal() {
+        RangerGrant grant = new RangerGrant();
+        grant.setPrincipal(new RangerPrincipal(RangerPrincipal.PrincipalType.ROLE, "role1"));
+        grant.setAccessTypes(new ArrayList<>(Arrays.asList("use")));
+        grant.setConditions(new ArrayList<>());
+
+        String s = grant.toString();
+        Assertions.assertTrue(s.contains("RangerGrant{"));
+        Assertions.assertTrue(s.contains("accessTypes"));
+        Assertions.assertTrue(s.contains("conditions"));
+    }
+
+    @Test
+    public void test06_conditionEqualsHashCodeToString() {
+        RangerGrant.Condition c1 = new RangerGrant.Condition("typeA", new ArrayList<>(Arrays.asList("v1", "v2")));
+        RangerGrant.Condition c2 = new RangerGrant.Condition("typeA", new ArrayList<>(Arrays.asList("v1", "v2")));
+        Assertions.assertEquals(c1, c2);
+        Assertions.assertEquals(c1.hashCode(), c2.hashCode());
+
+        c2.setType("typeB");
+        Assertions.assertNotEquals(c1, c2);
+
+        String s = c1.toString();
+        Assertions.assertTrue(s.contains("type='typeA'"));
+        Assertions.assertTrue(Objects.nonNull(c1.getValues()));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerHealth.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerHealth.java
index 113018585..32fdcc9d5 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerHealth.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerHealth.java
@@ -20,7 +20,11 @@
 package org.apache.ranger.plugin.model;
 
 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.HashMap;
 import java.util.LinkedHashMap;
@@ -29,6 +33,12 @@
 import static org.apache.ranger.plugin.model.RangerServerHealth.RangerServerStatus.DOWN;
 import static org.apache.ranger.plugin.model.RangerServerHealth.RangerServerStatus.UP;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for TestRangerHealth class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerHealth {
     @Test
     public void testRangerStatusUP() {
@@ -96,4 +106,80 @@ public void testRangerStatusDOWN() {
         Assertions.assertEquals(1, rangerHealth.getDetails().size(), "RangerHealth.getDetails()");
         Assertions.assertEquals(2, ((Map<?, ?>) rangerHealth.getDetails().get("components")).size(), "RangerHealth.getDetails('component')");
     }
+
+    @Test
+    public void testRangerStatusUnknownToStringAndImmutability() {
+        RangerServerHealth unknown = RangerServerHealth.unknown().build();
+
+        Assertions.assertEquals(RangerServerHealth.RangerServerStatus.UNKNOWN, unknown.getStatus());
+        Assertions.assertTrue(unknown.getDetails().isEmpty());
+        Assertions.assertEquals("UNKNOWN {}", unknown.toString());
+
+        try {
+            unknown.getDetails().put("x", "y");
+            Assertions.fail("details map should be unmodifiable");
+        } catch (UnsupportedOperationException expected) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testStatusInitializingAndInitFailure() {
+        RangerServerHealth initializing = RangerServerHealth.status(RangerServerHealth.RangerServerStatus.INITIALIZING)
+                .withDetail("phase", "boot").build();
+        RangerServerHealth initFailure = RangerServerHealth.status(RangerServerHealth.RangerServerStatus.INITIALIZATION_FAILURE)
+                .withDetail("error", "db").build();
+
+        Assertions.assertEquals(RangerServerHealth.RangerServerStatus.INITIALIZING, initializing.getStatus());
+        Assertions.assertEquals("boot", initializing.getDetails().get("phase"));
+
+        Assertions.assertEquals(RangerServerHealth.RangerServerStatus.INITIALIZATION_FAILURE, initFailure.getStatus());
+        Assertions.assertEquals("db", initFailure.getDetails().get("error"));
+    }
+
+    @Test
+    public void testBuilderConstructors() {
+        RangerServerHealth.Builder defaultBuilder = new RangerServerHealth.Builder();
+        RangerServerHealth def = defaultBuilder.build();
+        Assertions.assertEquals(RangerServerHealth.RangerServerStatus.UNKNOWN, def.getStatus());
+        Assertions.assertTrue(def.getDetails().isEmpty());
+
+        RangerServerHealth.Builder upBuilder = new RangerServerHealth.Builder(RangerServerHealth.RangerServerStatus.UP);
+        RangerServerHealth upHealth = upBuilder.withDetail("k", "v").build();
+        Assertions.assertEquals(RangerServerHealth.RangerServerStatus.UP, upHealth.getStatus());
+        Assertions.assertEquals("v", upHealth.getDetails().get("k"));
+
+        Map<String, Object> seed = new LinkedHashMap<>();
+        seed.put("a", 1);
+        seed.put("b", 2);
+        RangerServerHealth.Builder seeded = new RangerServerHealth.Builder(RangerServerHealth.RangerServerStatus.DOWN, seed);
+        RangerServerHealth downHealth = seeded.build();
+        Assertions.assertEquals(RangerServerHealth.RangerServerStatus.DOWN, downHealth.getStatus());
+        Assertions.assertEquals(2, downHealth.getDetails().size());
+        Assertions.assertEquals(1, downHealth.getDetails().get("a"));
+        Assertions.assertEquals(2, downHealth.getDetails().get("b"));
+    }
+
+    @Test
+    public void testEqualsAndHashCode() {
+        Map<String, Object> details1 = new LinkedHashMap<>();
+        details1.put("x", 1);
+        details1.put("y", 2);
+
+        Map<String, Object> details2 = new LinkedHashMap<>();
+        details2.put("x", 1);
+        details2.put("y", 2);
+
+        RangerServerHealth h1 = new RangerServerHealth.Builder(RangerServerHealth.RangerServerStatus.UP, details1).build();
+        RangerServerHealth h2 = new RangerServerHealth.Builder(RangerServerHealth.RangerServerStatus.UP, details2).build();
+        RangerServerHealth h3 = new RangerServerHealth.Builder(RangerServerHealth.RangerServerStatus.DOWN, details1).build();
+
+        Assertions.assertEquals(h1, h1); // reflexive
+        Assertions.assertEquals(h1, h2);
+        Assertions.assertEquals(h1.hashCode(), h2.hashCode());
+
+        Assertions.assertNotEquals(h1, h3);
+        Assertions.assertNotEquals(h1, null);
+        Assertions.assertNotEquals(h1, "not-a-health");
+    }
 }
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerMetrics.java
similarity index 56%
copy from agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java
copy to agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerMetrics.java
index d1ea46d61..7295cb9a2 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerMetrics.java
@@ -19,26 +19,29 @@
 
 package org.apache.ranger.plugin.model;
 
-import org.apache.commons.lang3.StringUtils;
 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.HashMap;
 
-public class TestRangerService {
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerMetrics class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerMetrics {
     @Test
-    public void test_configToString() {
-        RangerService svc = new RangerService("hdfs", "dev_hdfs", "HDFS", "dev_tag", new HashMap<>());
-        String        str = svc.toString();
-
-        Assertions.assertFalse(StringUtils.containsIgnoreCase(str, RangerService.CONFIG_PASSWORD));
-
-        svc.getConfigs().put(RangerService.CONFIG_PASSWORD, "test1234");
-
-        str = svc.toString();
-
-        Assertions.assertTrue(StringUtils.containsIgnoreCase(str, RangerService.CONFIG_PASSWORD));
-        Assertions.assertFalse(StringUtils.containsIgnoreCase(str, "test1234"));
-        Assertions.assertTrue(StringUtils.containsIgnoreCase(str, RangerService.MASKED_PASSWORD_VALUE));
+    public void test01_DefaultsAndSetter() {
+        RangerMetrics m = new RangerMetrics();
+        Assertions.assertNull(m.getData());
+        HashMap<String, Object> d = new HashMap<>();
+        d.put("k", "v");
+        m.setData(d);
+        Assertions.assertEquals("v", m.getData().get("k"));
     }
 }
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPluginInfo.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPluginInfo.java
new file mode 100644
index 000000000..2c7ec5514
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPluginInfo.java
@@ -0,0 +1,153 @@
+/*
+ * 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.plugin.model;
+
+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.Date;
+import java.util.HashMap;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerPluginInfo class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerPluginInfo {
+    @Test
+    public void test01_InfoMapDefaultingAndToString() {
+        RangerPluginInfo info = new RangerPluginInfo();
+        Assertions.assertNotNull(info.getInfo());
+
+        info.setInfo(null);
+        Assertions.assertNotNull(info.getInfo());
+
+        info.setServiceName("svc");
+        info.setServiceDisplayName("svc-dn");
+        info.setServiceType("type");
+        info.setServiceTypeDisplayName("type-dn");
+        info.setHostName("host");
+        info.setAppType("app");
+        info.setIpAddress("1.2.3.4");
+        info.setId(10L);
+        Date now = new Date();
+        info.setCreateTime(now);
+        info.setUpdateTime(now);
+
+        String s = info.toString();
+        Assertions.assertNotNull(s);
+        Assertions.assertTrue(s.contains("serviceName={svc}"));
+        Assertions.assertTrue(s.contains("serviceType={type}"));
+        Assertions.assertTrue(s.contains("hostName={host}"));
+    }
+
+    @Test
+    public void test02_PolicyFields() {
+        RangerPluginInfo info = new RangerPluginInfo();
+        Assertions.assertNull(info.getPolicyDownloadTime());
+        Assertions.assertNull(info.getPolicyDownloadedVersion());
+        Assertions.assertNull(info.getPolicyActivationTime());
+        Assertions.assertNull(info.getPolicyActiveVersion());
+
+        info.setPolicyDownloadTime(100L);
+        info.setPolicyDownloadedVersion(2L);
+        info.setPolicyActivationTime(200L);
+        info.setPolicyActiveVersion(3L);
+
+        Assertions.assertEquals(100L, info.getPolicyDownloadTime());
+        Assertions.assertEquals(2L, info.getPolicyDownloadedVersion());
+        Assertions.assertEquals(200L, info.getPolicyActivationTime());
+        Assertions.assertEquals(3L, info.getPolicyActiveVersion());
+
+        // ensure underlying map stores strings
+        Assertions.assertInstanceOf(String.class, info.getInfo().get(RangerPluginInfo.PLUGIN_INFO_POLICY_DOWNLOAD_TIME));
+    }
+
+    @Test
+    public void test03_TagFields() {
+        RangerPluginInfo info = new RangerPluginInfo();
+        info.setTagDownloadTime(10L);
+        info.setTagDownloadedVersion(20L);
+        info.setTagActivationTime(30L);
+        info.setTagActiveVersion(40L);
+
+        Assertions.assertEquals(10L, info.getTagDownloadTime());
+        Assertions.assertEquals(20L, info.getTagDownloadedVersion());
+        Assertions.assertEquals(30L, info.getTagActivationTime());
+        Assertions.assertEquals(40L, info.getTagActiveVersion());
+    }
+
+    @Test
+    public void test04_RoleFields() {
+        RangerPluginInfo info = new RangerPluginInfo();
+        info.setRoleDownloadTime(11L);
+        info.setRoleDownloadedVersion(22L);
+        info.setRoleActivationTime(33L);
+        info.setRoleActiveVersion(44L);
+
+        Assertions.assertEquals(11L, info.getRoleDownloadTime());
+        Assertions.assertEquals(22L, info.getRoleDownloadedVersion());
+        Assertions.assertEquals(33L, info.getRoleActivationTime());
+        Assertions.assertEquals(44L, info.getRoleActiveVersion());
+    }
+
+    @Test
+    public void test05_UserStoreFields() {
+        RangerPluginInfo info = new RangerPluginInfo();
+        info.setUserStoreDownloadTime(111L);
+        info.setUserStoreDownloadedVersion(222L);
+        info.setUserStoreActivationTime(333L);
+        info.setUserStoreActiveVersion(444L);
+
+        Assertions.assertEquals(111L, info.getUserStoreDownloadTime());
+        Assertions.assertEquals(222L, info.getUserStoreDownloadedVersion());
+        Assertions.assertEquals(333L, info.getUserStoreActivationTime());
+        Assertions.assertEquals(444L, info.getUserStoreActiveVersion());
+    }
+
+    @Test
+    public void test06_GdsFieldsAndCapabilities() {
+        RangerPluginInfo info = new RangerPluginInfo();
+        info.setGdsDownloadTime(5L);
+        info.setGdsDownloadedVersion(6L);
+        info.setGdsActivationTime(7L);
+        info.setGdsActiveVersion(8L);
+
+        Assertions.assertEquals(5L, info.getGdsDownloadTime());
+        Assertions.assertEquals(6L, info.getGdsDownloadedVersion());
+        Assertions.assertEquals(7L, info.getGdsActivationTime());
+        Assertions.assertEquals(8L, info.getGdsActiveVersion());
+
+        // capabilities store raw strings and return null on blank
+        info.setPluginCapabilities("cap1,cap2");
+        info.setAdminCapabilities("capA");
+        Assertions.assertEquals("cap1,cap2", info.getPluginCapabilities());
+        Assertions.assertEquals("capA", info.getAdminCapabilities());
+
+        info.setInfo(new HashMap<>());
+        Assertions.assertNull(info.getPluginCapabilities());
+        Assertions.assertNull(info.getAdminCapabilities());
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicy.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicy.java
index 30797e6da..467fc0f34 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicy.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicy.java
@@ -19,19 +19,38 @@
 
 package org.apache.ranger.plugin.model;
 
+import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
 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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerPolicy class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerPolicy {
     @Test
-    public void test_01_Policy_SetListMethods() {
+    public void test01_Policy_SetListMethods() {
         RangerPolicy           policy         = new RangerPolicy();
         List<RangerPolicyItem> policyItemList = getList(new RangerPolicyItem());
 
@@ -61,7 +80,7 @@ public void test_01_Policy_SetListMethods() {
     }
 
     @Test
-    public void test_02_PolicyItem_SetListMethods() {
+    public void test02_PolicyItem_SetListMethods() {
         RangerPolicyItem                policyItem = new RangerPolicyItem();
         List<RangerPolicyItemAccess>    accesses   = getList(new RangerPolicyItemAccess());
         List<String>                    users      = getList("user");
@@ -94,7 +113,7 @@ public void test_02_PolicyItem_SetListMethods() {
     }
 
     @Test
-    public void test_03_PolicyResource_SetListMethods() {
+    public void test03_PolicyResource_SetListMethods() {
         RangerPolicyResource policyResource = new RangerPolicyResource();
         List<String>         values         = getList("value");
 
@@ -106,7 +125,7 @@ public void test_03_PolicyResource_SetListMethods() {
     }
 
     @Test
-    public void test_04_PolicyItemCondition_SetListMethods() {
+    public void test04_PolicyItemCondition_SetListMethods() {
         RangerPolicyItemCondition policyItemCondition = new RangerPolicyItemCondition();
         List<String>              values              = getList("value");
 
@@ -117,6 +136,152 @@ public void test_04_PolicyItemCondition_SetListMethods() {
         Assertions.assertEquals(values.size(), policyItemCondition.getValues().size(), "RangerPolicyItemCondition.setValues()");
     }
 
+    @Test
+    public void test05_DefaultsAndPriorityAuditFlags() {
+        RangerPolicy p = new RangerPolicy();
+        Assertions.assertEquals(RangerPolicy.POLICY_PRIORITY_NORMAL, p.getPolicyPriority());
+        Assertions.assertEquals(Boolean.TRUE, p.getIsAuditEnabled());
+
+        p.setPolicyPriority(null);
+        Assertions.assertEquals(RangerPolicy.POLICY_PRIORITY_NORMAL, p.getPolicyPriority());
+
+        p.setIsAuditEnabled(null);
+        Assertions.assertEquals(Boolean.TRUE, p.getIsAuditEnabled());
+
+        p.addPolicyLabel("L1");
+        Assertions.assertTrue(p.getPolicyLabels().contains("L1"));
+    }
+
+    @Test
+    public void test06_PolicyResourceEqualsHashCodeAndFlags() {
+        RangerPolicyResource r1 = new RangerPolicyResource("db1", null, null);
+        RangerPolicyResource r2 = new RangerPolicyResource("db1", null, null);
+        Assertions.assertEquals(r1, r2);
+        Assertions.assertEquals(r1.hashCode(), r2.hashCode());
+
+        r1.setIsExcludes(null);
+        r1.setIsRecursive(null);
+        Assertions.assertEquals(Boolean.FALSE, r1.getIsExcludes());
+        Assertions.assertEquals(Boolean.FALSE, r1.getIsRecursive());
+
+        r1.setValues(Arrays.asList("a", "b"));
+        Assertions.assertEquals(Arrays.asList("a", "b"), r1.getValues());
+
+        r1.addValue("c");
+        Assertions.assertTrue(r1.getValues().contains("c"));
+        r1.addValues(Arrays.asList("x", "y"));
+        r1.addValues(new String[] {"z"});
+        Assertions.assertTrue(r1.getValues().containsAll(Arrays.asList("x", "y", "z")));
+    }
+
+    @Test
+    public void test07_PolicyItemAddRemoveApisAndEquals() {
+        RangerPolicyItem item = new RangerPolicyItem();
+        RangerPolicyItemAccess a = new RangerPolicyItemAccess("read", null);
+        item.addAccess(a);
+        item.addUsers(Arrays.asList("u1", "u2"));
+        item.addGroups(Collections.singletonList("g1"));
+        item.addRoles(Collections.singletonList("r1"));
+        item.addConditions(Collections.singletonList(new RangerPolicyItemCondition("type", Arrays.asList("v"))));
+        item.setDelegateAdmin(null);
+
+        Assertions.assertEquals(Boolean.FALSE, item.getDelegateAdmin());
+        Assertions.assertTrue(item.getUsers().contains("u1"));
+        Assertions.assertTrue(item.getGroups().contains("g1"));
+        Assertions.assertTrue(item.getRoles().contains("r1"));
+
+        Assertions.assertTrue(item.removeUser("u2"));
+        Assertions.assertTrue(item.removeGroup("g1"));
+        Assertions.assertTrue(item.removeRole("r1"));
+
+        RangerPolicyItem copy = new RangerPolicyItem(item);
+        Assertions.assertEquals(item, copy);
+        Assertions.assertEquals(item.hashCode(), copy.hashCode());
+    }
+
+    @Test
+    public void test08_DataMaskAndRowFilterItems() {
+        RangerPolicyItemDataMaskInfo dm = new RangerPolicyItemDataMaskInfo("MASK", "col > 1", "val");
+        RangerDataMaskPolicyItem dmItem = new RangerDataMaskPolicyItem(Collections.emptyList(), dm, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Boolean.TRUE);
+        Assertions.assertEquals(dm, dmItem.getDataMaskInfo());
+        Assertions.assertTrue(dmItem.toString().contains("dataMaskInfo={"));
+
+        RangerPolicyItemRowFilterInfo rf = new RangerPolicyItemRowFilterInfo("col=1");
+        RangerRowFilterPolicyItem rfItem = new RangerRowFilterPolicyItem(rf, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Boolean.FALSE);
+        Assertions.assertEquals(rf, rfItem.getRowFilterInfo());
+        Assertions.assertTrue(rfItem.toString().contains("rowFilterInfo={"));
+    }
+
+    @Test
+    public void test09_PolicySettersAndNullSafeSupplierV2() {
+        RangerPolicy p = new RangerPolicy();
+        p.setResources(new HashMap<>());
+        p.addResource(new HashMap<>()); // should do nothing harmful
+        p.setOptions(new HashMap<>());
+        p.setValiditySchedules(Collections.emptyList());
+        p.setConditions(Collections.emptyList());
+        p.setPolicyItems(Collections.emptyList());
+        p.setDenyPolicyItems(Collections.emptyList());
+        p.setAllowExceptions(Collections.emptyList());
+        p.setDenyExceptions(Collections.emptyList());
+        p.setDataMaskPolicyItems(Collections.emptyList());
+        p.setRowFilterPolicyItems(Collections.emptyList());
+
+        Assertions.assertNotNull(p.getResources());
+        Assertions.assertNotNull(p.getOptions());
+        Assertions.assertNotNull(p.getValiditySchedules());
+
+        // switch supplier to V2 and verify empty collections are immutable empty
+        RangerBaseModelObject.setNullSafeSupplier(RangerBaseModelObject.NULL_SAFE_SUPPLIER_V2);
+        p.setPolicyItems(null);
+        Assertions.assertEquals(0, p.getPolicyItems().size());
+        // revert to default
+        RangerBaseModelObject.setNullSafeSupplier((RangerBaseModelObject.NullSafeSupplier) null);
+    }
+
+    @Test
+    public void test10_AdditionalResourcesAndToString() {
+        RangerPolicy p = new RangerPolicy();
+        Map<String, RangerPolicyResource> res = new LinkedHashMap<>();
+        res.put("db", new RangerPolicyResource("db1"));
+        p.setResources(new HashMap<>());
+        p.addResource(res); // with existing base resources -> should go to additionalResources
+
+        String s = p.toString();
+        Assertions.assertTrue(s.contains("additionalResources={"));
+    }
+
+    @Test
+    public void test11_PolicyIdComparator() {
+        RangerPolicy p1 = new RangerPolicy();
+        p1.setId(5L);
+        RangerPolicy p2 = new RangerPolicy();
+        p2.setId(10L);
+
+        Assertions.assertTrue(RangerPolicy.POLICY_ID_COMPARATOR.compare(p1, p2) < 0);
+        Assertions.assertTrue(RangerPolicy.POLICY_ID_COMPARATOR.compare(p2, p1) > 0);
+        Assertions.assertEquals(0, RangerPolicy.POLICY_ID_COMPARATOR.compare(p1, p1));
+    }
+
+    @Test
+    public void test12_NestedEqualsNullPaths() {
+        RangerPolicy.RangerPolicyItemAccess a1 = new RangerPolicy.RangerPolicyItemAccess(null, null);
+        RangerPolicy.RangerPolicyItemAccess a2 = new RangerPolicy.RangerPolicyItemAccess(null, null);
+        Assertions.assertEquals(a1, a2);
+
+        RangerPolicy.RangerPolicyItemCondition c1 = new RangerPolicy.RangerPolicyItemCondition(null, null);
+        RangerPolicy.RangerPolicyItemCondition c2 = new RangerPolicy.RangerPolicyItemCondition(null, null);
+        Assertions.assertEquals(c1, c2);
+
+        RangerPolicy.RangerPolicyItemDataMaskInfo dm1 = new RangerPolicy.RangerPolicyItemDataMaskInfo();
+        RangerPolicy.RangerPolicyItemDataMaskInfo dm2 = new RangerPolicy.RangerPolicyItemDataMaskInfo();
+        Assertions.assertEquals(dm1, dm2);
+
+        RangerPolicy.RangerPolicyItemRowFilterInfo rf1 = new RangerPolicy.RangerPolicyItemRowFilterInfo();
+        RangerPolicy.RangerPolicyItemRowFilterInfo rf2 = new RangerPolicy.RangerPolicyItemRowFilterInfo();
+        Assertions.assertEquals(rf1, rf2);
+    }
+
     private <T> List<T> getList(T value) {
         List<T> ret = new ArrayList<>();
 
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyDelta.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyDelta.java
new file mode 100644
index 000000000..bedf9c7ec
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyDelta.java
@@ -0,0 +1,82 @@
+/*
+ * 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.plugin.model;
+
+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.HashMap;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerPolicyDelta class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerPolicyDelta {
+    @Test
+    public void test01_defaultsAndNullPolicyBranch() {
+        RangerPolicyDelta delta = new RangerPolicyDelta(1L, RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE, 5L, null);
+
+        Assertions.assertEquals(1L, delta.getId());
+        Assertions.assertEquals(RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE, delta.getChangeType());
+        Assertions.assertNull(delta.getServiceType());
+        Assertions.assertNull(delta.getPolicyType());
+        Assertions.assertNull(delta.getPolicyId());
+        Assertions.assertNull(delta.getZoneName());
+
+        // dedupStrings should be a no-op when policy is null
+        Map<String, String> tbl = new HashMap<>();
+        delta.dedupStrings(tbl);
+
+        String s = delta.toString();
+        Assertions.assertTrue(s.contains("id:1"));
+        Assertions.assertTrue(s.contains("POLICY_CREATE"));
+    }
+
+    @Test
+    public void test02_nonNullPolicyBranchAndGetters() {
+        RangerPolicy policy = new RangerPolicy();
+        policy.setId(99L);
+        policy.setServiceType("hive");
+        policy.setPolicyType(7);
+        policy.setZoneName("zoneA");
+
+        RangerPolicyDelta delta = new RangerPolicyDelta(2L, RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE, 6L, policy);
+
+        Assertions.assertEquals("hive", delta.getServiceType());
+        Assertions.assertEquals(7, delta.getPolicyType());
+        Assertions.assertEquals(99L, delta.getPolicyId());
+        Assertions.assertEquals("zoneA", delta.getZoneName());
+
+        Map<String, String> tbl = new HashMap<>();
+        tbl.put("hive", "hive");
+        delta.dedupStrings(tbl);
+
+        String s = delta.toString();
+        Assertions.assertTrue(s.contains("POLICY_UPDATE"));
+        Assertions.assertTrue(s.contains("policyId:[99]"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyHeader.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyHeader.java
new file mode 100644
index 000000000..84729269e
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyHeader.java
@@ -0,0 +1,83 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+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.HashMap;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerPolicyHeader class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerPolicyHeader {
+    @Test
+    public void test01_ConstructFromPolicyAndToString() {
+        RangerPolicy p = new RangerPolicy();
+        p.setId(5L);
+        p.setGuid("G");
+        p.setName("name");
+        p.setIsEnabled(Boolean.TRUE);
+        p.setService("svc");
+        p.setVersion(2L);
+        p.setPolicyType(1);
+        p.setZoneName("zone");
+        Map<String, RangerPolicyResource> res = new HashMap<>();
+        res.put("db", new RangerPolicyResource("db1"));
+        p.setResources(res);
+
+        RangerPolicyHeader hdr = new RangerPolicyHeader(p);
+        Assertions.assertEquals("svc", hdr.getService());
+        Assertions.assertEquals("name", hdr.getName());
+        Assertions.assertEquals(1, hdr.getPolicyType());
+        Assertions.assertEquals("zone", hdr.getZoneName());
+        Assertions.assertTrue(hdr.getResources().containsKey("db"));
+
+        StringBuilder sb = new StringBuilder();
+        hdr.toString(sb);
+        String s = sb.toString();
+        Assertions.assertTrue(s.contains("id={5}"));
+        Assertions.assertTrue(s.contains("guid={G}"));
+        Assertions.assertTrue(s.contains("name={name}"));
+        Assertions.assertTrue(s.contains("service={svc}"));
+        Assertions.assertTrue(s.contains("policyType={1}"));
+        Assertions.assertTrue(s.contains("zoneName={zone}"));
+    }
+
+    @Test
+    public void test02_SetResourcesDefensiveCopy() {
+        RangerPolicyHeader hdr = new RangerPolicyHeader(new RangerPolicy());
+        Map<String, RangerPolicyResource> res = new HashMap<>();
+        res.put("a", new RangerPolicyResource("v"));
+        hdr.setResources(res);
+        Assertions.assertTrue(hdr.getResources().containsKey("a"));
+        res.clear();
+        Assertions.assertTrue(hdr.getResources().containsKey("a"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
index 191c1d3a5..b823f53a2 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
@@ -25,7 +25,11 @@
 import org.apache.ranger.plugin.model.RangerPolicyResourceSignature.ResourceSerializer;
 import org.apache.ranger.plugin.model.validation.ValidationTestUtils;
 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.Arrays;
 import java.util.HashMap;
@@ -34,6 +38,12 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerPolicyResourceSignature class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerPolicyResourceSignature {
     /*
      * Format of data expected by the utility function which uses this is:
@@ -72,7 +82,7 @@ public class TestRangerPolicyResourceSignature {
     private final ValidationTestUtils utils      = new ValidationTestUtils();
 
     @Test
-    public void test_RangerPolicyResourceView_toString() {
+    public void test01_RangerPolicyResourceView_toString() {
         // null resource
         RangerPolicyResource resource   = null;
         ResourceSerializer   serializer = new ResourceSerializer(resource);
@@ -95,7 +105,7 @@ public void test_RangerPolicyResourceView_toString() {
     }
 
     @Test
-    public void test_isPolicyValidForResourceSignatureComputation() {
+    public void test02_isPolicyValidForResourceSignatureComputation() {
         // null policy is invalid
         RangerPolicy     rangerPolicy     = null;
         PolicySerializer policySerializer = new PolicySerializer(rangerPolicy);
@@ -122,7 +132,7 @@ public void test_isPolicyValidForResourceSignatureComputation() {
     }
 
     @Test
-    public void test_RangerPolicyResourceSignature() {
+    public void test03_RangerPolicyResourceSignature() {
         // String rep of a null policy is an empty string! and its hash is sha of empty string!
         RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String) null);
         Assertions.assertEquals("", signature.asString());
@@ -130,7 +140,7 @@ public void test_RangerPolicyResourceSignature() {
     }
 
     @Test
-    public void test_getResourceSignature_happyPath() {
+    public void test04_getResourceSignature_happyPath() {
         // null policy returns signature of empty resource
         RangerPolicy     policy     = null;
         PolicySerializer serializer = new PolicySerializer(policy);
@@ -141,7 +151,6 @@ public void test_getResourceSignature_happyPath() {
         Map<String, RangerPolicyResource> policyResources = utils.createPolicyResourceMap(first);
         when(policy.getResources()).thenReturn(policyResources);
         when(policy.getZoneName()).thenReturn(null);
-        when(policy.getGuid()).thenReturn("TEST_GUID");
         when(policy.getIsEnabled()).thenReturn(true);
         serializer = new PolicySerializer(policy);
         String expectedVersion = "version=1";
@@ -167,69 +176,59 @@ public void test_getResourceSignature_happyPath() {
     }
 
     @Test
-    public void test_nullRecursiveFlagIsSameAsFlase() {
+    public void test05_nullRecursiveFlagIsSameAsFlase() {
         // create two policies with resources that differ only in the recursive flag such that flags are null in one and false in another
         RangerPolicy                  policy1    = createPolicy(first);
         RangerPolicy                  policy2    = createPolicy(firstRecursiveNullOrFalse);
         RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1);
         RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2);
-        when(policy1.getGuid()).thenReturn("TEST_GUID-1");
-        when(policy2.getGuid()).thenReturn("TEST_GUID-2");
 
         Assertions.assertEquals(signature1.toString(), signature2.toString(), "Recursive flag: null is same as false");
     }
 
     @Test
-    public void test_onlyDifferByRecursiveFlag() {
+    public void test06_onlyDifferByRecursiveFlag() {
         // create two policies with resources that differ only in the recursive flag, i.e. null/false in one and true in another
         RangerPolicy policy1 = createPolicy(first);
         RangerPolicy policy2 = createPolicy(firstRecursiveFlagDifferent);
-        when(policy1.getGuid()).thenReturn("TEST_GUID-1");
-        when(policy2.getGuid()).thenReturn("TEST_GUID-2");
         RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1);
         RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2);
         Assertions.assertNotEquals(signature1.toString(), signature2.toString(), "Resources differ only by recursive flag true vs false/null");
     }
 
     @Test
-    public void test_nullExcludesFlagIsSameAsFlase() {
+    public void test07_nullExcludesFlagIsSameAsFlase() {
         // create two policies with resources that differ only in the excludes flag such that flags are null in one and false in another
         RangerPolicy policy1 = createPolicy(first);
         RangerPolicy policy2 = createPolicy(firstExcludesNullOrFalse);
-        when(policy1.getGuid()).thenReturn("TEST_GUID-1");
-        when(policy2.getGuid()).thenReturn("TEST_GUID-2");
         RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1);
         RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2);
         Assertions.assertEquals(signature1.toString(), signature2.toString(), "Excludes flag: null is same as false");
     }
 
     @Test
-    public void test_onlyDifferByExcludesFlag() {
+    public void test08_onlyDifferByExcludesFlag() {
         // create two policies with resources that differ only in the excludes flag, i.e. null/false in one and true in another
         RangerPolicy policy1 = createPolicy(first);
         RangerPolicy policy2 = createPolicy(firstExcludesFlagDifferent);
-        when(policy1.getGuid()).thenReturn("TEST_GUID-1");
-        when(policy2.getGuid()).thenReturn("TEST_GUID-2");
         RangerPolicyResourceSignature signature1 = new RangerPolicyResourceSignature(policy1);
         RangerPolicyResourceSignature signature2 = new RangerPolicyResourceSignature(policy2);
         Assertions.assertNotEquals(signature1.toString(), signature2.toString(), "Resources differ only by excludes flag true vs false/null");
     }
 
     @Test
-    public void test_integration() {
+    public void test09_integration() {
         // setup two policies with resources that are structurally different but semantically the same.
         RangerPolicy                      aPolicy   = mock(RangerPolicy.class);
         Map<String, RangerPolicyResource> resources = utils.createPolicyResourceMap(first);
         when(aPolicy.getResources()).thenReturn(resources);
         when(aPolicy.getIsEnabled()).thenReturn(true);
-        when(aPolicy.getGuid()).thenReturn("TEST_GUID-1");
         RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature(aPolicy);
 
         RangerPolicy anotherPolicy = mock(RangerPolicy.class);
         resources = utils.createPolicyResourceMap(dataSecond);
         when(anotherPolicy.getResources()).thenReturn(resources);
         when(anotherPolicy.getIsEnabled()).thenReturn(true);
-        when(anotherPolicy.getGuid()).thenReturn("TEST_GUID-2");
 
         RangerPolicyResourceSignature anotherSignature = new RangerPolicyResourceSignature(anotherPolicy);
         Assertions.assertEquals(signature, anotherSignature);
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPrincipal.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPrincipal.java
new file mode 100644
index 000000000..7b4849850
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPrincipal.java
@@ -0,0 +1,50 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerPrincipal.PrincipalType;
+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 for RangerPrincipal class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerPrincipal {
+    @Test
+    public void test01_SettersEqualsHashCodeToString() {
+        RangerPrincipal p1 = new RangerPrincipal();
+        p1.setType(PrincipalType.USER);
+        p1.setName("alice");
+
+        RangerPrincipal p2 = new RangerPrincipal(PrincipalType.USER, "alice");
+
+        Assertions.assertEquals(p1, p2);
+        Assertions.assertEquals(p1.hashCode(), p2.hashCode());
+        Assertions.assertTrue(p1.toString().contains("type=USER"));
+        Assertions.assertTrue(p1.toString().contains("name=alice"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerRole.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerRole.java
new file mode 100644
index 000000000..f0843f765
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerRole.java
@@ -0,0 +1,121 @@
+/*
+ * 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.plugin.model;
+
+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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerRole class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerRole {
+    @Test
+    public void test01_constructorAndToString() {
+        Map<String, Object> options = new HashMap<>();
+        options.put("opt1", "val1");
+        List<RangerRole.RoleMember> users = new ArrayList<>();
+        users.add(new RangerRole.RoleMember("alice", true));
+        List<RangerRole.RoleMember> groups = new ArrayList<>();
+        groups.add(new RangerRole.RoleMember("dev", false));
+        List<RangerRole.RoleMember> roles = new ArrayList<>();
+        roles.add(new RangerRole.RoleMember("data-steward", false));
+
+        RangerRole role = new RangerRole("r1", "desc", options, users, groups, roles);
+        role.setCreatedByUser("admin");
+
+        String s = role.toString();
+        Assertions.assertTrue(s.contains("name=r1"));
+        Assertions.assertTrue(s.contains("options={opt1, [val1],}"));
+        Assertions.assertTrue(s.contains("users=["));
+        Assertions.assertTrue(s.contains("groups=["));
+        Assertions.assertTrue(s.contains("roles=["));
+    }
+
+    @Test
+    public void test02_gettersSettersAndCollectionsDefault() {
+        RangerRole role = new RangerRole();
+        role.setName("n");
+        role.setDescription("d");
+        role.setOptions(null);
+        role.setUsers(null);
+        role.setGroups(null);
+        role.setRoles(null);
+        role.setCreatedByUser("c");
+
+        Assertions.assertEquals("n", role.getName());
+        Assertions.assertEquals("d", role.getDescription());
+        Assertions.assertNotNull(role.getOptions());
+        Assertions.assertNotNull(role.getUsers());
+        Assertions.assertNotNull(role.getGroups());
+        Assertions.assertNotNull(role.getRoles());
+        Assertions.assertEquals("c", role.getCreatedByUser());
+    }
+
+    @Test
+    public void test03_equalsAndHashCode() {
+        RangerRole r1 = new RangerRole();
+        r1.setName("x");
+        r1.setDescription("y");
+        r1.setOptions(new HashMap<>());
+        r1.setUsers(new ArrayList<>());
+        r1.setGroups(new ArrayList<>());
+        r1.setRoles(new ArrayList<>());
+
+        RangerRole r2 = new RangerRole();
+        r2.setName("x");
+        r2.setDescription("y");
+        r2.setOptions(new HashMap<>());
+        r2.setUsers(new ArrayList<>());
+        r2.setGroups(new ArrayList<>());
+        r2.setRoles(new ArrayList<>());
+
+        Assertions.assertEquals(r1, r2);
+        Assertions.assertEquals(r1.hashCode(), r2.hashCode());
+
+        r2.setDescription("z");
+        Assertions.assertNotEquals(r1, r2);
+    }
+
+    @Test
+    public void test04_roleMemberEqualsHashCodeToString() {
+        RangerRole.RoleMember m1 = new RangerRole.RoleMember("u1", true);
+        RangerRole.RoleMember m2 = new RangerRole.RoleMember("u1", true);
+        Assertions.assertEquals(m1, m2);
+        Assertions.assertEquals(m1.hashCode(), m2.hashCode());
+
+        m2.setIsAdmin(false);
+        Assertions.assertNotEquals(m1, m2);
+
+        String s = m1.toString();
+        Assertions.assertTrue(s.contains("u1"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZone.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZone.java
new file mode 100644
index 000000000..603faa780
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZone.java
@@ -0,0 +1,102 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerPrincipal.PrincipalType;
+import org.apache.ranger.plugin.model.RangerSecurityZone.SecurityZoneSummary;
+import org.apache.ranger.plugin.model.RangerSecurityZone.ZoneServiceSummary;
+import org.apache.ranger.plugin.model.RangerSecurityZoneV2.RangerSecurityZoneResourceBase;
+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.ArrayList;
+import java.util.HashMap;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerSecurityZone class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerSecurityZone {
+    @Test
+    public void test01_DefaultsAndSetters() {
+        RangerSecurityZone zone = new RangerSecurityZone();
+        Assertions.assertNotNull(zone.getServices());
+        Assertions.assertNotNull(zone.getAdminUsers());
+        Assertions.assertNotNull(zone.getAdminUserGroups());
+        Assertions.assertNotNull(zone.getAuditUsers());
+        Assertions.assertNotNull(zone.getAuditUserGroups());
+        Assertions.assertNotNull(zone.getTagServices());
+
+        zone.setName("zone1");
+        zone.setDescription("desc");
+        zone.setAdminRoles(new ArrayList<>());
+        zone.setAuditRoles(new ArrayList<>());
+        zone.setTagServices(new ArrayList<>());
+
+        Assertions.assertEquals("zone1", zone.getName());
+        Assertions.assertEquals("desc", zone.getDescription());
+
+        String s = zone.toString();
+        Assertions.assertTrue(s.contains("name=zone1"));
+    }
+
+    @Test
+    public void test02_ServiceNestedToString() {
+        RangerSecurityZone.RangerSecurityZoneService svc = new RangerSecurityZone.RangerSecurityZoneService();
+        svc.setResources(new ArrayList<>());
+        svc.setResourcesBaseInfo(new ArrayList<RangerSecurityZoneResourceBase>());
+        String s = svc.toString();
+        Assertions.assertTrue(s.startsWith("{resources=["));
+    }
+
+    @Test
+    public void test03_SummaryNestedSetters() {
+        SecurityZoneSummary summary = new SecurityZoneSummary();
+        summary.setName("zn");
+        summary.setDescription("desc");
+        summary.setTotalResourceCount(5L);
+        summary.setAdminCount(new HashMap<PrincipalType, Integer>());
+        summary.setAuditorCount(new HashMap<PrincipalType, Integer>());
+        summary.setTagServices(new ArrayList<String>());
+        summary.setServices(new ArrayList<ZoneServiceSummary>());
+
+        Assertions.assertEquals("zn", summary.getName());
+        Assertions.assertEquals("desc", summary.getDescription());
+        Assertions.assertEquals(5L, summary.getTotalResourceCount());
+
+        ZoneServiceSummary zss = new ZoneServiceSummary();
+        zss.setId(1L);
+        zss.setName("svc");
+        zss.setType("type");
+        zss.setDisplayName("dn");
+        zss.setResourceCount(7L);
+        Assertions.assertEquals(1L, zss.getId());
+        Assertions.assertEquals("svc", zss.getName());
+        Assertions.assertEquals("type", zss.getType());
+        Assertions.assertEquals("dn", zss.getDisplayName());
+        Assertions.assertEquals(7L, zss.getResourceCount());
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZoneHeaderInfo.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZoneHeaderInfo.java
new file mode 100644
index 000000000..5814fa781
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZoneHeaderInfo.java
@@ -0,0 +1,55 @@
+/*
+ * 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.plugin.model;
+
+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 for RangerSecurityZoneHeaderInfo class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerSecurityZoneHeaderInfo {
+    @Test
+    public void test01_defaultConstructorAndToString() {
+        RangerSecurityZoneHeaderInfo info = new RangerSecurityZoneHeaderInfo();
+        Assertions.assertEquals(-1L, info.getId());
+        Assertions.assertEquals("", info.getName());
+        String s = info.toString(new StringBuilder()).toString();
+        Assertions.assertTrue(s.contains("id={-1}"));
+        Assertions.assertTrue(s.contains("isEnabled={true}"));
+    }
+
+    @Test
+    public void test02_paramConstructorAndSetters() {
+        RangerSecurityZoneHeaderInfo info = new RangerSecurityZoneHeaderInfo(5L, "zone");
+        Assertions.assertEquals(5L, info.getId());
+        Assertions.assertEquals("zone", info.getName());
+
+        info.setName("z2");
+        Assertions.assertEquals("z2", info.getName());
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZoneV2.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZoneV2.java
new file mode 100644
index 000000000..a7ae1bf09
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerSecurityZoneV2.java
@@ -0,0 +1,144 @@
+/*
+ * 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.plugin.model;
+
+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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerSecurityZoneV2 class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerSecurityZoneV2 {
+    @Test
+    public void test01_defaultsAndSetters() {
+        RangerSecurityZoneV2 v2 = new RangerSecurityZoneV2();
+        Assertions.assertNotNull(v2.getServices());
+        Assertions.assertNotNull(v2.getTagServices());
+        Assertions.assertNotNull(v2.getAdmins());
+        Assertions.assertNotNull(v2.getAuditors());
+
+        v2.setName("nz");
+        v2.setDescription("desc");
+        v2.setAdmins(new ArrayList<>());
+        v2.setAuditors(new ArrayList<>());
+        v2.setTagServices(new ArrayList<>());
+        v2.setServices(null);
+
+        Assertions.assertEquals("nz", v2.getName());
+        Assertions.assertEquals("desc", v2.getDescription());
+        Assertions.assertNotNull(v2.getServices());
+    }
+
+    @Test
+    public void test02_convertFromV1AndBack() {
+        RangerSecurityZone v1 = new RangerSecurityZone();
+        v1.setId(10L);
+        v1.setGuid("g");
+        v1.setIsEnabled(Boolean.TRUE);
+        v1.setCreatedBy("creator");
+        v1.setUpdatedBy("upd");
+        v1.setName("zone1");
+        v1.setDescription("d");
+        v1.setTagServices(new ArrayList<>());
+        v1.getTagServices().add("tags1");
+        v1.setAdminUsers(new ArrayList<>());
+        v1.getAdminUsers().add("u1");
+        v1.setAdminUserGroups(new ArrayList<>());
+        v1.getAdminUserGroups().add("g1");
+        v1.setAdminRoles(new ArrayList<>());
+        v1.getAdminRoles().add("r1");
+        v1.setAuditUsers(new ArrayList<>());
+        v1.getAuditUsers().add("u2");
+        v1.setAuditUserGroups(new ArrayList<>());
+        v1.getAuditUserGroups().add("g2");
+        v1.setAuditRoles(new ArrayList<>());
+        v1.getAuditRoles().add("r2");
+
+        Map<String, RangerSecurityZone.RangerSecurityZoneService> services = new HashMap<>();
+        RangerSecurityZone.RangerSecurityZoneService v1svc = new RangerSecurityZone.RangerSecurityZoneService();
+        v1svc.setResources(new ArrayList<>());
+        HashMap<String, List<String>> resMap = new HashMap<>();
+        resMap.put("db", new ArrayList<>());
+        resMap.get("db").add("sales");
+        v1svc.getResources().add(resMap);
+        v1svc.setResourcesBaseInfo(new ArrayList<>());
+        RangerSecurityZoneV2.RangerSecurityZoneResourceBase base = new RangerSecurityZoneV2.RangerSecurityZoneResourceBase();
+        base.setId(1L);
+        v1svc.getResourcesBaseInfo().add(base);
+        services.put("hive", v1svc);
+        v1.setServices(services);
+
+        RangerSecurityZoneV2 v2 = new RangerSecurityZoneV2(v1);
+        Assertions.assertEquals("zone1", v2.getName());
+        Assertions.assertEquals(1, v2.getServices().get("hive").getResources().size());
+        Assertions.assertEquals(3, v2.getAdmins().size());
+        Assertions.assertEquals(3, v2.getAuditors().size());
+
+        RangerSecurityZone back = v2.toV1();
+        Assertions.assertEquals(v1.getId(), back.getId());
+        Assertions.assertEquals(v1.getGuid(), back.getGuid());
+        Assertions.assertEquals(v1.getIsEnabled(), back.getIsEnabled());
+        Assertions.assertEquals("zone1", back.getName());
+        Assertions.assertEquals("d", back.getDescription());
+        Assertions.assertEquals(v1.getTagServices(), back.getTagServices());
+        Assertions.assertTrue(back.getAdminUsers().contains("u1"));
+        Assertions.assertTrue(back.getAdminUserGroups().contains("g1"));
+        Assertions.assertTrue(back.getAdminRoles().contains("r1"));
+        Assertions.assertTrue(back.getAuditUsers().contains("u2"));
+        Assertions.assertTrue(back.getAuditUserGroups().contains("g2"));
+        Assertions.assertTrue(back.getAuditRoles().contains("r2"));
+        Assertions.assertEquals(resMap, back.getServices().get("hive").getResources().get(0));
+        Assertions.assertEquals(1, back.getServices().get("hive").getResourcesBaseInfo().size());
+    }
+
+    @Test
+    public void test03_nestedToStringCoverage() {
+        RangerSecurityZoneV2.RangerSecurityZoneServiceV2 svc = new RangerSecurityZoneV2.RangerSecurityZoneServiceV2();
+        List<RangerSecurityZoneV2.RangerSecurityZoneResource> resList = new ArrayList<>();
+        Map<String, List<String>> res = new HashMap<>();
+        res.put("path", new ArrayList<>());
+        res.get("path").add("/data");
+        RangerSecurityZoneV2.RangerSecurityZoneResourceBase base = new RangerSecurityZoneV2.RangerSecurityZoneResourceBase();
+        base.setId(11L);
+        RangerSecurityZoneV2.RangerSecurityZoneResource rs = new RangerSecurityZoneV2.RangerSecurityZoneResource(res,
+                base);
+        resList.add(rs);
+        svc.setResources(resList);
+
+        String s1 = svc.toString();
+        Assertions.assertTrue(s1.contains("resources=["));
+        String s2 = rs.toString();
+        Assertions.assertTrue(s2.contains("resource-def-name=path"));
+        String s3 = base.toString();
+        Assertions.assertTrue(s3.contains("id=11"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java
index d1ea46d61..baa3ebd15 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java
@@ -21,13 +21,23 @@
 
 import org.apache.commons.lang3.StringUtils;
 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.HashMap;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerService class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerService {
     @Test
-    public void test_configToString() {
+    public void test01_configToString() {
         RangerService svc = new RangerService("hdfs", "dev_hdfs", "HDFS", "dev_tag", new HashMap<>());
         String        str = svc.toString();
 
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceDef.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceDef.java
new file mode 100644
index 000000000..408b18b01
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceDef.java
@@ -0,0 +1,348 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+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.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @generated by Cursor
+ * @description <Unit Test for RangerServiceDef class>
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerServiceDef {
+    @Test
+    public void test01_DefaultsAndSetters() {
+        RangerServiceDef def = new RangerServiceDef();
+        def.setName("name");
+        def.setDisplayName("dn");
+        def.setImplClass("impl");
+        def.setLabel("label");
+        def.setDescription("desc");
+        def.setRbKeyLabel("rbl");
+        def.setRbKeyDescription("rbd");
+        def.setOptions(new HashMap<String, String>() {
+            {
+                put("k", "v");
+            }
+        });
+        def.setConfigs(new ArrayList<RangerServiceDef.RangerServiceConfigDef>());
+        def.setResources(new ArrayList<RangerResourceDef>());
+        def.setAccessTypes(new ArrayList<RangerAccessTypeDef>());
+        def.setPolicyConditions(new ArrayList<RangerPolicyConditionDef>());
+        def.setContextEnrichers(new ArrayList<RangerServiceDef.RangerContextEnricherDef>());
+        def.setEnums(new ArrayList<RangerEnumDef>());
+        def.setMarkerAccessTypes(new ArrayList<RangerAccessTypeDef>());
+
+        Assertions.assertEquals("name", def.getName());
+        Assertions.assertEquals("dn", def.getDisplayName());
+        Assertions.assertEquals("impl", def.getImplClass());
+        Assertions.assertEquals("label", def.getLabel());
+        Assertions.assertEquals("desc", def.getDescription());
+        Assertions.assertTrue(def.getOptions().containsKey("k"));
+
+        String s = def.toString();
+        Assertions.assertTrue(s.contains("RangerServiceDef={"));
+        Assertions.assertTrue(s.contains("name={name}"));
+        Assertions.assertTrue(s.contains("displayName={dn}"));
+    }
+
+    @Test
+    public void test02_RangerEnumDefDefaultIndex() {
+        List<RangerEnumElementDef> elements = new ArrayList<>();
+        elements.add(new RangerEnumElementDef(1L, "e1", "l1", "rb1"));
+        elements.add(new RangerEnumElementDef(2L, "e2", "l2", "rb2"));
+
+        RangerEnumDef enumDef = new RangerEnumDef(1L, "en", elements, null);
+        enumDef.setDefaultIndex(5); // out of bounds -> should clamp to 0
+        Assertions.assertEquals(0, enumDef.getDefaultIndex());
+
+        enumDef.setDefaultIndex(1);
+        Assertions.assertEquals(1, enumDef.getDefaultIndex());
+    }
+
+    @Test
+    public void test03_ResourceDefDefaultsAndSetters() {
+        RangerResourceDef r = new RangerResourceDef();
+        r.setLevel(null);
+        r.setMandatory(null);
+        r.setLookupSupported(null);
+        r.setRecursiveSupported(null);
+        r.setExcludesSupported(null);
+        r.setMatcherOptions(new HashMap<String, String>() {
+            {
+                put("m", "o");
+            }
+        });
+        r.setAccessTypeRestrictions(new HashSet<String>());
+
+        Assertions.assertEquals(Integer.valueOf(1), r.getLevel());
+        Assertions.assertEquals(Boolean.FALSE, r.getMandatory());
+        Assertions.assertEquals(Boolean.FALSE, r.getLookupSupported());
+        Assertions.assertEquals(Boolean.FALSE, r.getRecursiveSupported());
+        Assertions.assertEquals(Boolean.FALSE, r.getExcludesSupported());
+        Assertions.assertTrue(r.getMatcherOptions().containsKey("m"));
+    }
+
+    @Test
+    public void test04_setMarkerAccessTypesAndDefaultDefs() {
+        RangerServiceDef def = new RangerServiceDef();
+        // verify defaulting of dataMaskDef/rowFilterDef when set to null
+        def.setDataMaskDef(null);
+        def.setRowFilterDef(null);
+        Assertions.assertNotNull(def.getDataMaskDef());
+        Assertions.assertNotNull(def.getRowFilterDef());
+
+        // verify setMarkerAccessTypes clears and adds
+        List<RangerAccessTypeDef> marker = new ArrayList<>();
+        marker.add(new RangerAccessTypeDef(1L, "m1", "lbl", "rb", null));
+        def.setMarkerAccessTypes(marker);
+        Assertions.assertEquals(1, def.getMarkerAccessTypes().size());
+        def.setMarkerAccessTypes(new ArrayList<RangerAccessTypeDef>());
+        Assertions.assertTrue(def.getMarkerAccessTypes().isEmpty());
+    }
+
+    @Test
+    public void test05_ServiceDefSettersSameRefAndClear() {
+        RangerServiceDef def = new RangerServiceDef();
+
+        List<RangerServiceDef.RangerServiceConfigDef> cfg = new ArrayList<>();
+        cfg.add(new RangerServiceDef.RangerServiceConfigDef());
+        def.setConfigs(cfg);
+        Assertions.assertEquals(1, def.getConfigs().size());
+
+        List<RangerResourceDef> res = new ArrayList<>();
+        res.add(new RangerResourceDef());
+        def.setResources(res);
+        Assertions.assertEquals(1, def.getResources().size());
+
+        List<RangerAccessTypeDef> at = new ArrayList<>();
+        at.add(new RangerAccessTypeDef("read"));
+        def.setAccessTypes(at);
+        Assertions.assertEquals(1, def.getAccessTypes().size());
+
+        List<RangerServiceDef.RangerPolicyConditionDef> pc = new ArrayList<>();
+        pc.add(new RangerServiceDef.RangerPolicyConditionDef());
+        def.setPolicyConditions(pc);
+        Assertions.assertEquals(1, def.getPolicyConditions().size());
+
+        List<RangerServiceDef.RangerContextEnricherDef> ce = new ArrayList<>();
+        ce.add(new RangerServiceDef.RangerContextEnricherDef());
+        def.setContextEnrichers(ce);
+        Assertions.assertEquals(1, def.getContextEnrichers().size());
+
+        List<RangerEnumDef> enums = new ArrayList<>();
+        enums.add(new RangerEnumDef());
+        def.setEnums(enums);
+        Assertions.assertEquals(1, def.getEnums().size());
+
+        // same-ref early-return: mutate the returned list and set the same reference
+        List<RangerResourceDef> sameResRef = def.getResources();
+        sameResRef.add(new RangerResourceDef());
+        def.setResources(sameResRef);
+        Assertions.assertEquals(2, def.getResources().size());
+
+        // now clear each by passing null
+        def.setConfigs(null);
+        def.setResources(null);
+        def.setAccessTypes(null);
+        def.setPolicyConditions(null);
+        def.setContextEnrichers(null);
+        def.setEnums(null);
+        Assertions.assertEquals(0, def.getConfigs().size());
+        Assertions.assertEquals(0, def.getResources().size());
+        Assertions.assertEquals(0, def.getAccessTypes().size());
+        Assertions.assertEquals(0, def.getPolicyConditions().size());
+        Assertions.assertEquals(0, def.getContextEnrichers().size());
+        Assertions.assertEquals(0, def.getEnums().size());
+    }
+
+    @Test
+    public void test06_ServiceConfigDefDefaultsEqualsAndToString() {
+        RangerServiceDef.RangerServiceConfigDef c1 = new RangerServiceDef.RangerServiceConfigDef();
+        c1.setMandatory(null);
+        Assertions.assertEquals(Boolean.FALSE, c1.getMandatory());
+        String s = c1.toString();
+        Assertions.assertTrue(s.contains("RangerServiceConfigDef={"));
+
+        RangerServiceDef.RangerServiceConfigDef c2 = new RangerServiceDef.RangerServiceConfigDef();
+        Assertions.assertEquals(c1, c2);
+        Assertions.assertEquals(c1.hashCode(), c2.hashCode());
+    }
+
+    @Test
+    public void test07_AccessTypeDefImpliedGrantsAndDedup() {
+        RangerAccessTypeDef at = new RangerAccessTypeDef();
+        at.setImpliedGrants(null);
+        Assertions.assertTrue(at.getImpliedGrants().isEmpty());
+
+        List<String> grants = new ArrayList<>(Arrays.asList(new String("read"), new String("write")));
+        at.setImpliedGrants(grants);
+        Assertions.assertTrue(at.getImpliedGrants().contains("read"));
+
+        Map<String, String> tbl = new HashMap<>();
+        at.dedupStrings(tbl);
+
+        String str = at.toString();
+        Assertions.assertTrue(str.contains("impliedGrants={"));
+    }
+
+    @Test
+    public void test08_PolicyConditionDefDefaultsEquals() {
+        RangerServiceDef.RangerPolicyConditionDef pc = new RangerServiceDef.RangerPolicyConditionDef();
+        pc.setEvaluatorOptions(null);
+        Assertions.assertNotNull(pc.getEvaluatorOptions());
+
+        RangerServiceDef.RangerPolicyConditionDef pc2 = new RangerServiceDef.RangerPolicyConditionDef();
+        Assertions.assertEquals(pc, pc2);
+        Assertions.assertEquals(pc.hashCode(), pc2.hashCode());
+    }
+
+    @Test
+    public void test09_ContextEnricherDefDefaultsEquals() {
+        RangerServiceDef.RangerContextEnricherDef ce = new RangerServiceDef.RangerContextEnricherDef();
+        ce.setEnricherOptions(null);
+        Assertions.assertNotNull(ce.getEnricherOptions());
+
+        RangerServiceDef.RangerContextEnricherDef ce2 = new RangerServiceDef.RangerContextEnricherDef();
+        Assertions.assertEquals(ce, ce2);
+        Assertions.assertEquals(ce.hashCode(), ce2.hashCode());
+    }
+
+    @Test
+    public void test10_DataMaskTypeDefDefaultsEquals() {
+        RangerServiceDef.RangerDataMaskTypeDef mt1 = new RangerServiceDef.RangerDataMaskTypeDef();
+        mt1.setDataMaskOptions(null);
+        Assertions.assertNotNull(mt1.getDataMaskOptions());
+
+        RangerServiceDef.RangerDataMaskTypeDef mt2 = new RangerServiceDef.RangerDataMaskTypeDef();
+        Assertions.assertEquals(mt1, mt2);
+        Assertions.assertEquals(mt1.hashCode(), mt2.hashCode());
+    }
+
+    @Test
+    public void test11_DataMaskDefSettersSameRefNullAndToString() {
+        RangerServiceDef.RangerDataMaskDef dm = new RangerServiceDef.RangerDataMaskDef();
+        Assertions.assertTrue(dm.getMaskTypes().isEmpty());
+        Assertions.assertTrue(dm.getAccessTypes().isEmpty());
+        Assertions.assertTrue(dm.getResources().isEmpty());
+
+        List<RangerServiceDef.RangerDataMaskTypeDef> mts = new ArrayList<>();
+        mts.add(new RangerServiceDef.RangerDataMaskTypeDef());
+        dm.setMaskTypes(mts);
+        List<RangerAccessTypeDef> ats = new ArrayList<>();
+        ats.add(new RangerAccessTypeDef("read"));
+        dm.setAccessTypes(ats);
+        List<RangerResourceDef> rs = new ArrayList<>();
+        rs.add(new RangerResourceDef());
+        dm.setResources(rs);
+        Assertions.assertEquals(1, dm.getMaskTypes().size());
+        Assertions.assertEquals(1, dm.getAccessTypes().size());
+        Assertions.assertEquals(1, dm.getResources().size());
+
+        // same-ref early return
+        List<RangerServiceDef.RangerDataMaskTypeDef> sameMt = dm.getMaskTypes();
+        sameMt.add(new RangerServiceDef.RangerDataMaskTypeDef());
+        dm.setMaskTypes(sameMt);
+        Assertions.assertEquals(2, dm.getMaskTypes().size());
+
+        // null to clear
+        dm.setMaskTypes(null);
+        dm.setAccessTypes(null);
+        dm.setResources(null);
+        Assertions.assertEquals(0, dm.getMaskTypes().size());
+        Assertions.assertEquals(0, dm.getAccessTypes().size());
+        Assertions.assertEquals(0, dm.getResources().size());
+
+        String s = dm.toString();
+        Assertions.assertTrue(s.contains("RangerDataMaskDef={"));
+    }
+
+    @Test
+    public void test12_RowFilterDefSettersSameRefNullAndToString() {
+        RangerServiceDef.RangerRowFilterDef rf = new RangerServiceDef.RangerRowFilterDef();
+        Assertions.assertTrue(rf.getAccessTypes().isEmpty());
+        Assertions.assertTrue(rf.getResources().isEmpty());
+
+        List<RangerAccessTypeDef> ats = new ArrayList<>();
+        ats.add(new RangerAccessTypeDef("read"));
+        rf.setAccessTypes(ats);
+        List<RangerResourceDef> rs = new ArrayList<>();
+        rs.add(new RangerResourceDef());
+        rf.setResources(rs);
+        Assertions.assertEquals(1, rf.getAccessTypes().size());
+        Assertions.assertEquals(1, rf.getResources().size());
+
+        // same-ref early return
+        List<RangerAccessTypeDef> sameAts = rf.getAccessTypes();
+        sameAts.add(new RangerAccessTypeDef("write"));
+        rf.setAccessTypes(sameAts);
+        Assertions.assertEquals(2, rf.getAccessTypes().size());
+
+        // null to clear
+        rf.setAccessTypes(null);
+        rf.setResources(null);
+        Assertions.assertEquals(0, rf.getAccessTypes().size());
+        Assertions.assertEquals(0, rf.getResources().size());
+
+        String s = rf.toString();
+        Assertions.assertTrue(s.contains("RangerRowFilterDef={"));
+    }
+
+    @Test
+    public void test13_EnumDefSetElementsSameRefAndDedup() {
+        RangerEnumElementDef e1 = new RangerEnumElementDef(1L, new String("e1"), new String("l1"), new String("rb1"));
+        List<RangerEnumElementDef> elements = new ArrayList<>();
+        elements.add(e1);
+
+        RangerEnumDef enumDef = new RangerEnumDef(1L, new String("en"), elements, 0);
+        enumDef.setDefaultIndex(10); // out of bounds -> set to 0
+        Assertions.assertEquals(0, enumDef.getDefaultIndex());
+
+        // same-ref early return (size remains unchanged when setting same list)
+        List<RangerEnumElementDef> sameRef = enumDef.getElements();
+        sameRef.add(new RangerEnumElementDef(2L, "e2", "l2", "rb2"));
+        enumDef.setElements(sameRef);
+        Assertions.assertEquals(2, enumDef.getElements().size());
+
+        Map<String, String> tbl = new HashMap<>();
+        enumDef.dedupStrings(tbl);
+
+        String s = enumDef.toString();
+        Assertions.assertTrue(s.contains("RangerEnumDef={"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceHeaderInfo.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceHeaderInfo.java
new file mode 100644
index 000000000..87f2c3cae
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceHeaderInfo.java
@@ -0,0 +1,72 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
+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 for RangerServiceHeaderInfo class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerServiceHeaderInfo {
+    @Test
+    public void test01_DefaultConstructor() {
+        RangerServiceHeaderInfo info = new RangerServiceHeaderInfo();
+        Assertions.assertEquals(-1L, info.getId());
+        Assertions.assertEquals("", info.getName());
+        Assertions.assertEquals(Boolean.TRUE, info.getIsEnabled());
+    }
+
+    @Test
+    public void test02_IdNameAndTagConstructor() {
+        RangerServiceHeaderInfo info = new RangerServiceHeaderInfo(1L, "svc", true);
+        Assertions.assertEquals(1L, info.getId());
+        Assertions.assertEquals("svc", info.getName());
+        Assertions.assertEquals(Boolean.TRUE, info.getIsTagService());
+        Assertions.assertEquals(Boolean.FALSE, info.getIsGdsService());
+    }
+
+    @Test
+    public void test03_WithTypeSetsTagFlag() {
+        RangerServiceHeaderInfo tagInfo = new RangerServiceHeaderInfo(2L, "tagSvc", "Tag Service", EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME);
+        Assertions.assertEquals(Boolean.TRUE, tagInfo.getIsTagService());
+
+        RangerServiceHeaderInfo other = new RangerServiceHeaderInfo(3L, "hdfsSvc", "HDFS", "hdfs");
+        Assertions.assertEquals(Boolean.FALSE, other.getIsTagService());
+    }
+
+    @Test
+    public void test04_WithTypeAndEnabled() {
+        RangerServiceHeaderInfo info = new RangerServiceHeaderInfo(4L, "svc4", "dn4", "hive", Boolean.FALSE);
+        Assertions.assertEquals(4L, info.getId());
+        Assertions.assertEquals("svc4", info.getName());
+        Assertions.assertEquals("dn4", info.getDisplayName());
+        Assertions.assertEquals("hive", info.getType());
+        Assertions.assertEquals(Boolean.FALSE, info.getIsEnabled());
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceResource.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceResource.java
new file mode 100644
index 000000000..eb79d5705
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceResource.java
@@ -0,0 +1,83 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+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.HashMap;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerServiceResource class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerServiceResource {
+    @Test
+    public void test01_SettersAndToString() {
+        Map<String, RangerPolicyResource> elements = new HashMap<>();
+        elements.put("db", new RangerPolicyResource("db1"));
+
+        Map<String, String> addl = new HashMap<>();
+        addl.put("k", "v");
+
+        RangerServiceResource rsr = new RangerServiceResource("guid-1", "svc", elements, "sig", "owner", addl);
+
+        Assertions.assertEquals("svc", rsr.getServiceName());
+        Assertions.assertEquals("sig", rsr.getResourceSignature());
+        Assertions.assertEquals("owner", rsr.getOwnerUser());
+        Assertions.assertEquals(elements, rsr.getResourceElements());
+        Assertions.assertEquals(addl, rsr.getAdditionalInfo());
+
+        String s = rsr.toString();
+        Assertions.assertTrue(s.contains("RangerServiceResource={"));
+        Assertions.assertTrue(s.contains("serviceName={svc}"));
+        Assertions.assertTrue(s.contains("resourceSignature={sig}"));
+    }
+
+    @Test
+    public void test02_dedupStrings() {
+        RangerServiceResource rsr = new RangerServiceResource();
+        rsr.setServiceName(new String("svc"));
+        rsr.setOwnerUser(new String("owner"));
+        Map<String, RangerPolicyResource> elements = new HashMap<>();
+        elements.put(new String("db"), new RangerPolicyResource("db1"));
+        rsr.setResourceElements(elements);
+        Map<String, String> addl = new HashMap<>();
+        addl.put(new String("k"), new String("v"));
+        rsr.setAdditionalInfo(addl);
+
+        Map<String, String> tbl = new HashMap<>();
+        rsr.dedupStrings(tbl);
+
+        // ensure dedup runs without altering semantics
+        Assertions.assertEquals("svc", rsr.getServiceName());
+        Assertions.assertEquals("owner", rsr.getOwnerUser());
+        Assertions.assertTrue(rsr.getResourceElements().containsKey("db"));
+        Assertions.assertEquals("v", rsr.getAdditionalInfo().get("k"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceResourceWithTags.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceResourceWithTags.java
new file mode 100644
index 000000000..f24a5b508
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceResourceWithTags.java
@@ -0,0 +1,59 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @generated by Cursor
+ * @description <Unit Test for RangerServiceResourceWithTags class>
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerServiceResourceWithTags {
+    @Test
+    public void test01_AssociatedTagsToString() {
+        RangerServiceResourceWithTags r = new RangerServiceResourceWithTags();
+        r.setServiceName("svc");
+        r.setResourceElements(new HashMap<String, RangerPolicyResource>() {
+            {
+                put("db", new RangerPolicyResource("db1"));
+            }
+        });
+
+        List<RangerTag> tags = new ArrayList<>();
+        tags.add(new RangerTag("t1", new HashMap<String, String>()));
+        r.setAssociatedTags(tags);
+
+        String s = r.toString();
+        Assertions.assertTrue(s.contains("RangerServiceResourceWithTags={"));
+        Assertions.assertTrue(s.contains("associatedTags=["));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceTags.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceTags.java
new file mode 100644
index 000000000..ba8bb2f70
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerServiceTags.java
@@ -0,0 +1,114 @@
+/*
+ * 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.plugin.model;
+
+import org.apache.ranger.plugin.util.ServiceTags;
+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.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerServiceTags class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerServiceTags {
+    @Test
+    public void test01_DefaultsAndSetters() {
+        RangerServiceTags rst = new RangerServiceTags();
+        Assertions.assertEquals(RangerServiceTags.OP_SET, rst.getOp());
+        Assertions.assertNotNull(rst.getTagDefinitions());
+        Assertions.assertNotNull(rst.getTags());
+        Assertions.assertNotNull(rst.getServiceResources());
+        Assertions.assertNotNull(rst.getResourceToTagIds());
+
+        rst.setOp(RangerServiceTags.OP_REPLACE);
+        rst.setServiceName("svc");
+        rst.setTagVersion(5L);
+        rst.setTagUpdateTime(new Date(0));
+
+        Assertions.assertEquals(RangerServiceTags.OP_REPLACE, rst.getOp());
+        Assertions.assertEquals("svc", rst.getServiceName());
+        Assertions.assertEquals(5L, rst.getTagVersion());
+        Assertions.assertEquals(new Date(0), rst.getTagUpdateTime());
+
+        String s = rst.toString();
+        Assertions.assertTrue(s.contains("RangerServiceTags={"));
+    }
+
+    @Test
+    public void test02_ConvertToServiceTagsAndBack() {
+        RangerServiceTags rst = new RangerServiceTags();
+        rst.setOp(RangerServiceTags.OP_SET);
+        rst.setServiceName("svc");
+        rst.setTagVersion(10L);
+        rst.setTagUpdateTime(new Date(1000));
+
+        Map<Long, RangerTagDef> tagDefs = new HashMap<>();
+        Map<Long, RangerTag> tags = new HashMap<>();
+        List<RangerServiceResource> serviceResources = new ArrayList<>();
+        Map<Long, List<Long>> r2t = new HashMap<>();
+
+        rst.setTagDefinitions(tagDefs);
+        rst.setTags(tags);
+        rst.setServiceResources(serviceResources);
+        rst.setResourceToTagIds(r2t);
+
+        ServiceTags st = RangerServiceTags.toServiceTags(rst);
+        Assertions.assertNotNull(st);
+        Assertions.assertEquals(ServiceTags.OP_ADD_OR_UPDATE, st.getOp());
+        Assertions.assertEquals("svc", st.getServiceName());
+        Assertions.assertEquals(10L, st.getTagVersion());
+        Assertions.assertEquals(new Date(1000), st.getTagUpdateTime());
+        Assertions.assertSame(tagDefs, st.getTagDefinitions());
+        Assertions.assertSame(tags, st.getTags());
+        Assertions.assertSame(serviceResources, st.getServiceResources());
+        Assertions.assertSame(r2t, st.getResourceToTagIds());
+
+        RangerServiceTags rstBack = RangerServiceTags.toRangerServiceTags(st);
+        Assertions.assertNotNull(rstBack);
+        Assertions.assertEquals(RangerServiceTags.OP_SET, rstBack.getOp());
+        Assertions.assertEquals("svc", rstBack.getServiceName());
+        Assertions.assertEquals(10L, rstBack.getTagVersion());
+        Assertions.assertEquals(new Date(1000), rstBack.getTagUpdateTime());
+    }
+
+    @Test
+    public void test03_NullConversionsAndToStringBuilder() {
+        Assertions.assertNull(RangerServiceTags.toServiceTags(null));
+        Assertions.assertNull(RangerServiceTags.toRangerServiceTags((ServiceTags) null));
+
+        RangerServiceTags rst = new RangerServiceTags();
+        StringBuilder sb = new StringBuilder();
+        StringBuilder out = rst.toString(sb);
+        Assertions.assertSame(sb, out);
+        Assertions.assertTrue(out.toString().contains("RangerServiceTags={"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTag.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTag.java
new file mode 100644
index 000000000..5b7d45f34
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTag.java
@@ -0,0 +1,96 @@
+/*
+ * 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.plugin.model;
+
+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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerTag class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerTag {
+    @Test
+    public void test01_constructorsAndSetters() {
+        RangerTag tag = new RangerTag();
+        tag.setGuid("g1");
+        tag.setType("t1");
+        tag.setOwner(RangerTag.OWNER_GLOBAL);
+        Map<String, String> attrs = new HashMap<>();
+        attrs.put("k", "v");
+        tag.setAttributes(attrs);
+        Map<String, Object> opts = new HashMap<>();
+        opts.put(RangerTag.OPTION_TAG_VALIDITY_PERIODS, "true");
+        tag.setOptions(opts);
+        List<RangerValiditySchedule> vp = new ArrayList<>();
+        vp.add(new RangerValiditySchedule());
+        tag.setValidityPeriods(vp);
+
+        Assertions.assertEquals("g1", tag.getGuid());
+        Assertions.assertEquals("t1", tag.getType());
+        Assertions.assertEquals(RangerTag.OWNER_GLOBAL, tag.getOwner());
+        Assertions.assertEquals(attrs, tag.getAttributes());
+        Assertions.assertEquals(opts, tag.getOptions());
+        Assertions.assertEquals(vp, tag.getValidityPeriods());
+    }
+
+    @Test
+    public void test02_dedupStringsAndToString() {
+        Map<String, String> attrs = new HashMap<>();
+        attrs.put("a", "b");
+        Map<String, Object> opts = new HashMap<>();
+        opts.put("x", "y");
+        RangerTag tag = new RangerTag("g", "type", attrs, RangerTag.OWNER_SERVICERESOURCE, opts, null);
+
+        Map<String, String> tbl = new HashMap<>();
+        tbl.put("type", "type");
+        int beforeSize = tbl.size();
+        tag.dedupStrings(tbl);
+        Assertions.assertTrue(tbl.size() >= beforeSize);
+
+        String s = tag.toString();
+        Assertions.assertTrue(s.contains("RangerTag={"));
+        Assertions.assertTrue(s.contains("type={type}"));
+    }
+
+    @Test
+    public void test03_equalsAndHashCode() {
+        RangerTag t1 = new RangerTag("g", "type", new HashMap<>(), RangerTag.OWNER_SERVICERESOURCE, new HashMap<>(),
+                new ArrayList<>());
+        RangerTag t2 = new RangerTag("g", "type", new HashMap<>(), RangerTag.OWNER_SERVICERESOURCE, new HashMap<>(),
+                new ArrayList<>());
+        Assertions.assertEquals(t1, t2);
+        Assertions.assertEquals(t1.hashCode(), t2.hashCode());
+
+        t2.setType("type2");
+        Assertions.assertNotEquals(t1, t2);
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTagDef.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTagDef.java
new file mode 100644
index 000000000..aebe453dd
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTagDef.java
@@ -0,0 +1,82 @@
+/*
+ * 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.plugin.model;
+
+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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerTagDef class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerTagDef {
+    @Test
+    public void test01_defaultsAndSetters() {
+        RangerTagDef def = new RangerTagDef();
+        Assertions.assertEquals("", def.getName());
+        Assertions.assertEquals("Internal", def.getSource());
+
+        def.setName("PII");
+        def.setSource("Atlas");
+        Assertions.assertEquals("PII", def.getName());
+        Assertions.assertEquals("Atlas", def.getSource());
+
+        List<RangerTagDef.RangerTagAttributeDef> attrs = new ArrayList<>();
+        attrs.add(new RangerTagDef.RangerTagAttributeDef("level", "string"));
+        def.setAttributeDefs(attrs);
+        Assertions.assertEquals(attrs, def.getAttributeDefs());
+    }
+
+    @Test
+    public void test02_dedupStringsAndEqualsHashCode() {
+        RangerTagDef.RangerTagAttributeDef ad1 = new RangerTagDef.RangerTagAttributeDef("n", "t");
+        RangerTagDef.RangerTagAttributeDef ad2 = new RangerTagDef.RangerTagAttributeDef("n", "t");
+        Assertions.assertEquals(ad1, ad2);
+        Assertions.assertEquals(ad1.hashCode(), ad2.hashCode());
+
+        RangerTagDef def1 = new RangerTagDef("PII", "Atlas");
+        List<RangerTagDef.RangerTagAttributeDef> list1 = new ArrayList<>();
+        list1.add(ad1);
+        def1.setAttributeDefs(list1);
+
+        RangerTagDef def2 = new RangerTagDef("PII", "Atlas");
+        List<RangerTagDef.RangerTagAttributeDef> list2 = new ArrayList<>();
+        list2.add(new RangerTagDef.RangerTagAttributeDef("n", "t"));
+        def2.setAttributeDefs(list2);
+
+        Assertions.assertEquals(def1, def2);
+        Assertions.assertEquals(def1.hashCode(), def2.hashCode());
+
+        Map<String, String> tbl = new HashMap<>();
+        def1.dedupStrings(tbl);
+        Assertions.assertTrue(tbl.isEmpty() || tbl.containsKey("PII") || tbl.containsKey("Atlas"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTagResourceMap.java
similarity index 50%
copy from agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java
copy to agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTagResourceMap.java
index d1ea46d61..90cddaa43 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerService.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerTagResourceMap.java
@@ -19,26 +19,32 @@
 
 package org.apache.ranger.plugin.model;
 
-import org.apache.commons.lang3.StringUtils;
 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.HashMap;
-
-public class TestRangerService {
+/**
+ * @generated by Cursor
+ * @description <Unit Test for RangerTagResourceMap class>
+ */
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerTagResourceMap {
     @Test
-    public void test_configToString() {
-        RangerService svc = new RangerService("hdfs", "dev_hdfs", "HDFS", "dev_tag", new HashMap<>());
-        String        str = svc.toString();
-
-        Assertions.assertFalse(StringUtils.containsIgnoreCase(str, RangerService.CONFIG_PASSWORD));
-
-        svc.getConfigs().put(RangerService.CONFIG_PASSWORD, "test1234");
-
-        str = svc.toString();
-
-        Assertions.assertTrue(StringUtils.containsIgnoreCase(str, RangerService.CONFIG_PASSWORD));
-        Assertions.assertFalse(StringUtils.containsIgnoreCase(str, "test1234"));
-        Assertions.assertTrue(StringUtils.containsIgnoreCase(str, RangerService.MASKED_PASSWORD_VALUE));
+    public void test01_gettersSettersAndToString() {
+        RangerTagResourceMap map = new RangerTagResourceMap();
+        map.setResourceId(100L);
+        map.setTagId(200L);
+
+        Assertions.assertEquals(100L, map.getResourceId());
+        Assertions.assertEquals(200L, map.getTagId());
+
+        String s = map.toString();
+        Assertions.assertTrue(s.contains("RangerTagResourceMap={"));
+        Assertions.assertTrue(s.contains("resourceId=100"));
+        Assertions.assertTrue(s.contains("tagId=200"));
     }
 }
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerValidityRecurrence.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerValidityRecurrence.java
new file mode 100644
index 000000000..bd56a1c23
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerValidityRecurrence.java
@@ -0,0 +1,92 @@
+/*
+ * 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.plugin.model;
+
+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 for RangerValidityRecurrence class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerValidityRecurrence {
+    @Test
+    public void test01_validityIntervalComputationAndToString() {
+        RangerValidityRecurrence.ValidityInterval vi = new RangerValidityRecurrence.ValidityInterval(1, 2, 30);
+        int minutes = RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(vi);
+        Assertions.assertEquals((1 * 24 + 2) * 60 + 30, minutes);
+
+        Assertions.assertEquals(0, RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(null));
+
+        String s = vi.toString();
+        Assertions.assertTrue(s.contains("days=1"));
+        Assertions.assertTrue(s.contains("hours=2"));
+        Assertions.assertTrue(s.contains("minutes=30"));
+    }
+
+    @Test
+    public void test02_recurrenceScheduleSetAndGet() {
+        RangerValidityRecurrence.RecurrenceSchedule rs = new RangerValidityRecurrence.RecurrenceSchedule();
+        rs.setFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute, "0,30");
+        rs.setFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour, "1");
+        rs.setFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth, "*");
+        rs.setFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek, "1-5");
+        rs.setFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month, "0-11");
+        rs.setFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year, "2025");
+
+        Assertions.assertEquals("0,30",
+                rs.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute));
+        Assertions.assertEquals("1",
+                rs.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour));
+        Assertions.assertEquals("*",
+                rs.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth));
+        Assertions.assertEquals("1-5",
+                rs.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek));
+        Assertions.assertEquals("0-11",
+                rs.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month));
+        Assertions.assertEquals("2025",
+                rs.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year));
+
+        String s = rs.toString();
+        Assertions.assertTrue(s.contains("minute=0,30"));
+        Assertions.assertTrue(s.contains("dayOfWeek=1-5"));
+    }
+
+    @Test
+    public void test03_validityRecurrenceToStringAndAccessors() {
+        RangerValidityRecurrence.RecurrenceSchedule rs = new RangerValidityRecurrence.RecurrenceSchedule("0", "12", "*",
+                "1-5", "0-11", "2030");
+        RangerValidityRecurrence.ValidityInterval vi = new RangerValidityRecurrence.ValidityInterval(0, 1, 0);
+        RangerValidityRecurrence rvr = new RangerValidityRecurrence(rs, vi);
+
+        Assertions.assertEquals(rs, rvr.getSchedule());
+        Assertions.assertEquals(vi, rvr.getInterval());
+
+        String s = rvr.toString();
+        Assertions.assertTrue(s.contains("Schedule={"));
+        Assertions.assertTrue(s.contains("ValidityInterval"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerValiditySchedule.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerValiditySchedule.java
new file mode 100644
index 000000000..f2cf8bd29
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerValiditySchedule.java
@@ -0,0 +1,71 @@
+/*
+ * 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.plugin.model;
+
+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.ArrayList;
+import java.util.List;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerValiditySchedule class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestRangerValiditySchedule {
+    @Test
+    public void test01_defaultsAndSetters() {
+        RangerValiditySchedule sched = new RangerValiditySchedule();
+        Assertions.assertNotNull(sched.getRecurrences());
+        Assertions.assertTrue(sched.getRecurrences().isEmpty());
+
+        sched.setTimeZone("UTC");
+        sched.setStartTime("2025/09/22 00:00:00");
+        sched.setEndTime("2025/09/23 00:00:00");
+        sched.setRecurrences(null);
+
+        Assertions.assertEquals("UTC", sched.getTimeZone());
+        Assertions.assertEquals("2025/09/22 00:00:00", sched.getStartTime());
+        Assertions.assertEquals("2025/09/23 00:00:00", sched.getEndTime());
+        Assertions.assertNotNull(sched.getRecurrences());
+    }
+
+    @Test
+    public void test02_setRecurrencesCopiesAndString() {
+        List<RangerValidityRecurrence> rec = new ArrayList<>();
+        rec.add(new RangerValidityRecurrence(new RangerValidityRecurrence.RecurrenceSchedule(),
+                new RangerValidityRecurrence.ValidityInterval()));
+
+        RangerValiditySchedule sched = new RangerValiditySchedule("s", "e", "Z", rec);
+        Assertions.assertEquals("Z", sched.getTimeZone());
+        Assertions.assertEquals(rec, sched.getRecurrences());
+
+        String s = sched.toString();
+        Assertions.assertTrue(s.contains("startTime=s"));
+        Assertions.assertTrue(s.contains("endTime=e"));
+        Assertions.assertTrue(s.contains("recurrences="));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestServiceDeleteResponse.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestServiceDeleteResponse.java
new file mode 100644
index 000000000..f78e34e9f
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestServiceDeleteResponse.java
@@ -0,0 +1,51 @@
+/*
+ * 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.plugin.model;
+
+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 for ServiceDeleteResponse class>
+*/
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+public class TestServiceDeleteResponse {
+    @Test
+    public void test01_gettersSetters() {
+        ServiceDeleteResponse resp = new ServiceDeleteResponse(7L);
+        Assertions.assertEquals(7L, resp.getServiceId());
+
+        resp.setServiceName("svc");
+        resp.setIsDeleted(Boolean.TRUE);
+        resp.setErrorMsg("none");
+        resp.setServiceId(8L);
+
+        Assertions.assertEquals("svc", resp.getServiceName());
+        Assertions.assertEquals(Boolean.TRUE, resp.getIsDeleted());
+        Assertions.assertEquals("none", resp.getErrorMsg());
+        Assertions.assertEquals(8L, resp.getServiceId());
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestUserInfo.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestUserInfo.java
new file mode 100644
index 000000000..1de8de729
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestUserInfo.java
@@ -0,0 +1,64 @@
+/*
+ * 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.plugin.model;
+
+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.HashMap;
+import java.util.HashSet;
+
+/**
+ * @generated by Cursor
+ * @description <Unit Test for UserInfo class>
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestUserInfo {
+    @Test
+    public void test01_ConstructorsAndSetters() {
+        UserInfo u1 = new UserInfo();
+        Assertions.assertNotNull(u1.getOtherAttributes());
+
+        UserInfo u2 = new UserInfo("alice", "desc", new HashMap<String, String>() {
+            {
+                put("k", "v");
+            }
+        });
+        u2.setGroups(new HashSet<String>() {
+            {
+                add("g1");
+            }
+        });
+
+        Assertions.assertEquals("alice", u2.getName());
+        Assertions.assertEquals("desc", u2.getDescription());
+        Assertions.assertEquals("v", u2.getOtherAttributes().get("k"));
+        Assertions.assertTrue(u2.getGroups().contains("g1"));
+
+        String s = u2.toString();
+        Assertions.assertTrue(s.contains("name=alice"));
+        Assertions.assertTrue(s.contains("otherAttributes={k, [v],}"));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidatorTest.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidatorTest.java
index e2ddb7863..4dc1c43ce 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidatorTest.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidatorTest.java
@@ -53,6 +53,10 @@
 
 import static org.mockito.Mockito.mock;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerSecurityZoneValidator class>
+*/
 @ExtendWith(MockitoExtension.class)
 @TestMethodOrder(MethodOrderer.MethodName.class)
 public class RangerSecurityZoneValidatorTest {
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestDirectedGraph.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestDirectedGraph.java
index dc8c5f086..5274880da 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestDirectedGraph.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestDirectedGraph.java
@@ -22,12 +22,22 @@
 import org.apache.hadoop.thirdparty.com.google.common.collect.Lists;
 import org.apache.hadoop.thirdparty.com.google.common.collect.Sets;
 import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper.DirectedGraph;
+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.HashSet;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for DirectedGraph class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestDirectedGraph {
     @Test
     public void test() {
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
index 83bb86ba9..cefd6b3b1 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
@@ -33,9 +33,11 @@
 import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
 import org.apache.ranger.plugin.store.ServiceStore;
 import org.apache.ranger.plugin.util.RangerObjectFactory;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.MethodOrderer;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -45,10 +47,20 @@
 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.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerPolicyValidator class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerPolicyValidator {
     final         Action[]   cu                                                           = new Action[] {Action.CREATE, Action.UPDATE};
     final         Object[]   policyItemsData      = new Object[] {
@@ -143,48 +155,46 @@ public class TestRangerPolicyValidator {
     private       RangerObjectFactory            factory;
     private final Long                           zoneId = RangerSecurityZone.RANGER_UNZONED_SECURITY_ZONE_ID;
 
-    @BeforeEach
-    public void setUp() throws Exception {
+    private void initialize() throws Exception {
         store      = mock(ServiceStore.class);
         policy     = mock(RangerPolicy.class);
         validator  = new RangerPolicyValidatorWrapper(store);
         serviceDef = mock(RangerServiceDef.class);
-        factory           = mock(RangerObjectFactory.class);
+        factory = mock(RangerObjectFactory.class);
         validator.factory = factory;
+        failures.clear();
     }
 
     @Test
     public final void testIsValid_long() throws Exception {
+        initialize();
         // this validation should be removed if we start supporting other than delete action
-        Assertions.assertFalse(validator.isValid(3L, Action.CREATE, failures));
+        assertFalse(validator.isValid(3L, Action.CREATE, failures));
         utils.checkFailureForInternalError(failures);
 
         // should fail with appropriate error message if id is null
         failures.clear();
         failures.clear();
-        Assertions.assertFalse(validator.isValid((Long) null, Action.DELETE, failures));
+        assertFalse(validator.isValid((Long) null, Action.DELETE, failures));
         utils.checkFailureForMissingValue(failures, "id");
 
         // should not fail if policy can't be found for the specified id
-        when(store.getPolicy(1L)).thenReturn(null);
-        when(store.getPolicy(2L)).thenThrow(new Exception());
-        RangerPolicy existingPolicy = mock(RangerPolicy.class);
-        when(store.getPolicy(3L)).thenReturn(existingPolicy);
         failures.clear();
-        Assertions.assertTrue(validator.isValid(1L, Action.DELETE, failures));
-        Assertions.assertTrue(failures.isEmpty());
+        assertTrue(validator.isValid(1L, Action.DELETE, failures));
+        assertTrue(failures.isEmpty());
         failures.clear();
-        Assertions.assertTrue(validator.isValid(2L, Action.DELETE, failures));
-        Assertions.assertTrue(failures.isEmpty());
+        assertTrue(validator.isValid(2L, Action.DELETE, failures));
+        assertTrue(failures.isEmpty());
 
         // if policy exists then delete validation should pass, too!
         failures.clear();
-        Assertions.assertTrue(validator.isValid(3L, Action.DELETE, failures));
-        Assertions.assertTrue(failures.isEmpty());
+        assertTrue(validator.isValid(3L, Action.DELETE, failures));
+        assertTrue(failures.isEmpty());
     }
 
     @Test
     public final void testIsValid_errorPaths() throws Exception {
+        initialize();
         boolean isAdmin = true;
 
         // 1. create policy in a non-existing service
@@ -192,49 +202,46 @@ public final void testIsValid_errorPaths() throws Exception {
         when(policy.getService()).thenReturn("non-existing-service-name");
         when(store.getServiceByName("non-existing-service-name")).thenReturn(null);
 
-        Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures), action.toString());
+        assertFalse(validator.isValid(policy, action, isAdmin, failures), action.toString());
 
         // 2. update a policy to change the service-name
+        failures.clear();
         RangerPolicy existingPolicy = mock(RangerPolicy.class);
-        when(existingPolicy.getId()).thenReturn(8L);
         when(existingPolicy.getService()).thenReturn("service-name");
 
         RangerService service = mock(RangerService.class);
         when(service.getType()).thenReturn("service-type");
-        when(service.getName()).thenReturn("service-name");
         when(store.getServiceByName("service-name")).thenReturn(service);
 
         RangerService service2 = mock(RangerService.class);
         when(service2.getType()).thenReturn("service-type");
-        when(service2.getName()).thenReturn("service-name2");
         when(store.getServiceByName("service-name2")).thenReturn(service2);
 
+        when(policy.getId()).thenReturn(8L);
+        when(policy.getName()).thenReturn("policy-name");
         when(policy.getService()).thenReturn("service-name2");
+        when(policy.getResources()).thenReturn(null);
+        when(policy.getIsAuditEnabled()).thenReturn(true);
+        when(store.getPolicy(8L)).thenReturn(existingPolicy);
 
-        RangerPolicyResourceSignature policySignature = mock(RangerPolicyResourceSignature.class);
-        when(policySignature.getSignature()).thenReturn("hash-1");
-
-        when(factory.createPolicyResourceSignature(policy)).thenReturn(policySignature);
-
-        when(store.getServiceByName("service-name2")).thenReturn(service2);
         action = Action.UPDATE;
 
-        Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures), action.toString());
+        assertFalse(validator.isValid(policy, action, isAdmin, failures), action.toString());
 
         // 3. update a policy to change the policy-type
-        when(existingPolicy.getId()).thenReturn(8L);
-        when(existingPolicy.getService()).thenReturn("service-name");
+        failures.clear();
         when(existingPolicy.getPolicyType()).thenReturn(0);
 
         when(policy.getId()).thenReturn(8L);
         when(policy.getService()).thenReturn("service-name");
         when(policy.getPolicyType()).thenReturn(1);
 
-        Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures), action.toString());
+        assertFalse(validator.isValid(policy, action, isAdmin, failures), action.toString());
     }
 
     @Test
     public final void testIsValid_happyPath() throws Exception {
+        initialize();
         // valid policy has valid non-empty name and service name
         when(policy.getService()).thenReturn("service-name");
         // service name exists
@@ -244,14 +251,10 @@ public final void testIsValid_happyPath() throws Exception {
         when(store.getServiceByName("service-name")).thenReturn(service);
         // service points to a valid service-def
         serviceDef = utils.createServiceDefWithAccessTypes(accessTypes);
-        when(serviceDef.getName()).thenReturn("service-type");
         when(store.getServiceDefByName("service-type")).thenReturn(serviceDef);
         // a matching policy should exist for create when checked by id and not exist when checked by name.
-        when(store.getPolicy(7L)).thenReturn(null);
         RangerPolicy existingPolicy = mock(RangerPolicy.class);
-        when(existingPolicy.getId()).thenReturn(8L);
         when(existingPolicy.getService()).thenReturn("service-name");
-        when(store.getPolicy(8L)).thenReturn(existingPolicy);
         // a matching policy should not exist for update.
         // valid policy can have empty set of policy items if audit is turned on
         // null value for audit is treated as audit on.
@@ -265,19 +268,21 @@ public final void testIsValid_happyPath() throws Exception {
                         when(policy.getId()).thenReturn(7L);
                         when(policy.getName()).thenReturn("policy-name-1");
                         when(store.getPolicyId(service.getId(), policy.getName(), zoneId)).thenReturn(null);
-                        Assertions.assertTrue(validator.isValid(policy, action, isAdmin, failures), action + ", " + auditEnabled);
-                        Assertions.assertTrue(failures.isEmpty());
+                        assertTrue(validator.isValid(policy, action, isAdmin, failures), action + ", " + auditEnabled);
+                        assertTrue(failures.isEmpty());
                     } else {
                         // update should work both when by-name is found or not, since nothing found by-name means name is being updated.
                         when(policy.getId()).thenReturn(8L);
                         when(policy.getName()).thenReturn("policy-name-1");
-                        Assertions.assertTrue(validator.isValid(policy, action, isAdmin, failures), action + ", " + auditEnabled);
-                        Assertions.assertTrue(failures.isEmpty());
+                        when(store.getPolicy(8L)).thenReturn(existingPolicy);
+                        assertTrue(validator.isValid(policy, action, isAdmin, failures), action + ", " + auditEnabled);
+                        assertTrue(failures.isEmpty());
 
                         when(policy.getName()).thenReturn("policy-name-2");
                         when(store.getPolicyId(service.getId(), policy.getName(), zoneId)).thenReturn(null);
-                        Assertions.assertTrue(validator.isValid(policy, action, isAdmin, failures), action + ", " + auditEnabled);
-                        Assertions.assertTrue(failures.isEmpty());
+                        when(store.getPolicy(8L)).thenReturn(existingPolicy);
+                        assertTrue(validator.isValid(policy, action, isAdmin, failures), action + ", " + auditEnabled);
+                        assertTrue(failures.isEmpty());
                     }
                 }
             }
@@ -295,8 +300,8 @@ public final void testIsValid_happyPath() throws Exception {
                     when(policy.getId()).thenReturn(8L);
                     when(policy.getName()).thenReturn("policy-name-2");
                 }
-                Assertions.assertTrue(validator.isValid(policy, action, isAdmin, failures), "" + action);
-                Assertions.assertTrue(failures.isEmpty());
+                assertTrue(validator.isValid(policy, action, isAdmin, failures), "" + action);
+                assertTrue(failures.isEmpty());
             }
         }
 
@@ -312,7 +317,9 @@ public final void testIsValid_happyPath() throws Exception {
         when(factory.createPolicyResourceSignature(policy)).thenReturn(policySignature);
         // setup the store to indicate that no other policy exists with matching signature
         when(policySignature.getSignature()).thenReturn("hash-1");
-        when(store.getPoliciesByResourceSignature("service-name", "hash-1", true)).thenReturn(null);
+        // Ensure helper works with non-null service-def name/time
+        when(serviceDef.getName()).thenReturn("service-type");
+        when(serviceDef.getUpdateTime()).thenReturn(new Date());
         // we are reusing the same policies collection here -- which is fine
         for (Action action : cu) {
             if (action == Action.CREATE) {
@@ -322,13 +329,14 @@ public final void testIsValid_happyPath() throws Exception {
                 when(policy.getId()).thenReturn(8L);
                 when(policy.getName()).thenReturn("policy-name-2");
             }
-            Assertions.assertTrue(validator.isValid(policy, action, true, failures), "" + action); // since policy resource has excludes admin privilages would be required
-            Assertions.assertTrue(failures.isEmpty());
+            assertTrue(validator.isValid(policy, action, true, failures), "" + action); // since policy resource has excludes admin privilages would be required
+            assertTrue(failures.isEmpty());
         }
     }
 
     @Test
     public final void testIsValid_failures() throws Exception {
+        initialize();
         for (Action action : cu) {
             // passing in a null policy should fail with appropriate failure reason
             policy = null;
@@ -338,7 +346,6 @@ public final void testIsValid_failures() throws Exception {
             policy = mock(RangerPolicy.class);
             for (String name : new String[] {null, "  "}) {
                 when(policy.getName()).thenReturn(name);
-                when(policy.getResources()).thenReturn(null);
                 checkFailure_isValid(action, "missing", "name");
             }
 
@@ -354,30 +361,23 @@ public final void testIsValid_failures() throws Exception {
          */
         when(policy.getName()).thenReturn("policy-name");
         when(policy.getService()).thenReturn("service-name");
+        when(policy.getResources()).thenReturn(null);
 
         when(store.getServiceByName("service-name")).thenReturn(service);
         when(service.getId()).thenReturn(2L);
 
         RangerPolicy existingPolicy = mock(RangerPolicy.class);
-        when(existingPolicy.getId()).thenReturn(7L);
-        when(existingPolicy.getService()).thenReturn("service-name");
-        List<RangerPolicy> existingPolicies = new ArrayList<>();
 
         when(store.getPolicyId(service.getId(), "policy-name", zoneId)).thenReturn(7L);
         checkFailure_isValid(Action.CREATE, "semantic", "policy name");
 
         // update : does not exist for id
         when(policy.getId()).thenReturn(7L);
-        when(store.getPolicy(7L)).thenReturn(null);
+        when(policy.getResources()).thenReturn(null);
         checkFailure_isValid(Action.UPDATE, "semantic", "id");
 
         // Update: name should not point to an existing different policy, i.e. with a different id
         when(store.getPolicy(7L)).thenReturn(existingPolicy);
-        RangerPolicy anotherExistingPolicy = mock(RangerPolicy.class);
-        when(anotherExistingPolicy.getId()).thenReturn(8L);
-        when(anotherExistingPolicy.getService()).thenReturn("service-name");
-
-        existingPolicies.add(anotherExistingPolicy);
         when(store.getPolicyId(service.getId(), "policy-name", zoneId)).thenReturn(8L);
         checkFailure_isValid(Action.UPDATE, "semantic", "id/name");
 
@@ -387,12 +387,12 @@ public final void testIsValid_failures() throws Exception {
             for (boolean isAdmin : new boolean[] {true, false}) {
                 when(policy.getService()).thenReturn(null);
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForMissingValue(failures, "service name");
 
                 when(policy.getService()).thenReturn("");
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForMissingValue(failures, "service name");
             }
         }
@@ -404,22 +404,22 @@ public final void testIsValid_failures() throws Exception {
             for (boolean isAdmin : new boolean[] {true, false}) {
                 when(policy.getService()).thenReturn(null);
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForMissingValue(failures, "service name");
 
                 when(policy.getService()).thenReturn(null);
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForMissingValue(failures, "service name");
 
                 when(policy.getService()).thenReturn("service-name");
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForSemanticError(failures, "service name");
 
                 when(policy.getService()).thenReturn("another-service-name");
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForSemanticError(failures, "service name");
             }
         }
@@ -431,12 +431,12 @@ public final void testIsValid_failures() throws Exception {
                 // when it is null
                 when(policy.getPolicyItems()).thenReturn(null);
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForMissingValue(failures, "policy items");
                 // or when it is not null but empty.
                 when(policy.getPolicyItems()).thenReturn(policyItems);
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForMissingValue(failures, "policy items");
             }
         }
@@ -452,24 +452,26 @@ public final void testIsValid_failures() throws Exception {
                 when(policy.getService()).thenReturn("service-name");
                 when(store.getServiceByName("service-name")).thenReturn(service);
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForInternalError(failures, "policy service def");
             }
         }
 
         // service-def should contain the right access types on it.
-        serviceDef = utils.createServiceDefWithAccessTypes(accessTypesBad, "service-type");
+        serviceDef = utils.createServiceDefWithAccessTypes(accessTypesBad);
         when(store.getServiceDefByName("service-type")).thenReturn(serviceDef);
         for (Action action : cu) {
             for (boolean isAdmin : new boolean[] {true, false}) {
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForSemanticError(failures, "policy item access type");
             }
         }
 
         // create the right service def with right resource defs - this is the same as in the happypath test above.
-        serviceDef = utils.createServiceDefWithAccessTypes(accessTypes, "service-type");
+        serviceDef = utils.createServiceDefWithAccessTypes(accessTypes);
+        when(serviceDef.getName()).thenReturn("service-type");
+        when(serviceDef.getUpdateTime()).thenReturn(new Date());
         when(store.getPolicyId(service.getId(), "policy-name", zoneId)).thenReturn(null);
         List<RangerResourceDef> resourceDefs = utils.createResourceDefs(resourceDefData);
         when(serviceDef.getResources()).thenReturn(resourceDefs);
@@ -482,11 +484,11 @@ public final void testIsValid_failures() throws Exception {
         RangerPolicyResourceSignature signature = mock(RangerPolicyResourceSignature.class);
         when(factory.createPolicyResourceSignature(policy)).thenReturn(signature);
         when(signature.getSignature()).thenReturn("hash-1");
-        when(store.getPoliciesByResourceSignature("service-name", "hash-1", true)).thenReturn(null); // store does not have any policies for that signature hash
+        when(store.getPoliciesByResourceSignature("service-name", "hash-1", true)).thenReturn(null); // store does not policies for that signature hash
         for (Action action : cu) {
             for (boolean isAdmin : new boolean[] {true, false}) {
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForSemanticError(failures, "resource-values", "col"); // for spurious resource: "extra"
                 utils.checkFailureForSemanticError(failures, "isRecursive", "db"); // for specifying it as true when def did not allow it
                 utils.checkFailureForSemanticError(failures, "isExcludes", "col"); // for specifying it as true when def did not allow it
@@ -494,64 +496,70 @@ public final void testIsValid_failures() throws Exception {
         }
 
         // Check if error around resource signature clash are reported.  have Store return policies for same signature
+        List<RangerPolicy> existingPolicies = new ArrayList<>();
+        RangerPolicy policy1 = mock(RangerPolicy.class);
+        existingPolicies.add(policy1);
         when(store.getPoliciesByResourceSignature("service-name", "hash-1", true)).thenReturn(existingPolicies);
         for (Action action : cu) {
             for (boolean isAdmin : new boolean[] {true, false}) {
                 failures.clear();
-                Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+                assertFalse(validator.isValid(policy, action, isAdmin, failures));
                 utils.checkFailureForSemanticError(failures, "policy resources");
             }
         }
     }
 
     @Test
-    public void test_isValidResourceValues() {
+    public void test_isValidResourceValues() throws Exception {
+        initialize();
         List<RangerResourceDef> resourceDefs = utils.createResourceDefs(resourceDefData);
         when(serviceDef.getResources()).thenReturn(resourceDefs);
         Map<String, RangerPolicyResource> policyResources = utils.createPolicyResourceMap(policyResourceMapBad);
-        Assertions.assertFalse(validator.isValidResourceValues(policyResources, failures, serviceDef));
+        assertFalse(validator.isValidResourceValues(policyResources, failures, serviceDef));
         utils.checkFailureForSemanticError(failures, "resource-values", "col");
 
         policyResources = utils.createPolicyResourceMap(policyResourceMapGood);
-        Assertions.assertTrue(validator.isValidResourceValues(policyResources, failures, serviceDef));
+        assertTrue(validator.isValidResourceValues(policyResources, failures, serviceDef));
 
         policyResources = utils.createPolicyResourceMap(policyResourceMapBadDuplicateValues);
-        Assertions.assertFalse(validator.isValidResourceValues(policyResources, failures, serviceDef));
+        assertFalse(validator.isValidResourceValues(policyResources, failures, serviceDef));
         utils.checkFailureForSemanticError(failures, "resource-values", "tbl");
 
         policyResources = utils.createPolicyResourceMap(policyResourceMapGoodDuplicateValues);
-        Assertions.assertTrue(validator.isValidResourceValues(policyResources, failures, serviceDef));
+        assertTrue(validator.isValidResourceValues(policyResources, failures, serviceDef));
     }
 
     @Test
-    public void test_isValidPolicyItems_failures() {
+    public void test_isValidPolicyItems_failures() throws Exception {
+        initialize();
         // null/empty list is good because there is nothing
-        Assertions.assertTrue(validator.isValidPolicyItems(null, failures, serviceDef));
+        assertTrue(validator.isValidPolicyItems(null, failures, serviceDef));
         failures.isEmpty();
 
         List<RangerPolicyItem> policyItems = new ArrayList<>();
-        Assertions.assertTrue(validator.isValidPolicyItems(policyItems, failures, serviceDef));
+        assertTrue(validator.isValidPolicyItems(policyItems, failures, serviceDef));
         failures.isEmpty();
 
         // null elements in the list are flagged
         policyItems.add(null);
-        Assertions.assertFalse(validator.isValidPolicyItems(policyItems, failures, serviceDef));
+        assertFalse(validator.isValidPolicyItems(policyItems, failures, serviceDef));
         utils.checkFailureForMissingValue(failures, "policy item");
     }
 
     @Test
-    public void test_isValidPolicyItem_failures() {
+    public void test_isValidPolicyItem_failures() throws Exception {
+        initialize();
         // empty access collections are invalid
         RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
         when(policyItem.getAccesses()).thenReturn(null);
         failures.clear();
-        Assertions.assertFalse(validator.isValidPolicyItem(policyItem, failures, serviceDef));
+        assertFalse(validator.isValidPolicyItem(policyItem, failures, serviceDef));
         utils.checkFailureForMissingValue(failures, "policy item accesses");
 
         List<RangerPolicyItemAccess> accesses = new ArrayList<>();
         when(policyItem.getAccesses()).thenReturn(accesses);
         failures.clear();
-        Assertions.assertFalse(validator.isValidPolicyItem(policyItem, failures, serviceDef));
+        assertFalse(validator.isValidPolicyItem(policyItem, failures, serviceDef));
         utils.checkFailureForMissingValue(failures, "policy item accesses");
 
         // both user and groups can't be null
@@ -560,12 +568,13 @@ public void test_isValidPolicyItem_failures() {
         when(policyItem.getUsers()).thenReturn(null);
         when(policyItem.getGroups()).thenReturn(new ArrayList<>());
         failures.clear();
-        Assertions.assertFalse(validator.isValidPolicyItem(policyItem, failures, serviceDef));
+        assertFalse(validator.isValidPolicyItem(policyItem, failures, serviceDef));
         utils.checkFailureForMissingValue(failures, "policy item users/user-groups/roles");
     }
 
     @Test
-    public void test_isValidPolicyItem_happPath() {
+    public void test_isValidPolicyItem_happPath() throws Exception {
+        initialize();
         // A policy item with no access is valid if it has delegated admin turned on and one user/group specified.
         RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
         when(policyItem.getAccesses()).thenReturn(null);
@@ -574,31 +583,34 @@ public void test_isValidPolicyItem_happPath() {
         List<String> users = Arrays.asList("user1");
         when(policyItem.getUsers()).thenReturn(users);
         failures.clear();
-        Assertions.assertTrue(validator.isValidPolicyItem(policyItem, failures, serviceDef));
-        Assertions.assertTrue(failures.isEmpty());
+        assertTrue(validator.isValidPolicyItem(policyItem, failures, serviceDef));
+        assertTrue(failures.isEmpty());
     }
 
     @Test
-    public void test_isValidItemAccesses_happyPath() {
+    public void test_isValidItemAccesses_happyPath() throws Exception {
+        initialize();
         // happy path
         Object[][] data = new Object[][] {
                 {"a", null}, // valid
                 {"b", true}, // valid
                 {"c", true}, // valid
         };
+
         List<RangerPolicyItemAccess> accesses = utils.createItemAccess(data);
         serviceDef = utils.createServiceDefWithAccessTypes(new String[] {"a", "b", "c", "d"});
-        Assertions.assertTrue(validator.isValidItemAccesses(accesses, failures, serviceDef));
-        Assertions.assertTrue(failures.isEmpty());
+        assertTrue(validator.isValidItemAccesses(accesses, failures, serviceDef));
+        assertTrue(failures.isEmpty());
     }
 
     @Test
-    public void test_isValidItemAccesses_failure() {
+    public void test_isValidItemAccesses_failure() throws Exception {
+        initialize();
         // null policy item access values are an error
         List<RangerPolicyItemAccess> accesses = new ArrayList<>();
         accesses.add(null);
         failures.clear();
-        Assertions.assertFalse(validator.isValidItemAccesses(accesses, failures, serviceDef));
+        assertFalse(validator.isValidItemAccesses(accesses, failures, serviceDef));
         utils.checkFailureForMissingValue(failures, "policy item access");
 
         // all items must be valid for this call to be valid
@@ -610,26 +622,28 @@ public void test_isValidItemAccesses_failure() {
         accesses   = utils.createItemAccess(data);
         serviceDef = utils.createServiceDefWithAccessTypes(new String[] {"a", "b", "c", "d"});
         failures.clear();
-        Assertions.assertFalse(validator.isValidItemAccesses(accesses, failures, serviceDef));
+        assertFalse(validator.isValidItemAccesses(accesses, failures, serviceDef));
     }
 
     @Test
-    public void test_isValidPolicyItemAccess_happyPath() {
+    public void test_isValidPolicyItemAccess_happyPath() throws Exception {
+        initialize();
         RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
         when(access.getType()).thenReturn("an-Access"); // valid
 
-        Set<String> validAccesses = Sets.newHashSet(new String[] {"an-access", "another-access"});  // valid accesses should be lower-cased
+        Set<String> validAccesses = Sets.newHashSet(new String[] {"an-access", "another-access" });  // valid accesses should be lower-cased
 
         // both null or true access types are the same and valid
         for (Boolean allowed : new Boolean[] {null, true}) {
             when(access.getIsAllowed()).thenReturn(allowed);
-            Assertions.assertTrue(validator.isValidPolicyItemAccess(access, failures, validAccesses));
-            Assertions.assertTrue(failures.isEmpty());
+            assertTrue(validator.isValidPolicyItemAccess(access, failures, validAccesses));
+            assertTrue(failures.isEmpty());
         }
     }
 
     @Test
-    public void test_isValidPolicyItemAccess_failures() {
+    public void test_isValidPolicyItemAccess_failures() throws Exception {
+        initialize();
         Set<String> validAccesses = Sets.newHashSet(new String[] {"anAccess", "anotherAccess"});
         // null/empty names are invalid
         RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
@@ -638,45 +652,45 @@ public void test_isValidPolicyItemAccess_failures() {
         for (String type : new String[] {null, " \t"}) {
             when(access.getType()).thenReturn(type); // invalid
             // null/empty validAccess set skips all checks
-            Assertions.assertTrue(validator.isValidPolicyItemAccess(access, failures, null));
-            Assertions.assertTrue(validator.isValidPolicyItemAccess(access, failures, new HashSet<>()));
+            assertTrue(validator.isValidPolicyItemAccess(access, failures, null));
+            assertTrue(validator.isValidPolicyItemAccess(access, failures, new HashSet<>()));
             failures.clear();
-            Assertions.assertFalse(validator.isValidPolicyItemAccess(access, failures, validAccesses));
+            assertFalse(validator.isValidPolicyItemAccess(access, failures, validAccesses));
             utils.checkFailureForMissingValue(failures, "policy item access type");
         }
 
         when(access.getType()).thenReturn("anAccess"); // valid
         when(access.getIsAllowed()).thenReturn(false); // invalid
         failures.clear();
-        Assertions.assertFalse(validator.isValidPolicyItemAccess(access, failures, validAccesses));
+        assertFalse(validator.isValidPolicyItemAccess(access, failures, validAccesses));
         utils.checkFailureForSemanticError(failures, "policy item access type allowed");
 
         when(access.getType()).thenReturn("newAccessType"); // invalid
         failures.clear();
-        Assertions.assertFalse(validator.isValidPolicyItemAccess(access, failures, validAccesses));
+        assertFalse(validator.isValidPolicyItemAccess(access, failures, validAccesses));
         utils.checkFailureForSemanticError(failures, "policy item access type");
     }
 
     @Test
-    public final void test_isValidResourceFlags_happyPath() {
+    public final void test_isValidResourceFlags_happyPath() throws Exception {
+        initialize();
         Map<String, RangerPolicyResource> resourceMap  = utils.createPolicyResourceMap(policyResourceMapHappyPath);
         List<RangerResourceDef>           resourceDefs = utils.createResourceDefs(resourceDefHappyPath);
-        when(serviceDef.getResources()).thenReturn(resourceDefs);
-        Assertions.assertTrue(validator.isValidResourceFlags(resourceMap, failures, resourceDefs, "a-service-def", "a-policy", true));
+        assertTrue(validator.isValidResourceFlags(resourceMap, failures, resourceDefs, "a-service-def", "a-policy", true));
 
         // Since one of the resource has excludes set to true, without admin privilages it should fail and contain appropriate error messages
-        Assertions.assertFalse(validator.isValidResourceFlags(resourceMap, failures, resourceDefs, "a-service-def", "a-policy", false));
+        assertFalse(validator.isValidResourceFlags(resourceMap, failures, resourceDefs, "a-service-def", "a-policy", false));
         utils.checkFailureForSemanticError(failures, "isExcludes", "isAdmin");
     }
 
     @Test
-    public final void test_isValidResourceFlags_failures() {
+    public final void test_isValidResourceFlags_failures() throws Exception {
+        initialize();
         // passing true when def says false/null
         List<RangerResourceDef>           resourceDefs = utils.createResourceDefs(resourceDefHappyPath);
         Map<String, RangerPolicyResource> resourceMap  = utils.createPolicyResourceMap(policyResourceMapFailures);
-        when(serviceDef.getResources()).thenReturn(resourceDefs);
         // should not error out on
-        Assertions.assertFalse(validator.isValidResourceFlags(resourceMap, failures, resourceDefs, "a-service-def", "a-policy", false));
+        assertFalse(validator.isValidResourceFlags(resourceMap, failures, resourceDefs, "a-service-def", "a-policy", false));
         utils.checkFailureForSemanticError(failures, "isExcludes", "tbl");
         utils.checkFailureForSemanticError(failures, "isRecursive", "col");
         utils.checkFailureForSemanticError(failures, "isExcludes", "isAdmin");
@@ -684,6 +698,7 @@ public final void test_isValidResourceFlags_failures() {
 
     @Test
     public final void test_isPolicyResourceUnique() throws Exception {
+        initialize();
         // if store does not contain any matching policies then check should succeed
         RangerPolicyResourceSignature signature = mock(RangerPolicyResourceSignature.class);
         String                        hash      = "hash-1";
@@ -694,8 +709,8 @@ public final void test_isPolicyResourceUnique() throws Exception {
         when(store.getPoliciesByResourceSignature("service-name", hash, true)).thenReturn(policies);
         policies = new ArrayList<>();
         for (Action action : cu) {
-            Assertions.assertTrue(validator.isPolicyResourceUnique(policy, failures, action));
-            Assertions.assertTrue(validator.isPolicyResourceUnique(policy, failures, action));
+            assertTrue(validator.isPolicyResourceUnique(policy, failures, action));
+            assertTrue(validator.isPolicyResourceUnique(policy, failures, action));
         }
         /*
          * If store has a policy with matching signature then the check should fail with appropriate error message.
@@ -705,48 +720,42 @@ public final void test_isPolicyResourceUnique() throws Exception {
         RangerPolicy policy1 = mock(RangerPolicy.class);
         policies.add(policy1);
         when(store.getPoliciesByResourceSignature("service-name", hash, true)).thenReturn(policies);
-        when(policy.getIsEnabled()).thenReturn(true); // ensure policy is enabled
         failures.clear();
-        Assertions.assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.CREATE));
+        assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.CREATE));
         utils.checkFailureForSemanticError(failures, "resources");
         // same check should fail even if the policy is disabled
-        when(policy.getIsEnabled()).thenReturn(false);
         failures.clear();
-        Assertions.assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.CREATE));
+        assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.CREATE));
         utils.checkFailureForSemanticError(failures, "resources");
 
         // For Update match with itself is not a problem as long as it isn't itself, i.e. same id.
-        when(policy.getIsEnabled()).thenReturn(true); // ensure policy is enabled
         when(policy1.getId()).thenReturn(103L);
         when(policy.getId()).thenReturn(103L);
-        Assertions.assertTrue(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
+        assertTrue(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
 
         // matching policy can't be some other policy (i.e. different id) because that implies a conflict.
         when(policy1.getId()).thenReturn(104L);
-        Assertions.assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
+        assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
         utils.checkFailureForSemanticError(failures, "resources");
         // same check should pass if the policy is disabled
-        when(policy.getIsEnabled()).thenReturn(false);
         failures.clear();
-        Assertions.assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
+        assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
         utils.checkFailureForSemanticError(failures, "resources");
 
         // And validation should never pass if there are more than one policies with matching signature, regardless of their ID!!
         RangerPolicy policy2 = mock(RangerPolicy.class);
-        when(policy2.getId()).thenReturn(103L);  // has same id as the policy being tested (_policy)
         policies.add(policy2);
-        when(policy.getIsEnabled()).thenReturn(true); // ensure policy is enabled
-        Assertions.assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
+        assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
         utils.checkFailureForSemanticError(failures, "resources");
         // same check should pass if the policy is disabled
-        when(policy.getIsEnabled()).thenReturn(false);
         failures.clear();
-        Assertions.assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
+        assertFalse(validator.isPolicyResourceUnique(policy, failures, Action.UPDATE));
         utils.checkFailureForSemanticError(failures, "resources");
     }
 
     @Test
-    public final void test_isValidResourceNames_happyPath() {
+    public final void test_isValidResourceNames_happyPath() throws Exception {
+        initialize();
         String serviceName = "a-service-def";
         // setup service-def
         Date now = new Date();
@@ -757,11 +766,12 @@ public final void test_isValidResourceNames_happyPath() {
         // setup policy
         Map<String, RangerPolicyResource> policyResources = utils.createPolicyResourceMap(policyResourceMapGoodMultipleHierarchies);
         when(policy.getResources()).thenReturn(policyResources);
-        Assertions.assertTrue(validator.isValidResourceNames(policy, failures, serviceDef));
+        assertTrue(validator.isValidResourceNames(policy, failures, serviceDef));
     }
 
     @Test
-    public final void test_isValidResourceNames_failures() {
+    public final void test_isValidResourceNames_failures() throws Exception {
+        initialize();
         String serviceName = "a-service-def";
         // setup service-def
         Date now = new Date();
@@ -772,26 +782,28 @@ public final void test_isValidResourceNames_failures() {
         // setup policy
         Map<String, RangerPolicyResource> policyResources = utils.createPolicyResourceMap(policyResourceMapBad);
         when(policy.getResources()).thenReturn(policyResources);
-        Assertions.assertFalse(validator.isValidResourceNames(policy, failures, serviceDef), "Missing required resource and unknown resource");
+        assertFalse(validator.isValidResourceNames(policy, failures, serviceDef), "Missing required resource and unknown resource");
         utils.checkFailureForSemanticError(failures, "policy resources");
 
         // another bad resource map that straddles multiple hierarchies
         policyResources = utils.createPolicyResourceMap(policyResourceMapBadMultipleHierarchies);
         when(policy.getResources()).thenReturn(policyResources);
         failures.clear();
-        Assertions.assertFalse(validator.isValidResourceNames(policy, failures, serviceDef), "Policy with resources for multiple hierarchies");
+        assertFalse(validator.isValidResourceNames(policy, failures, serviceDef), "Policy with resources for multiple hierarchies");
         utils.checkFailureForSemanticError(failures, "policy resources", "incompatible");
 
         // another bad policy resource map that could match multiple hierarchies but is short on mandatory resources for all of those matches
         policyResources = utils.createPolicyResourceMap(policyResourceMapBadMultipleHierarchiesMissingMandatory);
         when(policy.getResources()).thenReturn(policyResources);
         failures.clear();
-        Assertions.assertFalse(validator.isValidResourceNames(policy, failures, serviceDef), "Policy with resources for multiple hierarchies missing mandatory resources for all pontential matches");
+        assertFalse(validator.isValidResourceNames(policy, failures, serviceDef),
+                "Policy with resources for multiple hierarchies missing mandatory resources for all pontential matches");
         utils.checkFailureForSemanticError(failures, "policy resources", "missing mandatory");
     }
 
     @Test
-    public void test_isValidResource_additionalResources() {
+    public void test_isValidResource_additionalResources() throws Exception {
+        initialize();
         String                                  serviceName         = "a-service-def";
         Date                                    now                 = new Date();
         List<RangerResourceDef>                 resourceDefs        = utils.createResourceDefs(resourceDefDataMultipleHierarchies);
@@ -804,17 +816,18 @@ public void test_isValidResource_additionalResources() {
         when(policy.getResources()).thenReturn(resources);
         when(policy.getAdditionalResources()).thenReturn(additionalResources);
 
-        Assertions.assertTrue(validator.isValidResourceNames(policy, failures, serviceDef), "valid resources and empty additionalResources");
+        assertTrue(validator.isValidResourceNames(policy, failures, serviceDef), "valid resources and empty additionalResources");
 
         additionalResources.add(utils.createPolicyResourceMap(policyResourceMapGood));
-        Assertions.assertTrue(validator.isValidResourceNames(policy, failures, serviceDef), "valid resources and additionalResources[0]");
+        assertTrue(validator.isValidResourceNames(policy, failures, serviceDef), "valid resources and additionalResources[0]");
 
         additionalResources.add(utils.createPolicyResourceMap(policyResourceMapBad));
-        Assertions.assertFalse(validator.isValidResourceNames(policy, failures, serviceDef), "valid resources and invalid additionalResources[1]");
+        assertFalse(validator.isValidResourceNames(policy, failures, serviceDef), "valid resources and invalid additionalResources[1]");
     }
 
     @Test
     public final void test_isValidServiceWithZone_happyPath() throws Exception {
+        initialize();
         boolean isAdmin = true;
         when(policy.getId()).thenReturn(1L);
         when(policy.getName()).thenReturn("my-all");
@@ -822,7 +835,6 @@ public final void test_isValidServiceWithZone_happyPath() throws Exception {
         when(policy.getZoneName()).thenReturn("zone1");
         when(policy.getResources()).thenReturn(null);
         when(policy.getIsAuditEnabled()).thenReturn(Boolean.TRUE);
-        when(policy.getIsEnabled()).thenReturn(Boolean.FALSE);
         RangerService service = new RangerService();
         service.setType("service-type");
         service.setId(2L);
@@ -839,13 +851,12 @@ public final void test_isValidServiceWithZone_happyPath() throws Exception {
         RangerServiceDef svcDef = new RangerServiceDef();
         svcDef.setName("my-svc-def");
         when(store.getServiceDefByName("service-type")).thenReturn(svcDef);
-        RangerPolicyResourceSignature policySignature = mock(RangerPolicyResourceSignature.class);
-        when(factory.createPolicyResourceSignature(policy)).thenReturn(policySignature);
-        Assertions.assertTrue(validator.isValid(policy, action, isAdmin, failures));
+        assertTrue(validator.isValid(policy, action, isAdmin, failures));
     }
 
     @Test
     public final void test_isValidServiceWithZone_failurePath() throws Exception {
+        initialize();
         boolean isAdmin = true;
         when(policy.getId()).thenReturn(1L);
         when(policy.getName()).thenReturn("my-all");
@@ -853,7 +864,6 @@ public final void test_isValidServiceWithZone_failurePath() throws Exception {
         when(policy.getZoneName()).thenReturn("zone1");
         when(policy.getResources()).thenReturn(null);
         when(policy.getIsAuditEnabled()).thenReturn(Boolean.TRUE);
-        when(policy.getIsEnabled()).thenReturn(Boolean.FALSE);
         RangerService service = new RangerService();
         service.setType("service-type");
         service.setId(2L);
@@ -870,12 +880,10 @@ public final void test_isValidServiceWithZone_failurePath() throws Exception {
         RangerServiceDef svcDef = new RangerServiceDef();
         svcDef.setName("my-svc-def");
         when(store.getServiceDefByName("service-type")).thenReturn(svcDef);
-        RangerPolicyResourceSignature policySignature = mock(RangerPolicyResourceSignature.class);
-        when(factory.createPolicyResourceSignature(policy)).thenReturn(policySignature);
         boolean isValid = validator.isValid(policy, action, isAdmin, failures);
-        Assertions.assertFalse(isValid);
-        Assertions.assertEquals(failures.get(0).errorCode, 3048);
-        Assertions.assertEquals(failures.get(0).reason, "Service name = hdfssvc1 is not associated to Zone name = zone1");
+        assertFalse(isValid);
+        assertEquals(failures.get(0).errorCode, 3048);
+        assertEquals(failures.get(0).reason, "Service name = hdfssvc1 is not associated to Zone name = zone1");
     }
 
     void checkFailure_isValid(Action action, String errorType, String field) {
@@ -885,7 +893,7 @@ void checkFailure_isValid(Action action, String errorType, String field) {
     void checkFailure_isValid(Action action, String errorType, String field, String subField) {
         for (boolean isAdmin : new boolean[] {true, false}) {
             failures.clear();
-            Assertions.assertFalse(validator.isValid(policy, action, isAdmin, failures));
+            assertFalse(validator.isValid(policy, action, isAdmin, failures));
             switch (errorType) {
                 case "missing":
                     utils.checkFailureForMissingValue(failures, field, subField);
@@ -897,7 +905,7 @@ void checkFailure_isValid(Action action, String errorType, String field, String
                     utils.checkFailureForInternalError(failures);
                     break;
                 default:
-                    Assertions.fail("Unsupported errorType[" + errorType + "]");
+                    fail("Unsupported errorType[" + errorType + "]");
                     break;
             }
         }
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerRoleValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerRoleValidator.java
new file mode 100644
index 000000000..443305b50
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerRoleValidator.java
@@ -0,0 +1,284 @@
+/*
+ * 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.plugin.model.validation;
+
+import org.apache.ranger.plugin.errors.ValidationErrorCode;
+import org.apache.ranger.plugin.model.RangerRole;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.RoleStore;
+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.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerRoleValidator class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestRangerRoleValidator {
+    @Test
+    public void test01_isValidId_unsupportedAction() {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(1L, Action.CREATE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_UNSUPPORTED_ACTION;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().isAnInternalError()
+                .becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test02_isValidId_nullId() {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid((Long) null, Action.DELETE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_MISSING_FIELD;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("id").isMissing()
+                .errorCode(error.getErrorCode()).becauseOf(error.getMessage((Object) null)).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test03_isValidId_roleDoesNotExist() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        Mockito.when(roleStore.roleExists(7L)).thenReturn(false);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(7L, Action.DELETE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_INVALID_ROLE_ID;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("id").isMissing()
+                .errorCode(error.getErrorCode()).becauseOf(error.getMessage(7L)).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test04_isValidId_success() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        Mockito.when(roleStore.roleExists(9L)).thenReturn(true);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(9L, Action.DELETE, failures);
+
+        Assertions.assertTrue(valid);
+        Assertions.assertTrue(failures.isEmpty());
+    }
+
+    @Test
+    public void test05_isValidName_unsupportedAction() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid("roleA", Action.UPDATE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_UNSUPPORTED_ACTION;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().isAnInternalError()
+                .becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test06_isValidName_nullName() {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid((String) null, Action.DELETE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_MISSING_FIELD;
+        // Implementation uses field("id") for name-missing; test reflects current
+        // behavior
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("id").isMissing()
+                .errorCode(error.getErrorCode()).becauseOf(error.getMessage((Object) null)).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test07_isValidName_notExist() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        Mockito.when(roleStore.roleExists("unknown")).thenReturn(false);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid("unknown", Action.DELETE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_INVALID_ROLE_NAME;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("name").isMissing()
+                .errorCode(error.getErrorCode()).becauseOf(error.getMessage("unknown")).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test08_isValidRole_nullRole() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid((RangerRole) null, Action.CREATE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_NULL_RANGER_ROLE_OBJECT;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().isAnInternalError().isMissing()
+                .becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test09_isValidRole_emptyName() {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+        RangerRole role = new RangerRole();
+        role.setName("");
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(role, Action.CREATE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_NULL_RANGER_ROLE_NAME;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("name").isMissing()
+                .becauseOf(error.getMessage()).errorCode(error.getErrorCode()).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test10_isValidRole_create_conflictOnSameName() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRole existing = new RangerRole();
+        existing.setName("r1");
+        Mockito.when(roleStore.getRole(5L)).thenReturn(existing);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        RangerRole input = new RangerRole();
+        input.setId(5L);
+        input.setName("r1");
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(input, Action.CREATE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_ROLE_NAME_CONFLICT;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("name")
+                .isSemanticallyIncorrect().becauseOf(error.getMessage("r1")).errorCode(error.getErrorCode()).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test11_isValidRole_update_missingId() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        RangerRole input = new RangerRole();
+        input.setName("r1");
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(input, Action.UPDATE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_MISSING_FIELD;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("id").isMissing()
+                .becauseOf(error.getMessage((Object) null)).errorCode(error.getErrorCode()).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test12_isValidRole_update_invalidId() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        Mockito.when(roleStore.getRole(100L)).thenReturn(null);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        RangerRole input = new RangerRole();
+        input.setId(100L);
+        input.setName("r1");
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(input, Action.UPDATE, failures);
+
+        Assertions.assertFalse(valid);
+        ValidationErrorCode error = ValidationErrorCode.ROLE_VALIDATION_ERR_INVALID_ROLE_ID;
+        ValidationFailureDetails expected = new ValidationFailureDetailsBuilder().field("id").isSemanticallyIncorrect()
+                .becauseOf(error.getMessage(100L)).errorCode(error.getErrorCode()).build();
+        Assertions.assertTrue(failures.contains(expected));
+    }
+
+    @Test
+    public void test13_validate_throws_onInvalid() {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+        RangerRole input = null;
+
+        Exception ex = Assertions.assertThrows(Exception.class, () -> validator.validate(input, Action.CREATE));
+        Assertions.assertTrue(ex.getMessage() != null && ex.getMessage().contains("Validation failure"));
+    }
+
+    @Test
+    public void test14_validate_ok_onUpdateWithExistingId() throws Exception {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRole existing = new RangerRole();
+        existing.setName("x");
+        Mockito.when(roleStore.getRole(11L)).thenReturn(existing);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        RangerRole input = new RangerRole();
+        input.setId(11L);
+        input.setName("new-name");
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        Assertions.assertTrue(validator.isValid(input, Action.UPDATE, failures));
+        validator.validate(input, Action.UPDATE);
+    }
+
+    @Test
+    public void test15_isValidRole_create_ok_withoutId() {
+        RoleStore roleStore = Mockito.mock(RoleStore.class);
+        RangerRoleValidator validator = new RangerRoleValidator(roleStore);
+
+        RangerRole input = new RangerRole();
+        input.setName("create-ok");
+
+        List<ValidationFailureDetails> failures = new ArrayList<>();
+        boolean valid = validator.isValid(input, Action.CREATE, failures);
+
+        Assertions.assertTrue(valid);
+        Assertions.assertTrue(failures.isEmpty());
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
index 934d0c7fd..918b67777 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java
@@ -23,9 +23,13 @@
 import org.apache.ranger.authorization.utils.JsonUtils;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerRowFilterDef;
 import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper.Delegate;
 import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher;
+import org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.MethodOrderer;
 import org.junit.jupiter.api.Test;
@@ -34,44 +38,39 @@
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
-import java.util.ConcurrentModificationException;
+import java.util.Collections;
 import java.util.Date;
 import java.util.GregorianCalendar;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import static java.util.Objects.requireNonNull;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertIterableEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerServiceDefHelper class>
+*/
 @ExtendWith(MockitoExtension.class)
 @TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerServiceDefHelper {
-    private RangerServiceDef       serviceDef;
-    private RangerServiceDefHelper helper;
-
     @BeforeEach
     public void before() {
-        serviceDef = mock(RangerServiceDef.class);
-
-        lenient().when(serviceDef.getName()).thenReturn("a-service-def");
-
         // wipe the cache clean
         RangerServiceDefHelper.cache.clear();
     }
@@ -94,34 +93,43 @@ public void test_getResourceHierarchies() {
          *  - [ Database Table Column ]
          *  - [ Database Table Table-Attribute ]
          */
-        RangerResourceDef database       = createResourceDef("Database", "");
-        RangerResourceDef udf            = createResourceDef("UDF", "Database");
-        RangerResourceDef table          = createResourceDef("Table", "Database");
-        RangerResourceDef column         = createResourceDef("Column", "Table", true);
-        RangerResourceDef tableAttribute = createResourceDef("Table-Attribute", "Table", true);
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+        when(serviceDef.getName()).thenReturn("a-service-def");
+        when(serviceDef.getUpdateTime()).thenReturn(getNow());
+
+        RangerResourceDef database       = createRealResourceDef("Database", null, 1, null);
+        RangerResourceDef udf            = createRealResourceDef("UDF", "Database", 2, null);
+        RangerResourceDef table          = createRealResourceDef("Table", "Database", 2, null);
+        RangerResourceDef column         = createRealResourceDef("Column", "Table", 3, true);
+        RangerResourceDef tableAttribute = createRealResourceDef("Table-Attribute", "Table", 3, true);
 
         // order of resources in list sould not matter
         List<RangerResourceDef> resourceDefs = Lists.newArrayList(column, database, table, tableAttribute, udf);
 
         // stuff this into a service-def
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
         // now assert the behavior
-        helper = new RangerServiceDefHelper(serviceDef);
+        RangerServiceDefHelper         helper = new RangerServiceDefHelper(serviceDef);
 
         assertTrue(helper.isResourceGraphValid());
 
         Set<List<RangerResourceDef>> hierarchies = helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS);
-        List<RangerResourceDef>      hierarchy   = Lists.newArrayList(database, udf);
 
-        // there should be
-        assertTrue(hierarchies.contains(hierarchy));
+        Set<List<String>> expectedHierarchies = new HashSet<>();
+        expectedHierarchies.add(Lists.newArrayList("Database", "UDF"));
+        expectedHierarchies.add(Lists.newArrayList("Database", "Table", "Column"));
+        expectedHierarchies.add(Lists.newArrayList("Database", "Table", "Table-Attribute"));
 
-        hierarchy = Lists.newArrayList(database, table, column);
-        assertTrue(hierarchies.contains(hierarchy));
+        for (List<RangerResourceDef> aHierarchy : hierarchies) {
+            List<String> resourceNames = helper.getAllResourceNamesOrdered(aHierarchy);
+            if (expectedHierarchies.contains(resourceNames)) {
+                expectedHierarchies.remove(resourceNames);
+            }
+        }
 
-        hierarchy = Lists.newArrayList(database, table, tableAttribute);
-        assertTrue(hierarchies.contains(hierarchy));
+        assertTrue(expectedHierarchies.isEmpty());
     }
 
     @Test
@@ -133,19 +141,24 @@ public final void test_isResourceGraphValid_detectCycle() {
          *  |           |
          *  |---- D <---
          */
-        RangerResourceDef a = createResourceDef("A", "D"); // A's parent is D, etc.
-        RangerResourceDef b = createResourceDef("B", "C");
-        RangerResourceDef c = createResourceDef("C", "D");
-        RangerResourceDef d = createResourceDef("D", "A");
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+        when(serviceDef.getName()).thenReturn("a-service-def");
+        when(serviceDef.getUpdateTime()).thenReturn(getNow());
+
+        RangerResourceDef a = createMockResourceDef("A", "D"); // A's parent is D, etc.
+        RangerResourceDef b = createMockResourceDef("B", "C");
+        RangerResourceDef c = createMockResourceDef("C", "D");
+        RangerResourceDef d = createMockResourceDef("D", "A");
 
         // order of resources in list sould not matter
         List<RangerResourceDef> resourceDefs = Lists.newArrayList(a, b, c, d);
 
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
-        helper = new RangerServiceDefHelper(serviceDef);
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
 
-        assertFalse(helper.isResourceGraphValid(), "Graph was valid!");
+        assertFalse(helper.isResourceGraphValid());
     }
 
     @Test
@@ -164,18 +177,23 @@ public final void test_isResourceGraphValid_forest() {
          *
          * Check that helper corrects reports back all of the hierarchies: levels in it and their order.
          */
-        RangerResourceDef       database     = createResourceDef("database", "");
-        RangerResourceDef       tableSpace   = createResourceDef("table-space", "database", true);
-        RangerResourceDef       table        = createResourceDef("table", "database");
-        RangerResourceDef       column       = createResourceDef("column", "table", true);
-        RangerResourceDef       namespace    = createResourceDef("namespace", "");
-        RangerResourceDef       function     = createResourceDef("function", "namespace", true);
-        RangerResourceDef       packagE      = createResourceDef("package", "namespace", true);
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+        when(serviceDef.getName()).thenReturn("a-service-def");
+        when(serviceDef.getUpdateTime()).thenReturn(getNow());
+
+        RangerResourceDef       database     = createMockResourceDef("database", "");
+        RangerResourceDef       tableSpace   = createMockResourceDef("table-space", "database", true);
+        RangerResourceDef       table        = createMockResourceDef("table", "database");
+        RangerResourceDef       column       = createMockResourceDef("column", "table", true);
+        RangerResourceDef       namespace    = createMockResourceDef("namespace", "");
+        RangerResourceDef       function     = createMockResourceDef("function", "namespace", true);
+        RangerResourceDef       packagE      = createMockResourceDef("package", "namespace", true);
         List<RangerResourceDef> resourceDefs = Lists.newArrayList(database, tableSpace, table, column, namespace, function, packagE);
 
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
-        helper = new RangerServiceDefHelper(serviceDef);
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
 
         assertTrue(helper.isResourceGraphValid());
 
@@ -195,7 +213,7 @@ public final void test_isResourceGraphValid_forest() {
             expectedHierarchies.remove(resourceNames);
         }
 
-        assertTrue(expectedHierarchies.isEmpty(), "Missing hierarchies: " + expectedHierarchies); // make sure we got back all hierarchies
+        assertTrue(expectedHierarchies.isEmpty());  // make sure we got back all hierarchies
     }
 
     @Test
@@ -214,16 +232,21 @@ public final void test_isResourceGraphValid_forest_singleNodeTrees() {
          *
          * Check that helper corrects reports back all of the hierarchies: levels in it and their order.
          */
-        RangerResourceDef       database     = createResourceDef("database", "");
-        RangerResourceDef       server       = createResourceDef("server", "");
-        RangerResourceDef       namespace    = createResourceDef("namespace", "");
-        RangerResourceDef       function     = createResourceDef("function", "namespace", true);
-        RangerResourceDef       packagE      = createResourceDef("package", "namespace", true);
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+        when(serviceDef.getName()).thenReturn("a-service-def");
+        when(serviceDef.getUpdateTime()).thenReturn(getNow());
+
+        RangerResourceDef       database  = createRealResourceDef("database", null, 1, null);
+        RangerResourceDef       server    = createRealResourceDef("server", null, 1, null);
+        RangerResourceDef       namespace = createRealResourceDef("namespace", null, 1, null);
+        RangerResourceDef       function  = createRealResourceDef("function", "namespace", 2, true);
+        RangerResourceDef       packagE   = createRealResourceDef("package", "namespace", 2, true);
         List<RangerResourceDef> resourceDefs = Lists.newArrayList(database, server, namespace, function, packagE);
 
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
-        helper = new RangerServiceDefHelper(serviceDef);
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
 
         assertTrue(helper.isResourceGraphValid());
 
@@ -243,34 +266,31 @@ public final void test_isResourceGraphValid_forest_singleNodeTrees() {
             expectedHierarchies.remove(resourceNames);
         }
 
-        assertTrue(expectedHierarchies.isEmpty(), "Missing hierarchies: " + expectedHierarchies); // make sure we got back all hierarchies
+        assertTrue(expectedHierarchies.isEmpty()); // make sure we got back all hierarchies
     }
 
     @Test
     public final void test_cacheBehavior() {
-        // wipe the cache clean
-        RangerServiceDefHelper.cache.clear();
-
         // let's add one entry to the cache
         Delegate delegate    = mock(Delegate.class);
         Date     aDate       = getNow();
         String   serviceName = "a-service-def";
 
-        lenient().when(delegate.getServiceFreshnessDate()).thenReturn(aDate);
-        lenient().when(delegate.getServiceName()).thenReturn(serviceName);
+        when(delegate.getServiceFreshnessDate()).thenReturn(aDate);
 
         RangerServiceDefHelper.cache.put(serviceName, delegate);
 
         // create a service def with matching date value
-        serviceDef = mock(RangerServiceDef.class);
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
 
         when(serviceDef.getName()).thenReturn(serviceName);
         when(serviceDef.getUpdateTime()).thenReturn(aDate);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
         // since cache has it, we should get back the one that we have added
-        helper = new RangerServiceDefHelper(serviceDef);
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
 
-        assertSame(delegate, helper.delegate, "Didn't get back the same object that was put in cache");
+        assertSame(delegate, helper.delegate);
 
         // if we change the date then that should force helper to create a new delegate instance
         /*
@@ -281,14 +301,14 @@ public final void test_cacheBehavior() {
 
         helper = new RangerServiceDefHelper(serviceDef);
 
-        assertNotSame(delegate, helper.delegate, "Didn't get a delegate different than what was put in the cache");
+        assertNotSame(delegate, helper.delegate);
 
         // now that a new instance was added to the cache let's ensure that it got added to the cache
         Delegate newDelegate = helper.delegate;
 
         helper = new RangerServiceDefHelper(serviceDef);
 
-        assertSame(newDelegate, helper.delegate, "Didn't get a delegate different than what was put in the cache");
+        assertSame(newDelegate, helper.delegate);
     }
 
     @Test
@@ -317,40 +337,46 @@ public void test_getResourceHierarchies_with_leaf_specification() {
          *  - [ Database Table ]
          *  - [ Database Table Table-Attribute ]
          */
-        RangerResourceDef database        = createResourceDef("Database", "", false);
-        RangerResourceDef udf             = createResourceDef("UDF", "Database");
-        RangerResourceDef table           = createResourceDef("Table", "Database", true);
-        RangerResourceDef column          = createResourceDef("Column", "Table", true);
-        RangerResourceDef tableAttribute = createResourceDef("Table-Attribute", "Table", true);
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+        when(serviceDef.getName()).thenReturn("a-service-def");
+        when(serviceDef.getUpdateTime()).thenReturn(getNow());
+
+        RangerResourceDef database       = createRealResourceDef("Database", null, 1, false);
+        RangerResourceDef udf            = createRealResourceDef("UDF", "Database", 2, null);
+        RangerResourceDef table          = createRealResourceDef("Table", "Database", 2, true);
+        RangerResourceDef column         = createRealResourceDef("Column", "Table", 3, true);
+        RangerResourceDef tableAttribute = createRealResourceDef("Table-Attribute", "Table", 3, true);
 
         // order of resources in list should not matter
         List<RangerResourceDef> resourceDefs = Lists.newArrayList(column, database, table, tableAttribute, udf);
 
         // stuff this into a service-def
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
         // now assert the behavior
-        helper = new RangerServiceDefHelper(serviceDef);
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
 
         assertTrue(helper.isResourceGraphValid());
 
         Set<List<RangerResourceDef>> hierarchies = helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS);
-        List<RangerResourceDef>      hierarchy   = Lists.newArrayList(database, udf);
-
-        // there should be
-        assertTrue(hierarchies.contains(hierarchy));
 
-        hierarchy = Lists.newArrayList(database, table, column);
-        assertTrue(hierarchies.contains(hierarchy));
+        Set<List<String>> expectedHierarchies = new HashSet<>();
+        expectedHierarchies.add(Lists.newArrayList("Database", "UDF"));
+        expectedHierarchies.add(Lists.newArrayList("Database", "Table", "Column"));
+        expectedHierarchies.add(Lists.newArrayList("Database", "Table", "Table-Attribute"));
+        expectedHierarchies.add(Lists.newArrayList("Database", "Table"));
 
-        hierarchy = Lists.newArrayList(database, table, tableAttribute);
-        assertTrue(hierarchies.contains(hierarchy));
+        Set<List<String>> actualHierarchies = new HashSet<>();
+        for (List<RangerResourceDef> aHierarchy : hierarchies) {
+            actualHierarchies.add(helper.getAllResourceNamesOrdered(aHierarchy));
+        }
 
-        hierarchy = Lists.newArrayList(database, table);
-        assertTrue(hierarchies.contains(hierarchy));
+        for (List<String> expected : expectedHierarchies) {
+            assertTrue(actualHierarchies.contains(expected));
+        }
 
-        hierarchy = Lists.newArrayList(database);
-        assertFalse(hierarchies.contains(hierarchy));
+        assertFalse(actualHierarchies.contains(Lists.newArrayList("Database")));
     }
 
     @Test
@@ -376,18 +402,23 @@ public void test_invalid_resourceHierarchies_with_leaf_specification() {
          *  It should fail as the hierarchy is invalid ("Error in path: sink node:[Column] is not leaf node")
          *
          */
-        RangerResourceDef       database       = createResourceDef("Database", "", false);
-        RangerResourceDef       udf            = createResourceDef("UDF", "Database");
-        RangerResourceDef       table          = createResourceDef("Table", "Database", true);
-        RangerResourceDef       column         = createResourceDef("Column", "Table", false);
-        RangerResourceDef       tableAttribute = createResourceDef("Table-Attribute", "Table", true);
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+        when(serviceDef.getName()).thenReturn("a-service-def");
+        when(serviceDef.getUpdateTime()).thenReturn(getNow());
+
+        RangerResourceDef database       = createRealResourceDef("Database", null, 1, false);
+        RangerResourceDef udf            = createRealResourceDef("UDF", "Database", 2, null);
+        RangerResourceDef table          = createRealResourceDef("Table", "Database", 2, true);
+        RangerResourceDef column         = createRealResourceDef("Column", "Table", 3, false);
+        RangerResourceDef tableAttribute = createRealResourceDef("Table-Attribute", "Table", 3, true);
         List<RangerResourceDef> resourceDefs   = Lists.newArrayList(column, database, table, tableAttribute, udf); // order of resources in list should not matter
 
         // stuff this into a service-def
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
         // now assert the behavior
-        helper = new RangerServiceDefHelper(serviceDef);
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
 
         assertFalse(helper.isResourceGraphValid());
     }
@@ -417,79 +448,525 @@ public void testRrnTemplateS3() {
     }
 
     @Test
-    public void test_getWildcardEnabledResourceDef_returnsWildcardEnabledCopy() {
-        RangerResourceDef database = createResourceDef("database", "");
-        RangerResourceDef table = createResourceDef("table", "database", true);
-        when(serviceDef.getResources()).thenReturn(Lists.newArrayList(database, table));
-        helper = new RangerServiceDefHelper(serviceDef);
-        RangerResourceDef wildcardDefDatabase = helper.getWildcardEnabledResourceDef("database", RangerPolicy.POLICY_TYPE_ACCESS);
-        RangerResourceDef wildcardDefTable = helper.getWildcardEnabledResourceDef("table", RangerPolicy.POLICY_TYPE_ACCESS);
-        assertNotNull(wildcardDefDatabase, "getWildcardEnabledResourceDef() should not return null for a valid resource");
-        assertNotSame(database, wildcardDefDatabase, "getWildcardEnabledResourceDef() must return a copy, not the original");
-        assertNotSame(table, wildcardDefTable, "getWildcardEnabledResourceDef() must return a copy, not the original");
-        assertEquals(Boolean.TRUE.toString(), wildcardDefDatabase.getMatcherOptions().get(RangerAbstractResourceMatcher.OPTION_WILD_CARD),
-                "Wildcard option must be set to true on the returned copy");
-        assertEquals(Boolean.TRUE.toString(), wildcardDefTable.getMatcherOptions().get(RangerAbstractResourceMatcher.OPTION_WILD_CARD),
-                "Wildcard option must be set to true on the returned copy");
-    }
+    public void test_getResourceHierarchies_filteredByKeys() {
+        RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+        when(serviceDef.getName()).thenReturn("a-service-def");
+        when(serviceDef.getUpdateTime()).thenReturn(getNow());
 
-    @Test
-    public void test_getWildcardEnabledResourceDef_threadSafety() throws InterruptedException {
-        int numberOfThreads = 3;
-        int numberOfIterations = 50;
+        RangerResourceDef database       = createRealResourceDef("Database", null, 1, null);
+        RangerResourceDef udf            = createRealResourceDef("UDF", "Database", 2, null);
+        RangerResourceDef table          = createRealResourceDef("Table", "Database", 2, null);
+        RangerResourceDef column         = createRealResourceDef("Column", "Table", 3, true);
+        RangerResourceDef tableAttribute = createRealResourceDef("Table-Attribute", "Table", 3, true);
 
-        RangerResourceDef database = createResourceDef("database", "");
-        RangerResourceDef table = createResourceDef("table", "database", true);
-        RangerResourceDef column = createResourceDef("column", "table", true);
+        List<RangerResourceDef> resourceDefs = Lists.newArrayList(column, database, table, tableAttribute, udf);
+        when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getAccessTypes()).thenReturn(new ArrayList<>());
 
-        when(serviceDef.getResources()).thenReturn(Lists.newArrayList(database, table, column));
-        helper = new RangerServiceDefHelper(serviceDef);
-        AtomicBoolean cmeObserved = new AtomicBoolean(false);
-        AtomicInteger successCount = new AtomicInteger(0);
-
-        for (int iter = 0; iter < numberOfIterations && !cmeObserved.get(); iter++) {
-            CountDownLatch startLatch = new CountDownLatch(1);
-            CountDownLatch doneLatch = new CountDownLatch(numberOfThreads);
-            ExecutorService pool = Executors.newFixedThreadPool(numberOfThreads);
-            for (int t = 0; t < numberOfThreads; t++) {
-                pool.submit(() -> {
-                    try {
-                        startLatch.await();
-                        RangerResourceDef def = helper.getWildcardEnabledResourceDef("database", RangerPolicy.POLICY_TYPE_ACCESS);
-                        if (def != null) {
-                            successCount.incrementAndGet();
-                        }
-                    } catch (ConcurrentModificationException e) {
-                        cmeObserved.set(true);
-                    } catch (InterruptedException e) {
-                        Thread.currentThread().interrupt();
-                    } finally {
-                        doneLatch.countDown();
-                    }
-                });
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
+        assertTrue(helper.isResourceGraphValid());
+
+        Set<String> keys = new HashSet<>();
+        keys.add("Database");
+        keys.add("Table");
+
+        Set<List<RangerResourceDef>> filtered = helper.getResourceHierarchies(RangerPolicy.POLICY_TYPE_ACCESS, keys);
+        List<RangerResourceDef> expected1 = Lists.newArrayList(database, table, column);
+        List<RangerResourceDef> expected2 = Lists.newArrayList(database, table, tableAttribute);
+
+        assertTrue(filtered.contains(expected1));
+        assertTrue(filtered.contains(expected2));
+    }
+
+    @Test
+    public void test_static_getServiceDefForPolicyFiltering_pathMatcherModification() {
+        RangerServiceDef base = new RangerServiceDef();
+        base.setName("svc");
+        base.setUpdateTime(getNow());
+        base.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef pathRes = new RangerResourceDef();
+        pathRes.setName("path");
+        pathRes.setMatcher(RangerPathResourceMatcher.class.getName());
+        Map<String, String> opts = new HashMap<>();
+        opts.put(RangerPathResourceMatcher.OPTION_PATH_SEPARATOR, "/");
+        pathRes.setMatcherOptions(opts);
+        pathRes.setRecursiveSupported(true);
+        pathRes.setLevel(1);
+
+        RangerResourceDef otherRes = new RangerResourceDef();
+        otherRes.setName("other");
+        otherRes.setMatcher("com.example.OtherMatcher");
+        otherRes.setLevel(1);
+
+        base.setResources(Arrays.asList(pathRes, otherRes));
+
+        RangerServiceDef modified = RangerServiceDefHelper.getServiceDefForPolicyFiltering(base);
+
+        RangerResourceDef modifiedPath = null;
+        RangerResourceDef modifiedOther = null;
+        for (RangerResourceDef r : modified.getResources()) {
+            if ("path".equals(r.getName())) {
+                modifiedPath = r;
+            } else if ("other".equals(r.getName())) {
+                modifiedOther = r;
             }
-            startLatch.countDown();
-            doneLatch.await(10, TimeUnit.SECONDS);
-            pool.shutdownNow();
         }
-        assertFalse(cmeObserved.get(), "ConcurrentModificationException must never occur — wildcardEnabledResourceDefs must be thread-safe after eager init fix");
-        assertEquals(numberOfThreads * numberOfIterations, successCount.get(), "All concurrent calls must return a valid result");
+        assertNotNull(modifiedPath);
+        assertNotNull(modifiedOther);
+        assertEquals("false", modifiedPath.getMatcherOptions().get(RangerAbstractResourceMatcher.OPTION_WILD_CARD));
+        assertFalse(Boolean.TRUE.equals(modifiedPath.getRecursiveSupported()));
+        assertNull(modifiedOther.getMatcherOptions() == null ? null : modifiedOther.getMatcherOptions().get(RangerAbstractResourceMatcher.OPTION_WILD_CARD));
     }
 
-    RangerResourceDef createResourceDef(String name, String parent) {
-        return createResourceDef(name, parent, null);
+    @Test
+    public void test_static_getFilterResourcesForAncestorPolicyFiltering_withDefaultDelimiterAndSuffix() {
+        RangerServiceDef base = new RangerServiceDef();
+        base.setName("svc");
+        base.setUpdateTime(getNow());
+        base.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef pathRes = new RangerResourceDef();
+        pathRes.setName("path");
+        pathRes.setMatcher(RangerPathResourceMatcher.class.getName());
+        pathRes.setLevel(1);
+        // no PATH_SEPARATOR option to force default
+        pathRes.setMatcherOptions(new HashMap<>());
+
+        RangerResourceDef otherRes = new RangerResourceDef();
+        otherRes.setName("other");
+        otherRes.setMatcher("com.example.OtherMatcher");
+        otherRes.setLevel(1);
+
+        base.setResources(Arrays.asList(pathRes, otherRes));
+
+        Map<String, String> filter = new HashMap<>();
+        filter.put("path", "a/b");
+
+        Map<String, String> out = RangerServiceDefHelper.getFilterResourcesForAncestorPolicyFiltering(base, filter);
+        assertNotNull(out);
+        assertEquals("a/b/" + RangerAbstractResourceMatcher.WILDCARD_ASTERISK, out.get("path"));
     }
 
-    RangerResourceDef createResourceDef(String name, String parent, Boolean isValidLeaf) {
-        RangerResourceDef resourceDef = mock(RangerResourceDef.class);
+    @Test
+    public void test_static_getFilterResourcesForAncestorPolicyFiltering_noMatchingReturnsNull() {
+        RangerServiceDef base = new RangerServiceDef();
+        base.setName("svc");
+        base.setUpdateTime(getNow());
+        base.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef otherRes = new RangerResourceDef();
+        otherRes.setName("other");
+        otherRes.setMatcher("com.example.OtherMatcher");
+        otherRes.setLevel(1);
+
+        base.setResources(Collections.singletonList(otherRes));
+
+        Map<String, String> filter = new HashMap<>();
+        filter.put("path", "a/b");
+
+        Map<String, String> out = RangerServiceDefHelper.getFilterResourcesForAncestorPolicyFiltering(base, filter);
+        assertNull(out);
+    }
+
+    @Test
+    public void test_resourceHierarchyKeys_nullAuditUnknown() {
+        RangerServiceDef serviceDef = createServiceDefWithSingleNodes("svc", Arrays.asList("A", "B"));
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
+
+        Set<Set<String>> accessKeys = helper.getResourceHierarchyKeys(RangerPolicy.POLICY_TYPE_ACCESS);
+        assertFalse(accessKeys.isEmpty());
+
+        Set<Set<String>> auditKeys = helper.getResourceHierarchyKeys(RangerPolicy.POLICY_TYPE_AUDIT);
+        assertIterableEquals(accessKeys, auditKeys);
+
+        Set<Set<String>> nullKeys = helper.getResourceHierarchyKeys(null);
+        assertIterableEquals(accessKeys, nullKeys);
+
+        Set<Set<String>> unknown = helper.getResourceHierarchyKeys(9999);
+        assertTrue(unknown.isEmpty());
+    }
+
+    @Test
+    public void test_isDataMaskSupported_variants() {
+        RangerServiceDef serviceDef = new RangerServiceDef();
+        serviceDef.setName("svc");
+        serviceDef.setUpdateTime(getNow());
+        serviceDef.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef dmRes = new RangerResourceDef();
+        dmRes.setName("DM");
+        dmRes.setLevel(1);
+
+        RangerDataMaskDef dmd = new RangerDataMaskDef();
+        dmd.setResources(Collections.singletonList(dmRes));
+        serviceDef.setDataMaskDef(dmd);
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
+        assertTrue(helper.isDataMaskSupported());
+        Set<String> match = new HashSet<>();
+        match.add("DM");
+        assertTrue(helper.isDataMaskSupported(match));
+
+        Set<String> noMatch = new HashSet<>();
+        noMatch.add("X");
+        assertFalse(helper.isDataMaskSupported(noMatch));
+    }
+
+    @Test
+    public void test_isRowFilterSupported_variants() {
+        RangerServiceDef serviceDef = new RangerServiceDef();
+        serviceDef.setName("svc");
+        serviceDef.setUpdateTime(getNow());
+        serviceDef.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef rfRes = new RangerResourceDef();
+        rfRes.setName("RF");
+        rfRes.setLevel(1);
+
+        RangerRowFilterDef rfd = new RangerRowFilterDef();
+        rfd.setResources(Collections.singletonList(rfRes));
+        serviceDef.setRowFilterDef(rfd);
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(serviceDef);
+        assertTrue(helper.isRowFilterSupported());
+
+        Set<String> match = new HashSet<>();
+        match.add("RF");
+        assertTrue(helper.isRowFilterSupported(match));
+
+        Set<String> noMatch = new HashSet<>();
+        noMatch.add("Y");
+        assertFalse(helper.isRowFilterSupported(noMatch));
+    }
+
+    @Test
+    public void test_filterHierarchies_containsOnlyMandatoryResources() {
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+        svc.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef r1 = new RangerResourceDef();
+        r1.setName("A");
+        r1.setLevel(1);
+        r1.setMandatory(true);
+
+        RangerResourceDef r2 = new RangerResourceDef();
+        r2.setName("B");
+        r2.setParent("A");
+        r2.setLevel(2);
+        r2.setMandatory(true);
+        r2.setIsValidLeaf(true);
+
+        RangerResourceDef r3 = new RangerResourceDef();
+        r3.setName("C");
+        r3.setParent("B");
+        r3.setLevel(3);
+        r3.setMandatory(false);
+
+        svc.setResources(Arrays.asList(r1, r2, r3));
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc);
+        Set<List<RangerResourceDef>> onlyMandatory = helper.filterHierarchies_containsOnlyMandatoryResources(RangerPolicy.POLICY_TYPE_ACCESS);
+        assertTrue(onlyMandatory.contains(Lists.newArrayList(r1, r2)));
+        assertFalse(onlyMandatory.contains(Lists.newArrayList(r1, r2, r3)));
+    }
+
+    @Test
+    public void test_isValidHierarchy_exact_vs_contains() {
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+        svc.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef resA = new RangerResourceDef();
+        resA.setName("A");
+        resA.setLevel(1);
+
+        RangerResourceDef resB = new RangerResourceDef();
+        resB.setName("B");
+        resB.setParent("A");
+        resB.setLevel(2);
+
+        RangerResourceDef resC = new RangerResourceDef();
+        resC.setName("C");
+        resC.setParent("B");
+        resC.setLevel(3);
+
+        svc.setResources(Arrays.asList(resA, resB, resC));
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc);
+
+        Set<String> subset = new HashSet<>();
+        subset.add("A");
+        subset.add("B");
+
+        Set<String> exact = new HashSet<>();
+        exact.add("A");
+        exact.add("B");
+        exact.add("C");
+
+        assertTrue(helper.isValidHierarchy(RangerPolicy.POLICY_TYPE_ACCESS, subset, false));
+        assertFalse(helper.isValidHierarchy(RangerPolicy.POLICY_TYPE_ACCESS, subset, true));
+        assertTrue(helper.isValidHierarchy(RangerPolicy.POLICY_TYPE_ACCESS, exact, true));
+    }
+
+    @Test
+    public void test_hierarchyHasAllResources_true_false() {
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+        svc.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef resA = new RangerResourceDef();
+        resA.setName("A");
+        resA.setLevel(1);
+
+        RangerResourceDef resB = new RangerResourceDef();
+        resB.setName("B");
+        resB.setParent("A");
+        resB.setLevel(2);
+
+        List<RangerResourceDef> hierarchy = Arrays.asList(resA, resB);
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc);
+
+        Set<String> yes = new HashSet<>();
+        yes.add("A");
+        yes.add("B");
+        assertTrue(helper.hierarchyHasAllResources(hierarchy, yes));
+
+        Set<String> no = new HashSet<>();
+        no.add("A");
+        no.add("C");
+        assertFalse(helper.hierarchyHasAllResources(hierarchy, no));
+    }
+
+    @Test
+    public void test_getMandatoryResourceNames_and_getAllResourceNamesOrdered() {
+        RangerResourceDef resA = new RangerResourceDef();
+        resA.setName("A");
+        resA.setLevel(1);
+        resA.setMandatory(true);
+
+        RangerResourceDef resB = new RangerResourceDef();
+        resB.setName("B");
+        resB.setParent("A");
+        resB.setLevel(2);
+        resB.setMandatory(false);
+
+        List<RangerResourceDef> hierarchy = Arrays.asList(resA, resB);
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(createServiceDef("svc", hierarchy));
+
+        Set<String> mandatory = helper.getMandatoryResourceNames(hierarchy);
+        assertTrue(mandatory.contains("A"));
+        assertFalse(mandatory.contains("B"));
+
+        List<String> ordered = helper.getAllResourceNamesOrdered(hierarchy);
+        assertIterableEquals(Arrays.asList("A", "B"), ordered);
+    }
+
+    @Test
+    public void test_getOrderedResourceNames_orderingAndNull() {
+        RangerResourceDef resA = new RangerResourceDef();
+        resA.setName("A");
+        resA.setLevel(2);
+
+        RangerResourceDef resB = new RangerResourceDef();
+        resB.setName("B");
+        resB.setLevel(1);
+
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+        svc.setResources(Arrays.asList(resA, resB));
+        svc.setAccessTypes(new ArrayList<>());
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc, false);
 
-        lenient().when(resourceDef.getName()).thenReturn(name);
-        lenient().when(resourceDef.getParent()).thenReturn(parent);
-        lenient().when(resourceDef.getIsValidLeaf()).thenReturn(isValidLeaf);
+        List<String> input = Arrays.asList("A", "B");
+        List<String> ordered = helper.getOrderedResourceNames(input);
+        assertIterableEquals(Arrays.asList("B", "A"), ordered);
 
+        List<String> nullOrdered = helper.getOrderedResourceNames(null);
+        assertTrue(nullOrdered.isEmpty());
+    }
+
+    @Test
+    public void test_getResourceDef_nullPolicyTypeAndSpecific() {
+        RangerResourceDef resA = new RangerResourceDef();
+        resA.setName("A");
+        resA.setLevel(1);
+        RangerResourceDef resB = new RangerResourceDef();
+        resB.setName("B");
+        resB.setLevel(1);
+
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+        svc.setResources(Arrays.asList(resA, resB));
+        svc.setAccessTypes(new ArrayList<>());
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc);
+        assertEquals("A", helper.getResourceDef("A", null).getName());
+        assertNull(helper.getResourceDef("Z", RangerPolicy.POLICY_TYPE_ACCESS));
+    }
+
+    @Test
+    public void test_getWildcardEnabledResourceDef_cachingAndNullCase() {
+        RangerResourceDef resA = new RangerResourceDef();
+        resA.setName("A");
+        resA.setLevel(1);
+        resA.setMatcher("com.example.X");
+        resA.setMatcherOptions(new HashMap<>());
+
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+        svc.setResources(Collections.singletonList(resA));
+        svc.setAccessTypes(new ArrayList<>());
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc);
+        RangerResourceDef wr1 = helper.getWildcardEnabledResourceDef("A", RangerPolicy.POLICY_TYPE_ACCESS);
+        assertNotNull(wr1);
+        assertEquals("true", wr1.getMatcherOptions().get(RangerAbstractResourceMatcher.OPTION_WILD_CARD));
+
+        RangerResourceDef wr2 = helper.getWildcardEnabledResourceDef("A", RangerPolicy.POLICY_TYPE_ACCESS);
+        assertSame(wr1, wr2);
+
+        RangerResourceDef missing = helper.getWildcardEnabledResourceDef("Z", RangerPolicy.POLICY_TYPE_ACCESS);
+        assertNull(missing);
+        RangerResourceDef missingAgain = helper.getWildcardEnabledResourceDef("Z", RangerPolicy.POLICY_TYPE_ACCESS);
+        assertNull(missingAgain);
+    }
+
+    @Test
+    public void test_expandImpliedAccessGrants_cases() {
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+
+        RangerAccessTypeDef read = new RangerAccessTypeDef();
+        read.setName("read");
+        read.setImpliedGrants(Arrays.asList("view"));
+
+        RangerAccessTypeDef write = new RangerAccessTypeDef();
+        write.setName("write");
+        write.setImpliedGrants(null);
+
+        RangerAccessTypeDef viewMarker = new RangerAccessTypeDef();
+        viewMarker.setName("view");
+        viewMarker.setImpliedGrants(Arrays.asList("inspect"));
+
+        svc.setAccessTypes(Arrays.asList(read, write));
+        svc.setMarkerAccessTypes(Collections.singletonList(viewMarker));
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc);
+
+        assertTrue(helper.getImpliedAccessGrants().containsKey("read"));
+        assertTrue(helper.getImpliedAccessGrants().containsKey("view"));
+        assertFalse(helper.getImpliedAccessGrants().containsKey("write"));
+
+        Set<String> empty = helper.expandImpliedAccessGrants(null);
+        assertTrue(empty.isEmpty());
+
+        Set<String> none = new HashSet<>();
+        none.add("write");
+        Set<String> noneOut = helper.expandImpliedAccessGrants(none);
+        assertSame(none, noneOut);
+
+        Set<String> some = new HashSet<>();
+        some.add("read");
+        Set<String> expanded = helper.expandImpliedAccessGrants(some);
+        assertTrue(expanded.contains("read"));
+        assertTrue(expanded.contains("view"));
+        // expansion is not recursive; should not include implied of implied
+        assertFalse(expanded.contains("inspect"));
+    }
+
+    @Test
+    public void test_patchServiceDefWithDefaultValues_setsLeafOnHierarchyEnds() {
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName("svc");
+        svc.setUpdateTime(getNow());
+        svc.setAccessTypes(new ArrayList<>());
+
+        RangerResourceDef resA = new RangerResourceDef();
+        resA.setName("A");
+        resA.setLevel(1);
+        resA.setIsValidLeaf(null);
+
+        RangerResourceDef resB = new RangerResourceDef();
+        resB.setName("B");
+        resB.setParent("A");
+        resB.setLevel(2);
+        resB.setIsValidLeaf(null);
+
+        RangerResourceDef resC = new RangerResourceDef();
+        resC.setName("C");
+        resC.setParent("B");
+        resC.setLevel(3);
+        resC.setIsValidLeaf(null);
+
+        svc.setResources(Arrays.asList(resA, resB, resC));
+
+        RangerServiceDefHelper helper = new RangerServiceDefHelper(svc);
+        helper.patchServiceDefWithDefaultValues();
+
+        assertFalse(Boolean.TRUE.equals(resA.getIsValidLeaf()));
+        assertFalse(Boolean.TRUE.equals(resB.getIsValidLeaf()));
+        assertTrue(Boolean.TRUE.equals(resC.getIsValidLeaf()));
+    }
+
+    private RangerServiceDef createServiceDef(String name, List<RangerResourceDef> resources) {
+        RangerServiceDef svc = new RangerServiceDef();
+        svc.setName(name);
+        svc.setUpdateTime(getNow());
+        svc.setResources(resources);
+        svc.setAccessTypes(new ArrayList<>());
+        return svc;
+    }
+
+    private RangerServiceDef createServiceDefWithSingleNodes(String name, List<String> resourceNames) {
+        List<RangerResourceDef> defs = new ArrayList<>();
+        int level = 1;
+        for (String rn : resourceNames) {
+            RangerResourceDef d = new RangerResourceDef();
+            d.setName(rn);
+            d.setLevel(level++);
+            defs.add(d);
+        }
+        return createServiceDef(name, defs);
+    }
+
+    private RangerResourceDef createMockResourceDef(String name, String parent) {
+        RangerResourceDef resourceDef = mock(RangerResourceDef.class);
+        when(resourceDef.getName()).thenReturn(name);
+        when(resourceDef.getParent()).thenReturn(parent);
         return resourceDef;
     }
 
+    private RangerResourceDef createMockResourceDef(String name, String parent, Boolean isValidLeaf) {
+        RangerResourceDef resourceDef = mock(RangerResourceDef.class);
+        when(resourceDef.getName()).thenReturn(name);
+        when(resourceDef.getParent()).thenReturn(parent);
+        if (isValidLeaf != null) {
+            when(resourceDef.getIsValidLeaf()).thenReturn(isValidLeaf);
+        }
+        return resourceDef;
+    }
+
+    private RangerResourceDef createRealResourceDef(String name, String parent, int level, Boolean isValidLeaf) {
+        RangerResourceDef r = new RangerResourceDef();
+        r.setName(name);
+        r.setParent(parent);
+        r.setLevel(level);
+        r.setIsValidLeaf(isValidLeaf);
+        return r;
+    }
+
     Date getLastMonth() {
         Calendar cal = GregorianCalendar.getInstance();
 
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
index 3d22784fc..a178f3174 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
@@ -465,7 +465,6 @@ public final void test_isValidResourceGraph() {
 
         failures.clear();
         assertFalse(validator.isValidResourceGraph(serviceDef, failures));
-        utils.checkFailureForMissingValue(failures, "resource level");
         utils.checkFailureForSemanticError(failures, "resource level", "20"); // level 20 is duplicate for 1 hierarchy
         utils.checkFailureForSemanticError(failures, "resource level", "10"); // level 10 is duplicate for another hierarchy
 
@@ -495,6 +494,8 @@ public final void test_isValidResourceGraph() {
         };
         resourceDefs = utils.createResourceDefs(dataGood);
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getName()).thenReturn("service-name");
+        when(serviceDef.getUpdateTime()).thenReturn(new Date());
         failures.clear();
         assertTrue(validator.isValidResourceGraph(serviceDef, failures));
         assertTrue(failures.isEmpty());
@@ -509,6 +510,8 @@ public final void test_isValidResourceGraph() {
 
         resourceDefs = utils.createResourceDefs(dataCycles);
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getName()).thenReturn("service-name");
+        when(serviceDef.getUpdateTime()).thenReturn(new Date());
         failures.clear();
         assertFalse(validator.isValidResourceGraph(serviceDef, failures), "Graph was valid!");
         assertFalse(failures.isEmpty());
@@ -523,6 +526,8 @@ public final void test_isValidResourceGraph() {
         };
         resourceDefs = utils.createResourceDefs(dataBad);
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getName()).thenReturn("service-name");
+        when(serviceDef.getUpdateTime()).thenReturn(new Date());
         failures.clear();
         assertFalse(validator.isValidResourceGraph(serviceDef, failures));
         assertFalse(failures.isEmpty());
@@ -536,6 +541,8 @@ public final void test_isValidResourceGraph() {
         };
         resourceDefs = utils.createResourceDefs(dataGood);
         when(serviceDef.getResources()).thenReturn(resourceDefs);
+        when(serviceDef.getName()).thenReturn("service-name");
+        when(serviceDef.getUpdateTime()).thenReturn(new Date());
         failures.clear();
         assertTrue(validator.isValidResourceGraph(serviceDef, failures));
         assertTrue(failures.isEmpty());
@@ -613,4 +620,46 @@ public final void test_isValidPolicyConditions() {
         utils.checkFailureForMissingValue(failures, "policy condition def evaluator", "condition-2");
         utils.checkFailureForMissingValue(failures, "policy condition def evaluator", "condition-1");
     }
+
+    @Test
+    public final void test_isValidServiceDefDisplayName_conflicts() throws Exception {
+        Long id = null;
+        String displayName = "svc-display";
+        RangerServiceDef other = mock(RangerServiceDef.class);
+        when(other.getId()).thenReturn(99L);
+        when(other.getName()).thenReturn("svc-name");
+        when(store.getServiceDefByDisplayName(displayName)).thenReturn(other);
+        assertFalse(validator.isValidServiceDefDisplayName(displayName, id, Action.CREATE, failures));
+        utils.checkFailureForSemanticError(failures, "displayName");
+
+        failures.clear();
+        id = 7L;
+        assertFalse(validator.isValidServiceDefDisplayName(displayName, id, Action.UPDATE, failures));
+        utils.checkFailureForSemanticError(failures, "id/displayName");
+    }
+
+    @Test
+    public final void test_isValidConfigs_enumTypeBranches() {
+        List<RangerServiceDef.RangerServiceConfigDef> configs = new ArrayList<>();
+        RangerServiceDef.RangerServiceConfigDef enumCfg = new RangerServiceDef.RangerServiceConfigDef();
+        enumCfg.setItemId(1L);
+        enumCfg.setName("enumCfg");
+        enumCfg.setType("enum");
+        enumCfg.setSubType("time-unit");
+        enumCfg.setDefaultValue("year"); // not in enum
+        configs.add(enumCfg);
+
+        List<RangerEnumDef> enumDefs = utils.createEnumDefs(new Object[][] {
+                {1L, "time-unit", new String[] {"day", "hour"}}
+        });
+
+        assertFalse(validator.isValidConfigs(configs, enumDefs, failures));
+        utils.checkFailureForSemanticError(failures, "config def default value", "enumCfg");
+
+        failures.clear();
+        enumCfg.setSubType("unknown-enum");
+        enumCfg.setDefaultValue(null);
+        assertFalse(validator.isValidConfigs(configs, enumDefs, failures));
+        utils.checkFailureForSemanticError(failures, "config def subtype", "enumCfg");
+    }
 }
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
index 010dc19ac..bf9a90723 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
@@ -25,18 +25,30 @@
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
 import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
 import org.apache.ranger.plugin.store.ServiceStore;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.MethodOrderer;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.util.ArrayList;
 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.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for RangerServiceValidator class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class TestRangerServiceValidator {
     private final Action[]                       cu        = new Action[] {Action.CREATE, Action.UPDATE};
     private       ServiceStore                   store;
@@ -45,15 +57,16 @@ public class TestRangerServiceValidator {
     private final ValidationTestUtils            utils    = new ValidationTestUtils();
     private final List<ValidationFailureDetails> failures = new ArrayList<>();
 
-    @BeforeEach
-    public void before() {
+    private void initialize() {
         store     = mock(ServiceStore.class);
         action    = Action.CREATE; // by default we set action to create
         validator = new RangerServiceValidator(store);
+        failures.clear();
     }
 
     @Test
     public void testIsValidServiceNameCreationWithOutSpecialCharacters() throws Exception {
+        initialize();
         String serviceName  = "c1_yarn";
 
         RangerService rangerService = new RangerService();
@@ -80,12 +93,13 @@ public void testIsValidServiceNameCreationWithOutSpecialCharacters() throws Exce
 
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean valid = validator.isValid(rangerService, Action.CREATE, failures);
-        Assertions.assertEquals(0, failures.size());
-        Assertions.assertTrue(valid);
+        assertEquals(0, failures.size());
+        assertTrue(valid);
     }
 
     @Test
     public void testIsValidServiceNameUpdationWithOutSpecialCharacters() throws Exception {
+        initialize();
         String serviceName = "c1_yarn";
 
         RangerService rangerService = new RangerService();
@@ -114,12 +128,13 @@ public void testIsValidServiceNameUpdationWithOutSpecialCharacters() throws Exce
         when(store.getService(1L)).thenReturn(rangerService);
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean valid = validator.isValid(rangerService, Action.UPDATE, failures);
-        Assertions.assertEquals(0, failures.size());
-        Assertions.assertTrue(valid);
+        assertEquals(0, failures.size());
+        assertTrue(valid);
     }
 
     @Test
     public void testIsValidServiceNameUpdationWithSpecialCharacters() throws Exception {
+        initialize();
         String serviceName = "<alert>c1_yarn</alert>";
 
         ValidationErrorCode vErrCod      = ValidationErrorCode.SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_NAME;
@@ -150,16 +165,17 @@ public void testIsValidServiceNameUpdationWithSpecialCharacters() throws Excepti
 
         when(store.getService(1L)).thenReturn(rangerService);
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
-        boolean                  valid          = validator.isValid(rangerService, Action.UPDATE, failures);
+        boolean valid = validator.isValid(rangerService, Action.UPDATE, failures);
         ValidationFailureDetails failureMessage = failures.get(0);
-        Assertions.assertFalse(valid);
-        Assertions.assertEquals("name", failureMessage.getFieldName());
-        Assertions.assertEquals(errorMessage, failureMessage.reason);
-        Assertions.assertEquals(errorCode, failureMessage.errorCode);
+        assertFalse(valid);
+        assertEquals("name", failureMessage.getFieldName());
+        assertEquals(errorMessage, failureMessage.reason);
+        assertEquals(errorCode, failureMessage.errorCode);
     }
 
     @Test
     public void testIsValidServiceNameCreationWithSpecialCharacters() throws Exception {
+        initialize();
         String serviceName = "<script>c1_yarn</script>";
 
         ValidationErrorCode vErrCod      = ValidationErrorCode.SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_NAME;
@@ -190,14 +206,15 @@ public void testIsValidServiceNameCreationWithSpecialCharacters() throws Excepti
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean                  valid          = validator.isValid(rangerService, action, failures);
         ValidationFailureDetails failureMessage = failures.get(0);
-        Assertions.assertFalse(valid);
-        Assertions.assertEquals("name", failureMessage.getFieldName());
-        Assertions.assertEquals(errorMessage, failureMessage.reason);
-        Assertions.assertEquals(errorCode, failureMessage.errorCode);
+        assertFalse(valid);
+        assertEquals("name", failureMessage.getFieldName());
+        assertEquals(errorMessage, failureMessage.reason);
+        assertEquals(errorCode, failureMessage.errorCode);
     }
 
     @Test
     public void testIsValidServiceNameCreationWithSpaceCharacter() throws Exception {
+        initialize();
         String serviceName = "Cluster 1_c1_yarn";
 
         ValidationErrorCode vErrCod      = ValidationErrorCode.SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_NAME;
@@ -229,15 +246,16 @@ public void testIsValidServiceNameCreationWithSpaceCharacter() throws Exception
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean                  valid          = validator.isValid(rangerService, action, failures);
         ValidationFailureDetails failureMessage = failures.get(0);
-        Assertions.assertFalse(valid);
-        Assertions.assertEquals("name", failureMessage.getFieldName());
-        Assertions.assertEquals(errorMessage, failureMessage.reason);
-        Assertions.assertEquals(errorCode, failureMessage.errorCode);
+        assertFalse(valid);
+        assertEquals("name", failureMessage.getFieldName());
+        assertEquals(errorMessage, failureMessage.reason);
+        assertEquals(errorCode, failureMessage.errorCode);
     }
 
     @Test
     public void testIsValidServiceNameUpdationWithSpaceCharacter() throws Exception {
-        String serviceName        = "Cluster 1_c1_yarn";
+        initialize();
+        String serviceName = "Cluster 1_c1_yarn";
 
         ValidationErrorCode vErrCod      = ValidationErrorCode.SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_NAME;
         String              errorMessage = vErrCod.getMessage(serviceName);
@@ -280,20 +298,21 @@ public void testIsValidServiceNameUpdationWithSpaceCharacter() throws Exception
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean                  valid          = validator.isValid(rangerService, Action.UPDATE, failures);
         ValidationFailureDetails failureMessage = failures.get(0);
-        Assertions.assertFalse(valid);
-        Assertions.assertEquals("name", failureMessage.getFieldName());
-        Assertions.assertEquals(errorMessage, failureMessage.reason);
-        Assertions.assertEquals(errorCode, failureMessage.errorCode);
+        assertFalse(valid);
+        assertEquals("name", failureMessage.getFieldName());
+        assertEquals(errorMessage, failureMessage.reason);
+        assertEquals(errorCode, failureMessage.errorCode);
 
         //Case: previous service name does have space, updating with name containing space
         when(store.getService(1L)).thenReturn(rangerService);
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean validWithSpace = validator.isValid(rangerService, Action.UPDATE, failures);
-        Assertions.assertTrue(validWithSpace);
+        assertTrue(validWithSpace);
     }
 
     @Test
     public void testIsValidServiceNameCreationWithGreater255Characters() throws Exception {
+        initialize();
         String serviceName = "c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1";
 
         ValidationErrorCode vErrCod      = ValidationErrorCode.SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_NAME;
@@ -324,14 +343,15 @@ public void testIsValidServiceNameCreationWithGreater255Characters() throws Exce
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean                  valid          = validator.isValid(rangerService, action, failures);
         ValidationFailureDetails failureMessage = failures.get(0);
-        Assertions.assertFalse(valid);
-        Assertions.assertEquals("name", failureMessage.getFieldName());
-        Assertions.assertEquals(errorMessage, failureMessage.reason);
-        Assertions.assertEquals(errorCode, failureMessage.errorCode);
+        assertFalse(valid);
+        assertEquals("name", failureMessage.getFieldName());
+        assertEquals(errorMessage, failureMessage.reason);
+        assertEquals(errorCode, failureMessage.errorCode);
     }
 
     @Test
     public void testIsValidServiceNameUpdationWithGreater255Characters() throws Exception {
+        initialize();
         String serviceName = "c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1_yarn_c1";
 
         ValidationErrorCode vErrCod      = ValidationErrorCode.SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_NAME;
@@ -364,23 +384,24 @@ public void testIsValidServiceNameUpdationWithGreater255Characters() throws Exce
         when(store.getServiceDefByName("yarn")).thenReturn(rangerServiceDef);
         boolean                  valid          = validator.isValid(rangerService, Action.UPDATE, failures);
         ValidationFailureDetails failureMessage = failures.get(0);
-        Assertions.assertFalse(valid);
-        Assertions.assertEquals("name", failureMessage.getFieldName());
-        Assertions.assertEquals(errorMessage, failureMessage.reason);
-        Assertions.assertEquals(errorCode, failureMessage.errorCode);
+        assertFalse(valid);
+        assertEquals("name", failureMessage.getFieldName());
+        assertEquals(errorMessage, failureMessage.reason);
+        assertEquals(errorCode, failureMessage.errorCode);
     }
 
     @Test
     public void testIsValid_failures() throws Exception {
+        initialize();
         RangerService service = mock(RangerService.class);
         // passing in a null service to the check itself is an error
-        Assertions.assertFalse(validator.isValid((RangerService) null, action, failures));
+        assertFalse(validator.isValid((RangerService) null, action, failures));
         utils.checkFailureForMissingValue(failures, "service");
 
         // id is required for update
         when(service.getId()).thenReturn(null);
         // let's verify the failure and the sort of error information that is returned (for one of these)
-        // Assertions.assert that among the failure reason is one about id being missing.
+        // Assert.assert that among the failure reason is one about id being missing.
         checkFailure_isValid(validator, service, Action.UPDATE, failures, "missing", "id");
         when(service.getId()).thenReturn(7L);
 
@@ -430,6 +451,7 @@ public void testIsValid_failures() throws Exception {
 
     @Test
     public void test_isValid_missingRequiredParameter() throws Exception {
+        initialize();
         // Create/Update: simulate a condition where required parameters are missing
         Object[][] input = new Object[][] {
                 {"param1", true},
@@ -460,6 +482,7 @@ public void test_isValid_missingRequiredParameter() throws Exception {
 
     @Test
     public void test_isValid_happyPath() throws Exception {
+        initialize();
         // create a service def with some required parameters
         Object[][] serviceDefInput = new Object[][] {
                 {"param1", true},
@@ -486,7 +509,7 @@ public void test_isValid_happyPath() throws Exception {
         // service def exists
         when(store.getServiceDefByName("aType")).thenReturn(serviceDef);
 
-        Assertions.assertTrue(validator.isValid(service, Action.CREATE, failures));
+        assertTrue(validator.isValid(service, Action.CREATE, failures));
 
         // for update to work the only additional requirement is that id is required and service should exist
         // if name is not null and it points to a service then it should match the id
@@ -495,40 +518,42 @@ public void test_isValid_happyPath() throws Exception {
         when(existingService.getId()).thenReturn(7L);
         when(store.getService(7L)).thenReturn(existingService);
         when(store.getServiceByName("aName")).thenReturn(existingService);
-        Assertions.assertTrue(validator.isValid(service, Action.UPDATE, failures));
+        assertTrue(validator.isValid(service, Action.UPDATE, failures));
         // name need not point to a service for update to work, of course.
         when(store.getServiceByName("aName")).thenReturn(null);
-        Assertions.assertTrue(validator.isValid(service, Action.UPDATE, failures));
+        assertTrue(validator.isValid(service, Action.UPDATE, failures));
     }
 
     @Test
     public void test_isValid_withId_errorConditions() throws Exception {
+        initialize();
         // api that takes in long is only supported for delete currently
-        Assertions.assertFalse(validator.isValid(1L, Action.CREATE, failures));
+        assertFalse(validator.isValid(1L, Action.CREATE, failures));
         utils.checkFailureForInternalError(failures);
         // passing in a null id is a failure!
         validator = new RangerServiceValidator(store);
         failures.clear();
-        Assertions.assertFalse(validator.isValid((Long) null, Action.DELETE, failures));
+        assertFalse(validator.isValid((Long) null, Action.DELETE, failures));
         utils.checkFailureForMissingValue(failures, "id");
         // if service with that id does not exist then that, is ok because delete is idempotent
         when(store.getService(1L)).thenReturn(null);
         when(store.getService(2L)).thenThrow(new Exception());
         failures.clear();
-        Assertions.assertTrue(validator.isValid(1L, Action.DELETE, failures));
-        Assertions.assertTrue(failures.isEmpty());
+        assertTrue(validator.isValid(1L, Action.DELETE, failures));
+        assertTrue(failures.isEmpty());
 
         failures.clear();
-        Assertions.assertTrue(validator.isValid(2L, Action.DELETE, failures));
-        Assertions.assertTrue(failures.isEmpty());
+        assertTrue(validator.isValid(2L, Action.DELETE, failures));
+        assertTrue(failures.isEmpty());
     }
 
     @Test
     public void test_isValid_withId_happyPath() throws Exception {
+        initialize();
         validator = new RangerServiceValidator(store);
         RangerService service = mock(RangerService.class);
         when(store.getService(1L)).thenReturn(service);
-        Assertions.assertTrue(validator.isValid(1L, Action.DELETE, failures));
+        assertTrue(validator.isValid(1L, Action.DELETE, failures));
     }
 
     void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field) {
@@ -537,7 +562,7 @@ void checkFailure_isValid(RangerServiceValidator validator, RangerService servic
 
     void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field, String subField) {
         failures.clear();
-        Assertions.assertFalse(validator.isValid(service, action, failures));
+        assertFalse(validator.isValid(service, action, failures));
         switch (errorType) {
             case "missing":
                 utils.checkFailureForMissingValue(failures, field, subField);
@@ -549,7 +574,7 @@ void checkFailure_isValid(RangerServiceValidator validator, RangerService servic
                 utils.checkFailureForInternalError(failures);
                 break;
             default:
-                Assertions.fail("Unsupported errorType[" + errorType + "]");
+                fail("Unsupported errorType[" + errorType + "]");
                 break;
         }
     }
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestValidationFailureDetails.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestValidationFailureDetails.java
new file mode 100644
index 000000000..376853fbf
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestValidationFailureDetails.java
@@ -0,0 +1,99 @@
+/*
+ * 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.plugin.model.validation;
+
+import org.apache.ranger.plugin.errors.ValidationErrorCode;
+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 for ValidationFailureDetails class>
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class TestValidationFailureDetails {
+    @Test
+    public void test01_equals_hashCode_builderVsCtor() {
+        ValidationFailureDetails a = new ValidationFailureDetailsBuilder().field("name").subField("sub").isMissing()
+                .errorCode(101).becauseOf("reason1").build();
+
+        ValidationFailureDetails b = new ValidationFailureDetails(101, "name", "sub", true, false, false, "reason1");
+
+        Assertions.assertEquals(a, b);
+        Assertions.assertEquals(a.hashCode(), b.hashCode());
+    }
+
+    @Test
+    public void test02_equals_differentFields() {
+        ValidationFailureDetails base = new ValidationFailureDetails(101, "f", "sf", true, false, false, "r");
+        ValidationFailureDetails diffError = new ValidationFailureDetails(102, "f", "sf", true, false, false, "r");
+        ValidationFailureDetails diffMissing = new ValidationFailureDetails(101, "f", "sf", false, false, false, "r");
+        ValidationFailureDetails diffSemantic = new ValidationFailureDetails(101, "f", "sf", true, true, false, "r");
+        ValidationFailureDetails diffInternal = new ValidationFailureDetails(101, "f", "sf", true, false, true, "r");
+        ValidationFailureDetails diffField = new ValidationFailureDetails(101, "f2", "sf", true, false, false, "r");
+        ValidationFailureDetails diffSub = new ValidationFailureDetails(101, "f", "sf2", true, false, false, "r");
+        ValidationFailureDetails diffReason = new ValidationFailureDetails(101, "f", "sf", true, false, false, "r2");
+
+        Assertions.assertNotEquals(base, diffError);
+        Assertions.assertNotEquals(base, diffMissing);
+        Assertions.assertNotEquals(base, diffSemantic);
+        Assertions.assertNotEquals(base, diffInternal);
+        Assertions.assertNotEquals(base, diffField);
+        Assertions.assertNotEquals(base, diffSub);
+        Assertions.assertNotEquals(base, diffReason);
+    }
+
+    @Test
+    public void test03_toString_includesType_missing() {
+        ValidationFailureDetails d = new ValidationFailureDetails(0, "f", "sf", true, false, false, "rr");
+        String s = d.toString();
+        Assertions.assertTrue(s.contains("type[missing]"));
+    }
+
+    @Test
+    public void test04_toString_includesType_semantic() {
+        ValidationFailureDetails d = new ValidationFailureDetails(0, "f", "sf", false, true, false, "rr");
+        String s = d.toString();
+        Assertions.assertTrue(s.contains("type[semantically incorrect]"));
+    }
+
+    @Test
+    public void test05_toString_includesType_internal() {
+        ValidationFailureDetails d = new ValidationFailureDetails(0, "f", "sf", false, false, true, "rr");
+        String s = d.toString();
+        Assertions.assertTrue(s.contains("type[internal error]"));
+    }
+
+    @Test
+    public void test06_ctor_fromErrorCode_messageFormatting() {
+        ValidationFailureDetails d = new ValidationFailureDetails(
+                ValidationErrorCode.ROLE_VALIDATION_ERR_INVALID_ROLE_ID, "id", 7L);
+        String s = d.toString();
+        Assertions.assertTrue(s.contains(
+                "error code[" + ValidationErrorCode.ROLE_VALIDATION_ERR_INVALID_ROLE_ID.getErrorCode() + "]"));
+        Assertions.assertTrue(s.contains("field[id]"));
+        Assertions.assertTrue(s.contains("reason["));
+    }
+}
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
index 8cb799578..ce08a96ba 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
@@ -31,6 +31,10 @@
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -41,6 +45,12 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+/**
+* @generated by Cursor
+* @description <Unit Test for ValidationTestUtils class>
+*/
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
 public class ValidationTestUtils {
     public Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] input) {
         if (input == null) {
@@ -52,14 +62,8 @@ public Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] inpu
             String[]             valuesArray  = (String[]) row[1];
             Boolean              isExcludes   = (Boolean) row[2];
             Boolean              isRecursive  = (Boolean) row[3];
-            RangerPolicyResource aResource    = mock(RangerPolicyResource.class);
-            if (valuesArray == null) {
-                when(aResource.getValues()).thenReturn(null);
-            } else {
-                when(aResource.getValues()).thenReturn(Arrays.asList(valuesArray));
-            }
-            when(aResource.getIsExcludes()).thenReturn(isExcludes);
-            when(aResource.getIsRecursive()).thenReturn(isRecursive);
+            List<String>         values       = valuesArray == null ? null : Arrays.asList(valuesArray);
+            RangerPolicyResource aResource    = new RangerPolicyResource(values, isExcludes, isRecursive);
             result.put(resourceName, aResource);
         }
         return result;
@@ -78,9 +82,9 @@ List<RangerServiceConfigDef> createServiceConditionDefs(Object[][] input) {
         List<RangerServiceConfigDef> result = new ArrayList<>();
 
         for (Object[] data : input) {
-            RangerServiceConfigDef aConfigDef = mock(RangerServiceConfigDef.class);
-            when(aConfigDef.getName()).thenReturn((String) data[0]);
-            when(aConfigDef.getMandatory()).thenReturn((boolean) data[1]);
+            RangerServiceConfigDef aConfigDef = new RangerServiceConfigDef();
+            aConfigDef.setName((String) data[0]);
+            aConfigDef.setMandatory((boolean) data[1]);
             result.add(aConfigDef);
         }
 
@@ -296,15 +300,15 @@ List<RangerResourceDef> createResourceDefs(Object[][] data) {
                     case 1:
                         name = (String) row[0];
                 }
-                aDef = mock(RangerResourceDef.class);
-                when(aDef.getName()).thenReturn(name);
-                when(aDef.getMandatory()).thenReturn(mandatory);
-                when(aDef.getValidationRegEx()).thenReturn(regExPattern);
-                when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
-                when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
-                when(aDef.getParent()).thenReturn(parent);
-                when(aDef.getLevel()).thenReturn(level);
-                when(aDef.getIsValidLeaf()).thenReturn(null);
+                aDef = new RangerResourceDef();
+                aDef.setName(name);
+                aDef.setMandatory(mandatory);
+                aDef.setValidationRegEx(regExPattern);
+                aDef.setExcludesSupported(isExcludesSupported);
+                aDef.setRecursiveSupported(isRecursiveSupported);
+                aDef.setParent(parent);
+                aDef.setLevel(level);
+                aDef.setIsValidLeaf(null);
             }
             defs.add(aDef);
         }
@@ -322,9 +326,9 @@ List<RangerResourceDef> createResourceDefsWithRegEx(String[][] data) {
             if (row != null) {
                 String name  = row[0];
                 String regEx = row[1];
-                aDef = mock(RangerResourceDef.class);
-                when(aDef.getName()).thenReturn(name);
-                when(aDef.getValidationRegEx()).thenReturn(regEx);
+                aDef = new RangerResourceDef();
+                aDef.setName(name);
+                aDef.setValidationRegEx(regEx);
             }
             defs.add(aDef);
         }
@@ -343,10 +347,10 @@ List<RangerResourceDef> createResourceDefsWithIds(Object[][] data) {
                 Long    itemId = (Long) row[0];
                 Integer level  = (Integer) row[1];
                 String  name   = (String) row[2];
-                aDef = mock(RangerResourceDef.class);
-                when(aDef.getName()).thenReturn(name);
-                when(aDef.getItemId()).thenReturn(itemId);
-                when(aDef.getLevel()).thenReturn(level);
+                aDef = new RangerResourceDef();
+                aDef.setName(name);
+                aDef.setItemId(itemId);
+                aDef.setLevel(level);
             }
             defs.add(aDef);
         }