diff --git a/plugin-ozone/pom.xml b/plugin-ozone/pom.xml
index 6794bf5f20a..732d9b5bb06 100644
--- a/plugin-ozone/pom.xml
+++ b/plugin-ozone/pom.xml
@@ -159,6 +159,12 @@ limitations under the License.
${junit.jupiter.version}
test
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
org.mockito
mockito-junit-jupiter
diff --git a/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java b/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java
index 1f365dd61be..d04b395842f 100644
--- a/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java
+++ b/plugin-ozone/src/test/java/org/apache/ranger/authorization/ozone/authorizer/TestRangerOzoneAuthorizer.java
@@ -29,11 +29,18 @@
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
import org.apache.ranger.plugin.model.RangerInlinePolicy;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
import org.apache.ranger.plugin.service.RangerBasePlugin;
import org.apache.ranger.plugin.util.JsonUtilsV2;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import java.lang.reflect.Field;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Collections;
@@ -47,8 +54,17 @@
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-public class TestRangerOzoneAuthorizer {
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerOzoneAuthorizer
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestRangerOzoneAuthorizer {
private static final String RANGER_SERVICE_TYPE = "ozone";
private static final String RANGER_APP_ID = "om";
private static final String OZONE_SERVICE_ID = "om";
@@ -62,10 +78,10 @@ public class TestRangerOzoneAuthorizer {
private final UserGroupInformation user2 = UserGroupInformation.createRemoteUser("user2");
private final String role1 = "role1";
- private final OzoneObj vol1 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.VOLUME).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol1").build();
- private final OzoneObj buck1 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.BUCKET).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol1").setBucketName("buck1").build();
- private final OzoneObj key1 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.KEY).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol1").setBucketName("buck1").setKeyName("key1").build();
- private final OzoneObj vol2 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.VOLUME).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol2").build();
+ private final OzoneObj vol1 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.VOLUME).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol1").build();
+ private final OzoneObj buck1 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.BUCKET).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol1").setBucketName("buck1").build();
+ private final OzoneObj key1 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.KEY).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol1").setBucketName("buck1").setKeyName("key1").build();
+ private final OzoneObj vol2 = new OzoneObjInfo.Builder().setResType(OzoneObj.ResourceType.VOLUME).setStoreType(OzoneObj.StoreType.OZONE).setVolumeName("vol2").build();
private final OzoneGrant grantList = new OzoneGrant(new HashSet<>(Arrays.asList(vol1, buck1)), Collections.singleton(IAccessAuthorizer.ACLType.LIST));
private final OzoneGrant grantRead = new OzoneGrant(Collections.singleton(key1), Collections.singleton(IAccessAuthorizer.ACLType.READ));
@@ -78,7 +94,7 @@ public class TestRangerOzoneAuthorizer {
.setOwnerName(OWNER_NAME);
@BeforeAll
- public static void setUpBeforeClass() {
+ static void setUpBeforeClass() {
RangerPluginConfig pluginConfig = new RangerPluginConfig(RANGER_SERVICE_TYPE, null, RANGER_APP_ID, null, null, null); // loads ranger-ozone-security.xml
RangerBasePlugin plugin = new RangerBasePlugin(pluginConfig);
@@ -91,7 +107,7 @@ public static void setUpBeforeClass() {
}
@Test
- public void testAssumeRoleDeny() {
+ void testAssumeRoleDeny() {
// user2 should not be allowed to assume role1 - no Ranger policy grants this permission
AssumeRoleRequest request = new AssumeRoleRequest(hostname, ipAddress, user2, role1, null);
@@ -99,7 +115,7 @@ public void testAssumeRoleDeny() {
}
@Test
- public void testAssumeRoleWithEmptyGrants() throws Exception {
+ void testAssumeRoleWithEmptyGrants() throws Exception {
Set grants = Collections.emptySet();
AssumeRoleRequest request = new AssumeRoleRequest(hostname, ipAddress, user1, role1, grants);
@@ -135,7 +151,7 @@ public void testAssumeRoleWithEmptyGrants() throws Exception {
}
@Test
- public void testAssumeRoleWithNullGrants() throws Exception {
+ void testAssumeRoleWithNullGrants() throws Exception {
Set grants = null;
AssumeRoleRequest request = new AssumeRoleRequest(hostname, ipAddress, user1, role1, grants);
@@ -171,7 +187,7 @@ public void testAssumeRoleWithNullGrants() throws Exception {
}
@Test
- public void testAssumeRoleWithGrants() throws Exception {
+ void testAssumeRoleWithGrants() throws Exception {
Set grants = new HashSet<>(Arrays.asList(grantList, grantRead));
AssumeRoleRequest request = new AssumeRoleRequest(hostname, ipAddress, user1, role1, grants);
@@ -201,4 +217,82 @@ public void testAssumeRoleWithGrants() throws Exception {
assertTrue(ozoneAuthorizer.checkAccess(buck1, ctxListWithSessionPolicy), "session-policy should allow list on bucket vol1/buck1");
assertTrue(ozoneAuthorizer.checkAccess(key1, ctxReadWithSessionPolicy), "session-policy should allow read on key vol1/buck1/key1");
}
+
+ @Test
+ void test05_checkAccess_whenPolicyAllows_returnsTrue() throws Exception {
+ RangerBasePlugin active = readRangerPluginField();
+
+ try {
+ RangerBasePlugin plugin = mock(RangerBasePlugin.class);
+ when(plugin.getClusterName()).thenReturn("test-cluster");
+
+ RangerAccessResult result = mock(RangerAccessResult.class);
+ when(result.getIsAllowed()).thenReturn(true);
+ when(plugin.isAccessAllowed(any(RangerAccessRequestImpl.class))).thenReturn(result);
+
+ RangerOzoneAuthorizer authorizer = new RangerOzoneAuthorizer(plugin);
+ RequestContext context = reqCtxBuilder.setAclRights(IAccessAuthorizer.ACLType.READ).build();
+
+ assertTrue(authorizer.checkAccess(key1, context));
+ } finally {
+ writeRangerPluginField(active);
+ }
+ }
+
+ @Test
+ void test06_checkAccess_whenPrefixResource_returnsFalse() throws Exception {
+ RangerBasePlugin active = readRangerPluginField();
+
+ try {
+ RangerBasePlugin plugin = mock(RangerBasePlugin.class);
+ when(plugin.getClusterName()).thenReturn("test-cluster");
+
+ RangerOzoneAuthorizer authorizer = new RangerOzoneAuthorizer(plugin);
+ OzoneObj prefix = new OzoneObjInfo.Builder()
+ .setResType(OzoneObj.ResourceType.PREFIX)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .setVolumeName("vol1")
+ .setBucketName("buck1")
+ .setPrefixName("pre")
+ .build();
+ RequestContext context = reqCtxBuilder.setAclRights(IAccessAuthorizer.ACLType.READ).build();
+
+ assertFalse(authorizer.checkAccess(prefix, context));
+ } finally {
+ writeRangerPluginField(active);
+ }
+ }
+
+ @Test
+ void test07_generateAssumeRoleSessionPolicy_whenTargetRoleNameNull_throwsOmException() {
+ AssumeRoleRequest request = new AssumeRoleRequest(hostname, ipAddress, user1, null, null);
+
+ assertThrows(OMException.class, () -> ozoneAuthorizer.generateAssumeRoleSessionPolicy(request));
+ }
+
+ @Test
+ void test08_generateAssumeRoleSessionPolicy_whenPluginUninitialized_throwsOmException() throws Exception {
+ RangerBasePlugin active = readRangerPluginField();
+
+ try {
+ writeRangerPluginField(null);
+ AssumeRoleRequest request = new AssumeRoleRequest(hostname, ipAddress, user1, role1, null);
+
+ assertThrows(OMException.class, () -> ozoneAuthorizer.generateAssumeRoleSessionPolicy(request));
+ } finally {
+ writeRangerPluginField(active);
+ }
+ }
+
+ private static RangerBasePlugin readRangerPluginField() throws Exception {
+ Field field = RangerOzoneAuthorizer.class.getDeclaredField("rangerPlugin");
+ field.setAccessible(true);
+ return (RangerBasePlugin) field.get(null);
+ }
+
+ private static void writeRangerPluginField(RangerBasePlugin plugin) throws Exception {
+ Field field = RangerOzoneAuthorizer.class.getDeclaredField("rangerPlugin");
+ field.setAccessible(true);
+ field.set(null, plugin);
+ }
}
diff --git a/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/TestRangerServiceOzone.java b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/TestRangerServiceOzone.java
new file mode 100644
index 00000000000..930b9064345
--- /dev/null
+++ b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/TestRangerServiceOzone.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.services.ozone;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.service.RangerBaseService;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
+import org.apache.ranger.services.ozone.client.OzoneResourceMgr;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Field;
+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;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyMap;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerServiceOzone
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestRangerServiceOzone {
+ private static final String CREATE_DEFAULT_POLICY_PER_HIERARCHY = "create.default.policy.per.hierarchy";
+
+ @Test
+ void test01_init_whenServiceProvided_setsIdentifiers() throws Exception {
+ RangerServiceOzone ozone = new RangerServiceOzone();
+ RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+
+ assertNotNull(def);
+
+ Map cfg = sampleServiceConfigs();
+ RangerService service = buildService("svc-ozone", "ozone", cfg);
+
+ ozone.init(def, service);
+
+ assertEquals(def, ozone.getServiceDef());
+ assertEquals(service, ozone.getService());
+ assertEquals(cfg, ozone.getConfigs());
+ assertEquals("svc-ozone", ozone.getServiceName());
+ assertEquals("ozone", ozone.getServiceType());
+ }
+
+ @Test
+ void test02_init_whenServiceIsNull_throwsNullPointerException() throws Exception {
+ RangerServiceOzone ozone = new RangerServiceOzone();
+ RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+
+ assertNotNull(def);
+ assertThrows(NullPointerException.class, () -> ozone.init(def, null));
+ }
+
+ @Test
+ void test03_validateConfig_whenConfigsAbsent_returnsEmptyResponse() throws Exception {
+ RangerServiceOzone ozone = initOzone(sampleServiceConfigs());
+ ozone.setConfigs(null);
+
+ Map out = ozone.validateConfig();
+
+ assertNotNull(out);
+ assertTrue(out.isEmpty());
+ }
+
+ @Test
+ void test04_validateConfig_whenConfigsAvailable_delegatesToOzoneResourceMgr() throws Exception {
+ RangerServiceOzone ozone = initOzone(sampleServiceConfigs());
+ Map expected = Collections.singletonMap("connectivityStatus", Boolean.TRUE);
+
+ try (MockedStatic mocked = mockStatic(OzoneResourceMgr.class)) {
+ mocked.when(() -> OzoneResourceMgr.connectionTest(eq("ozone-svc"), anyMap())).thenReturn(expected);
+
+ Map actual = ozone.validateConfig();
+
+ assertSame(expected, actual);
+ mocked.verify(() -> OzoneResourceMgr.connectionTest(eq("ozone-svc"), anyMap()));
+ }
+ }
+
+ @Test
+ void test05_lookupResource_whenContextIsNull_returnsEmptyList() throws Exception {
+ RangerServiceOzone ozone = initOzoneForLookup(sampleServiceConfigs());
+
+ try (MockedStatic mocked = mockStatic(OzoneResourceMgr.class)) {
+ List result = ozone.lookupResource(null);
+
+ assertEquals(Collections.emptyList(), result);
+
+ mocked.verify(() -> OzoneResourceMgr.getOzoneResources(anyString(), anyString(), anyMap(), any()),
+ never());
+ }
+ }
+
+ @Test
+ void test06_lookupResource_whenContextPresent_delegatesToOzoneResourceMgr() throws Exception {
+ RangerServiceOzone ozone = initOzoneForLookup(sampleServiceConfigs());
+ ResourceLookupContext ctx = sampleLookupContext();
+ List expected = Arrays.asList("/a", "/b");
+
+ try (MockedStatic mocked = mockStatic(OzoneResourceMgr.class)) {
+ mocked.when(() -> OzoneResourceMgr.getOzoneResources(eq("svc-lookup"), eq("ozone"), anyMap(), same(ctx))).thenReturn(expected);
+
+ List result = ozone.lookupResource(ctx);
+
+ assertSame(expected, result);
+ }
+ }
+
+ @Test
+ void test07_getDefaultRangerPolicies_addsOwnerGrantForPoliciesNamedAll() throws Exception {
+ RangerServiceOzone ozone = new RangerServiceOzone();
+ RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+
+ ozone.init(def, buildService("def-svc", "ozone", defaultPolicyConfigs()));
+
+ List policies = ozone.getDefaultRangerPolicies();
+
+ assertFalse(policies.isEmpty());
+
+ boolean foundExtended = policies.stream().anyMatch(p ->
+ p.getName() != null
+ && p.getName().startsWith("all")
+ && p.getPolicyItems().stream().anyMatch(pi ->
+ pi.getUsers() != null && pi.getUsers().contains(RangerPolicyEngine.RESOURCE_OWNER)));
+
+ assertTrue(foundExtended);
+ }
+
+ @Test
+ void test08_getDefaultRangerPolicies_whenLookupUserPresent_addsDedicatedPolicyItems() throws Exception {
+ RangerServiceOzone ozone = new RangerServiceOzone();
+
+ Field lookUpField = RangerBaseService.class.getDeclaredField("lookUpUser");
+ lookUpField.setAccessible(true);
+ lookUpField.set(ozone, "resolver-user");
+
+ RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+ ozone.init(def, buildService("def-svc-2", "ozone", defaultPolicyConfigs()));
+
+ List policies = ozone.getDefaultRangerPolicies();
+
+ Set allPolicyNames = new HashSet<>();
+ for (RangerPolicy p : policies) {
+ if (p.getName() != null && p.getName().startsWith("all")) {
+ boolean hasLookup = p.getPolicyItems().stream().anyMatch(pi ->
+ pi.getUsers() != null && pi.getUsers().contains("resolver-user"));
+ assertTrue(hasLookup, "expected lookup user grants on policy " + p.getName());
+ allPolicyNames.add(p.getName());
+ }
+ }
+
+ assertFalse(allPolicyNames.isEmpty());
+ }
+
+ private RangerServiceOzone initOzone(Map cfg) throws Exception {
+ RangerServiceOzone svc = new RangerServiceOzone();
+
+ RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+ assertNotNull(def);
+
+ svc.init(def, buildService("ozone-svc", "ozone", cfg));
+ return svc;
+ }
+
+ private RangerServiceOzone initOzoneForLookup(Map cfg) throws Exception {
+ RangerServiceOzone svc = new RangerServiceOzone();
+
+ RangerServiceDef def = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_OZONE_NAME);
+ assertNotNull(def);
+
+ svc.init(def, buildService("svc-lookup", "ozone", cfg));
+ return svc;
+ }
+
+ private RangerService buildService(String name, String type, Map cfg) {
+ RangerService service = new RangerService();
+ service.setName(name);
+ service.setType(type);
+ service.setConfigs(cfg);
+ return service;
+ }
+
+ private Map sampleServiceConfigs() {
+ Map cfg = new HashMap<>();
+ cfg.put("username", "u");
+ cfg.put("password", "p");
+ cfg.put("ozone.om.http-address", "localhost:9862");
+ return cfg;
+ }
+
+ private ResourceLookupContext sampleLookupContext() {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("volume-a");
+ ctx.setResourceName("volume");
+ return ctx;
+ }
+
+ private Map defaultPolicyConfigs() {
+ Map cfg = sampleServiceConfigs();
+ cfg.put("setup.additional.default.policies", "false");
+ cfg.put(CREATE_DEFAULT_POLICY_PER_HIERARCHY, Boolean.TRUE.toString());
+ return cfg;
+ }
+}
diff --git a/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneClient.java b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneClient.java
new file mode 100644
index 00000000000..cdbbce234c0
--- /dev/null
+++ b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneClient.java
@@ -0,0 +1,565 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.services.ozone.client;
+
+import org.apache.hadoop.hdds.conf.ConfigurationSource;
+import org.apache.hadoop.ozone.client.ObjectStore;
+import org.apache.hadoop.ozone.client.OzoneBucket;
+import org.apache.hadoop.ozone.client.OzoneClientFactory;
+import org.apache.hadoop.ozone.client.OzoneKey;
+import org.apache.hadoop.ozone.client.OzoneVolume;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.security.auth.Subject;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for OzoneClient
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestOzoneClient {
+ @Test
+ void test01_close_whenHadoopClientCloseThrows_swallowsIOException() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ doThrow(new IOException("close-fail")).when(hdc).close();
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+ rangerClient.close();
+
+ verify(hdc).close();
+ }
+ }
+
+ @Test
+ void test02_connectionTest_whenVolumesEmpty_returnsFailureMap() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.listVolumes(eq(""))).thenReturn(Collections.emptyIterator());
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ Map out = OzoneClient.connectionTest("svc", minimalConnectionProperties());
+
+ assertEquals(Boolean.FALSE, out.get("connectivityStatus"));
+ verify(hdc).close();
+ }
+ }
+
+ @Test
+ void test03_connectionTest_whenVolumesPresent_returnsSuccessMap() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+
+ OzoneVolume vol = mock(OzoneVolume.class);
+ when(vol.getName()).thenReturn("vol-a");
+ List singleVol = Collections.singletonList(vol);
+ when(objectStore.listVolumes(eq(""))).thenAnswer(invocation -> singleVol.iterator());
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ Map out = OzoneClient.connectionTest("svc", minimalConnectionProperties());
+
+ assertEquals(Boolean.TRUE, out.get("connectivityStatus"));
+ verify(hdc).close();
+ }
+ }
+
+ @Test
+ void test04_connectionTest_whenListVolumesIteratorNull_handlesGracefully() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.listVolumes(eq(""))).thenReturn(null);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ Map out = OzoneClient.connectionTest("svc", minimalConnectionProperties());
+
+ assertEquals(Boolean.FALSE, out.get("connectivityStatus"));
+ }
+ }
+
+ @Test
+ void test05_constructor_skipsEntriesWithNullValues() throws Exception {
+ Map props = minimalConnectionProperties();
+ props.put("ignored.null.value", null);
+
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", props);
+ assertNotNull(rangerClient);
+ rangerClient.close();
+ }
+ }
+
+ @Test
+ void test06_getBucketList_whenBucketsPresent_returnsNames() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume ozoneVolume = mock(OzoneVolume.class);
+ OzoneBucket b1 = mock(OzoneBucket.class);
+
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(eq("v1"))).thenReturn(ozoneVolume);
+
+ when(b1.getName()).thenReturn("buck-a");
+ List buckets = new ArrayList<>();
+ buckets.add(b1);
+
+ when(ozoneVolume.listBuckets(eq("pre"))).thenAnswer(invocation -> buckets.iterator());
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+ List names = rangerClient.getBucketList("pre", Collections.singletonList("v1"));
+
+ assertEquals(Collections.singletonList("buck-a"), names);
+ }
+ }
+
+ @Test
+ void test07_getBucketList_whenIteratorNull_returnsEmpty() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume ozoneVolume = mock(OzoneVolume.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(eq("v1"))).thenReturn(ozoneVolume);
+ when(ozoneVolume.listBuckets(eq("pre"))).thenReturn(null);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getBucketList("pre", Collections.singletonList("v1")).isEmpty());
+ }
+ }
+
+ @Test
+ void test08_getBucketList_whenListVolumesThrowsIOException_returnsEmptyAndLogs() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(anyString())).thenThrow(new IOException("no-volume"));
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getBucketList("bp", Collections.singletonList("v1")).isEmpty());
+ }
+ }
+
+ @Test
+ void test09_getBucketList_whenVolumeListNull_skipsReads() throws Exception {
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getBucketList("bp", null).isEmpty());
+ assertTrue(rangerClient.getBucketList("bp", Collections.emptyList()).isEmpty());
+
+ verify(hdc, never()).getObjectStore();
+ }
+ }
+
+ @Test
+ void test10_getKeyList_whenKeysPresent_returnsNames() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume ozoneVolume = mock(OzoneVolume.class);
+ OzoneBucket bucket = mock(OzoneBucket.class);
+ OzoneKey ozoneKey = mock(OzoneKey.class);
+
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(eq("v1"))).thenReturn(ozoneVolume);
+
+ when(bucket.getName()).thenReturn("b-target");
+ when(ozoneKey.getName()).thenReturn("key-1");
+
+ when(bucket.listKeys(eq("kp")))
+ .thenAnswer(invocation -> Collections.singletonList(ozoneKey).iterator());
+
+ when(ozoneVolume.listBuckets(isNull()))
+ .thenAnswer(invocation -> Collections.singletonList(bucket).iterator());
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ List names = rangerClient.getKeyList("kp", Collections.singletonList("v1"), Collections.singletonList("b-target"));
+
+ assertEquals(Collections.singletonList("key-1"), names);
+ }
+ }
+
+ @Test
+ void test11_getKeyList_whenBucketNotListed_skipsKeys() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume ozoneVolume = mock(OzoneVolume.class);
+ OzoneBucket other = mock(OzoneBucket.class);
+
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(eq("v1"))).thenReturn(ozoneVolume);
+ when(other.getName()).thenReturn("other-bucket");
+ when(ozoneVolume.listBuckets(isNull())).thenAnswer(invocation -> Collections.singletonList(other).iterator());
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getKeyList("kp", Collections.singletonList("v1"),
+ Collections.singletonList("wanted-bucket")).isEmpty());
+
+ verify(other, never()).listKeys(anyString());
+ }
+ }
+
+ @Test
+ void test12_getKeyList_whenBucketIteratorNull_returnsEmpty() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume ozoneVolume = mock(OzoneVolume.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(anyString())).thenReturn(ozoneVolume);
+ when(ozoneVolume.listBuckets(isNull())).thenReturn(null);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getKeyList("kp", Collections.singletonList("v1"),
+ Collections.singletonList("b")).isEmpty());
+ }
+ }
+
+ @Test
+ void test13_getVolumeList_whenHadoopThrowsIOException_returnsEmpty() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.listVolumes(eq("pfx"))).thenThrow(new IOException("no-list"));
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getVolumeList("pfx").isEmpty());
+ }
+ }
+
+ @Test
+ void test14_getVolumeList_whenInnerClientNull_returnsEmptyAfterClear() throws Exception {
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+ Field inner = OzoneClient.class.getDeclaredField("ozoneClient");
+ inner.setAccessible(true);
+ inner.set(rangerClient, null);
+
+ assertTrue(rangerClient.getVolumeList("pfx").isEmpty());
+ }
+ }
+
+ @Test
+ void test15_getVolumeList_whenVolumesPresent_collectsNames() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume vol = mock(OzoneVolume.class);
+ when(vol.getName()).thenReturn("v-a");
+ when(objectStore.listVolumes(eq("vp"))).thenAnswer(invocation -> Collections.singletonList(vol).iterator());
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertEquals(Collections.singletonList("v-a"), rangerClient.getVolumeList("vp"));
+ }
+ }
+
+ @Test
+ void test16_getVolumeList_whenVolumeIteratorNull_returnsEmpty() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.listVolumes(eq("pfx"))).thenReturn(null);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getVolumeList("pfx").isEmpty());
+ }
+ }
+
+ @Test
+ void test17_getKeyList_whenBucketListNull_throwsNullPointer() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume ozoneVolume = mock(OzoneVolume.class);
+ OzoneBucket bucket = mock(OzoneBucket.class);
+
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(eq("v1"))).thenReturn(ozoneVolume);
+ when(bucket.getName()).thenReturn("b-any");
+ when(ozoneVolume.listBuckets(isNull())).thenAnswer(invocation -> Collections.singletonList(bucket).iterator());
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertThrows(NullPointerException.class, () -> rangerClient.getKeyList("kp", Collections.singletonList("v1"), null));
+ }
+ }
+
+ @Test
+ void test18_getKeyList_whenKeyIteratorNull_skipsKeys() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume ozoneVolume = mock(OzoneVolume.class);
+ OzoneBucket bucket = mock(OzoneBucket.class);
+
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+ when(objectStore.getVolume(eq("v1"))).thenReturn(ozoneVolume);
+ when(bucket.getName()).thenReturn("b1");
+ when(bucket.listKeys(eq("kp"))).thenReturn(null);
+ when(ozoneVolume.listBuckets(isNull())).thenAnswer(invocation -> Collections.singletonList(bucket).iterator());
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getKeyList("kp", Collections.singletonList("v1"),
+ Collections.singletonList("b1")).isEmpty());
+ }
+ }
+
+ @Test
+ void test19_getVolumeList_whenMultipleVolumes_appendsAll() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+ ObjectStore objectStore = mock(ObjectStore.class);
+ OzoneVolume v1 = mock(OzoneVolume.class);
+ OzoneVolume v2 = mock(OzoneVolume.class);
+ when(v1.getName()).thenReturn("va");
+ when(v2.getName()).thenReturn("vb");
+ List both = Arrays.asList(v1, v2);
+ when(objectStore.listVolumes(eq("pref"))).thenAnswer(invocation -> both.iterator());
+ when(hdc.getObjectStore()).thenReturn(objectStore);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertEquals(Arrays.asList("va", "vb"), rangerClient.getVolumeList("pref"));
+ }
+ }
+
+ @Test
+ void test20_connectionTest_whenGetVolumeListReturnsNull_reportsDisconnected() throws Exception {
+ Map cfg = minimalConnectionProperties();
+
+ try (MockedConstruction cons = mockConstruction(OzoneClient.class,
+ (mock, context) -> when(mock.getVolumeList(eq(""))).thenReturn(null))) {
+ Map out = OzoneClient.connectionTest("svc", cfg);
+
+ assertEquals(Boolean.FALSE, out.get("connectivityStatus"));
+
+ assertEquals(1, cons.constructed().size());
+ verify(cons.constructed().get(0)).close();
+ }
+ }
+
+ @Test
+ void test21_getBucketList_whenInnerClientNull_returnsEmpty() throws Exception {
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+ Field inner = OzoneClient.class.getDeclaredField("ozoneClient");
+ inner.setAccessible(true);
+ inner.set(rangerClient, null);
+
+ assertTrue(rangerClient.getBucketList("pre", Collections.singletonList("v1")).isEmpty());
+ }
+ }
+
+ @Test
+ void test22_getKeyList_whenInnerClientNull_returnsEmpty() throws Exception {
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+ Field inner = OzoneClient.class.getDeclaredField("ozoneClient");
+ inner.setAccessible(true);
+ inner.set(rangerClient, null);
+
+ assertTrue(rangerClient.getKeyList("kp", Collections.singletonList("v1"),
+ Collections.singletonList("b")).isEmpty());
+ }
+ }
+
+ @Test
+ void test23_getKeyList_whenVolumeListEmpty_skipsStoreAccess() throws Exception {
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+
+ try (MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ stubSubjectExecutesExceptionAction(subjectStatic);
+ stubFactoryReturns(factoryStatic, hdc);
+
+ OzoneClient rangerClient = new OzoneClient("svc", minimalConnectionProperties());
+
+ assertTrue(rangerClient.getKeyList("kp", Collections.emptyList(),
+ Collections.singletonList("b")).isEmpty());
+
+ verify(hdc, never()).getObjectStore();
+ }
+ }
+
+ private static Map minimalConnectionProperties() {
+ Map cfg = new HashMap<>();
+ cfg.put("username", "u");
+ cfg.put("password", "p");
+ cfg.put("hadoop.security.authentication", "simple");
+ cfg.put("ozone.om.service.ids", "ozone1");
+ return cfg;
+ }
+
+ private static void stubSubjectExecutesExceptionAction(MockedStatic subjectStatic) {
+ subjectStatic.when(() -> Subject.doAs(any(Subject.class), any(PrivilegedExceptionAction.class)))
+ .thenAnswer(invocation -> {
+ PrivilegedExceptionAction> pea = invocation.getArgument(1);
+ return pea.run();
+ });
+ }
+
+ private static void stubFactoryReturns(MockedStatic factoryStatic,
+ org.apache.hadoop.ozone.client.OzoneClient hadoopClient) {
+ factoryStatic.when(() -> OzoneClientFactory.getRpcClient(anyString(), any(ConfigurationSource.class))).thenReturn(hadoopClient);
+ }
+}
diff --git a/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneConnectionMgr.java b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneConnectionMgr.java
new file mode 100644
index 00000000000..a71ae908974
--- /dev/null
+++ b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneConnectionMgr.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.services.ozone.client;
+
+import org.apache.hadoop.hdds.conf.ConfigurationSource;
+import org.apache.hadoop.ozone.client.OzoneClientFactory;
+import org.apache.ranger.plugin.util.TimedEventUtil;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.security.auth.Subject;
+
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for OzoneConnectionMgr
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestOzoneConnectionMgr {
+ /**
+ * Extends manager to expose protected cache fields for assertions.
+ */
+ private static final class OzoneConnectionMgrHarness extends OzoneConnectionMgr {
+ }
+
+ @Test
+ void test01_getOzoneConnection_whenServiceTypeNull_returnsNull() {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ Map config = new HashMap<>();
+ config.put("k", "v");
+
+ assertNull(mgr.getOzoneConnection("svc", null, config));
+ }
+
+ @Test
+ void test02_getOzoneConnection_whenTimedTaskReturnsClient_cachesConnection() throws Exception {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ OzoneClient freshClient = mock(OzoneClient.class);
+ Map config = new HashMap<>();
+ config.put("ozone.om.service.ids", "ozone1");
+
+ try (MockedStatic timed = mockStatic(TimedEventUtil.class)) {
+ timed.when(() -> TimedEventUtil.timedTask(any(Callable.class), eq(5L), eq(TimeUnit.SECONDS))).thenReturn(freshClient);
+
+ OzoneClient result = mgr.getOzoneConnection("new-svc", "ozone", config);
+
+ assertSame(freshClient, result);
+ assertSame(freshClient, mgr.ozoneConnectionCache.get("new-svc"));
+ assertEquals(Boolean.TRUE, mgr.repoConnectStatusMap.get("new-svc"));
+ }
+ }
+
+ @Test
+ void test03_getOzoneConnection_whenConfigsNullOnMiss_logsAndReturnsNull() {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+
+ assertNull(mgr.getOzoneConnection("svc", "ozone", null));
+ assertTrue(mgr.ozoneConnectionCache.isEmpty());
+ }
+
+ @Test
+ void test04_getOzoneConnection_whenTimedTaskThrows_returnsNull() throws Exception {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ Map config = minimalConfig();
+
+ try (MockedStatic timed = mockStatic(TimedEventUtil.class)) {
+ timed.when(() -> TimedEventUtil.timedTask(any(Callable.class), eq(5L), eq(TimeUnit.SECONDS)))
+ .thenThrow(new IllegalStateException("connect-fail"));
+
+ assertNull(mgr.getOzoneConnection("boom", "ozone", config));
+ assertEquals(Boolean.TRUE, mgr.repoConnectStatusMap.get("boom"));
+ }
+ }
+
+ @Test
+ void test05_getOzoneConnection_whenPutIfAbsentReturnsExisting_closesNewborn() throws Exception {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ OzoneClient winner = mock(OzoneClient.class);
+ OzoneClient loser = mock(OzoneClient.class);
+ Map config = minimalConfig();
+
+ try (MockedStatic timed = mockStatic(TimedEventUtil.class)) {
+ timed.when(() -> TimedEventUtil.timedTask(any(Callable.class), eq(5L), eq(TimeUnit.SECONDS)))
+ .thenAnswer(invocation -> {
+ mgr.ozoneConnectionCache.put("svc", winner);
+ return loser;
+ });
+
+ OzoneClient result = mgr.getOzoneConnection("svc", "ozone", config);
+
+ assertSame(winner, result);
+ verify(loser).close();
+ verify(winner, never()).close();
+ assertEquals(Boolean.TRUE, mgr.repoConnectStatusMap.get("svc"));
+ }
+ }
+
+ @Test
+ void test06_getOzoneConnection_whenCachedPingFails_reloadsConnection() throws Exception {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ Map config = minimalConfig();
+ OzoneClient stale = mock(OzoneClient.class);
+ OzoneClient fresh = mock(OzoneClient.class);
+
+ when(stale.getVolumeList(isNull())).thenThrow(new IllegalStateException("stale-connection"));
+
+ mgr.ozoneConnectionCache.put("rec", stale);
+
+ try (MockedStatic timed = mockStatic(TimedEventUtil.class)) {
+ timed.when(() -> TimedEventUtil.timedTask(any(Callable.class), eq(5L), eq(TimeUnit.SECONDS))).thenReturn(fresh);
+
+ OzoneClient result = mgr.getOzoneConnection("rec", "ozone", config);
+
+ assertSame(fresh, result);
+ verify(stale).close();
+ verify(stale).getVolumeList(null);
+ assertSame(fresh, mgr.ozoneConnectionCache.get("rec"));
+ }
+ }
+
+ @Test
+ void test07_getOzoneConnection_whenCacheHitHealthy_returnsExistingClient() throws Exception {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ Map config = minimalConfig();
+ OzoneClient cached = mock(OzoneClient.class);
+
+ when(cached.getVolumeList(isNull())).thenReturn(Collections.emptyList());
+ mgr.ozoneConnectionCache.put("reuse", cached);
+
+ OzoneClient result = mgr.getOzoneConnection("reuse", "ozone", config);
+
+ assertSame(cached, result);
+ verify(cached).getVolumeList(null);
+ }
+
+ @Test
+ void test08_getOzoneConnection_whenCallableBuildsClient_invokesOzoneClientConstructor() throws Exception {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ Map config = minimalConfig();
+
+ org.apache.hadoop.ozone.client.OzoneClient hdc = mock(org.apache.hadoop.ozone.client.OzoneClient.class);
+
+ try (MockedStatic timed = mockStatic(TimedEventUtil.class);
+ MockedStatic subjectStatic = mockStatic(Subject.class);
+ MockedStatic factoryStatic = mockStatic(OzoneClientFactory.class)) {
+ subjectStatic.when(() -> Subject.doAs(any(Subject.class), any(PrivilegedExceptionAction.class)))
+ .thenAnswer(invocation -> {
+ PrivilegedExceptionAction> pea = invocation.getArgument(1);
+ return pea.run();
+ });
+ factoryStatic.when(() -> OzoneClientFactory.getRpcClient(anyString(), any(ConfigurationSource.class))).thenReturn(hdc);
+
+ timed.when(() -> TimedEventUtil.timedTask(any(Callable.class), eq(5L), eq(TimeUnit.SECONDS)))
+ .thenAnswer(invocation -> {
+ @SuppressWarnings("unchecked")
+ Callable callable = invocation.getArgument(0);
+ return callable.call();
+ });
+
+ OzoneClient result = mgr.getOzoneConnection("live", "ozone", config);
+
+ assertNotNull(result);
+ assertSame(result, mgr.ozoneConnectionCache.get("live"));
+ factoryStatic.verify(() -> OzoneClientFactory.getRpcClient(anyString(), any(ConfigurationSource.class)));
+ }
+ }
+
+ @Test
+ void test09_getOzoneConnection_whenTimedTaskReturnsNull_butCacheFilled_usesWinner() throws Exception {
+ OzoneConnectionMgrHarness mgr = new OzoneConnectionMgrHarness();
+ OzoneClient winner = mock(OzoneClient.class);
+ Map config = minimalConfig();
+
+ try (MockedStatic timed = mockStatic(TimedEventUtil.class)) {
+ timed.when(() -> TimedEventUtil.timedTask(any(Callable.class), eq(5L), eq(TimeUnit.SECONDS))).thenAnswer(
+ invocation -> {
+ mgr.ozoneConnectionCache.put("svc", winner);
+ return null;
+ });
+
+ OzoneClient result = mgr.getOzoneConnection("svc", "ozone", config);
+
+ assertSame(winner, result);
+ verify(winner, never()).close();
+ assertSame(winner, mgr.ozoneConnectionCache.get("svc"));
+ assertEquals(Boolean.TRUE, mgr.repoConnectStatusMap.get("svc"));
+ }
+ }
+
+ private static Map minimalConfig() {
+ Map cfg = new HashMap<>();
+ cfg.put("username", "u");
+ cfg.put("password", "p");
+ cfg.put("hadoop.security.authentication", "simple");
+ cfg.put("ozone.om.service.ids", "ozone1");
+ return cfg;
+ }
+}
diff --git a/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneResourceMgr.java b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneResourceMgr.java
new file mode 100644
index 00000000000..ce58fdec8bf
--- /dev/null
+++ b/plugin-ozone/src/test/java/org/apache/ranger/services/ozone/client/TestOzoneResourceMgr.java
@@ -0,0 +1,420 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.services.ozone.client;
+
+import org.apache.ranger.plugin.client.HadoopException;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.apache.ranger.plugin.util.TimedEventUtil;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for OzoneResourceMgr
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestOzoneResourceMgr {
+ @Test
+ void test01_connectionTest_whenOzoneClientOk_returnsMap() throws Exception {
+ Map cfg = new HashMap<>();
+ cfg.put("ozone.om.service.ids", "ozone1");
+ Map expected = Collections.singletonMap("connectivityStatus", Boolean.TRUE);
+
+ try (MockedStatic mocked = Mockito.mockStatic(OzoneClient.class)) {
+ mocked.when(() -> OzoneClient.connectionTest(Mockito.eq("svc"), Mockito.eq(cfg))).thenReturn(expected);
+
+ Map result = OzoneResourceMgr.connectionTest("svc", cfg);
+
+ assertSame(expected, result);
+ mocked.verify(() -> OzoneClient.connectionTest(Mockito.eq("svc"), Mockito.eq(cfg)));
+ }
+ }
+
+ @Test
+ void test02_connectionTest_whenOzoneClientThrowsPropagatesHadoopException() {
+ Map cfg = new HashMap<>();
+ HadoopException hadoopFail = new HadoopException("boom", new RuntimeException("root"));
+
+ try (MockedStatic mocked = Mockito.mockStatic(OzoneClient.class)) {
+ mocked.when(() -> OzoneClient.connectionTest(Mockito.eq("svc"), Mockito.eq(cfg))).thenThrow(hadoopFail);
+
+ assertThrows(HadoopException.class, () -> OzoneResourceMgr.connectionTest("svc", cfg));
+ }
+ }
+
+ @Test
+ void test03_connectionTest_whenUncheckedException_propagates() {
+ Map cfg = new HashMap<>();
+ cfg.put("k", "v");
+ IllegalStateException fail = new IllegalStateException("not-hadoop");
+
+ try (MockedStatic mocked = Mockito.mockStatic(OzoneClient.class)) {
+ mocked.when(() -> OzoneClient.connectionTest(Mockito.eq("svc"), Mockito.eq(cfg))).thenThrow(fail);
+
+ assertThrows(IllegalStateException.class, () -> OzoneResourceMgr.connectionTest("svc", cfg));
+ }
+ }
+
+ @Test
+ void test04_getOzoneResources_whenBucketPrefix_resolvesViaTimedTask() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("bpre");
+ ctx.setResourceName("bucket");
+ ctx.setResources(Collections.singletonMap("volume", Collections.singletonList("v1")));
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+ List want = Arrays.asList("b-a", "b-b");
+ Mockito.when(client.getBucketList(Mockito.eq("bpre"), Mockito.eq(Collections.singletonList("v1")))).thenReturn(want);
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS))).then(inv -> {
+ @SuppressWarnings("unchecked")
+ Callable> callable = inv.getArgument(0);
+
+ return callable.call();
+ });
+
+ assertEquals(want, OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test05_getOzoneResources_whenKeyPrefix_resolvesViaTimedTask() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("kpre");
+ ctx.setResourceName("key");
+
+ Map> res = new HashMap<>();
+ res.put("volume", Collections.singletonList("v1"));
+ res.put("bucket", Collections.singletonList("b1"));
+ ctx.setResources(res);
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+ Mockito.when(client.getKeyList(Mockito.eq("kpre"), Mockito.eq(Collections.singletonList("v1")),
+ Mockito.eq(Collections.singletonList("b1")))).thenReturn(Collections.singletonList("k1"));
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS))).then(inv -> {
+ @SuppressWarnings("unchecked")
+ Callable> callable = inv.getArgument(0);
+
+ return callable.call();
+ });
+
+ assertEquals(Collections.singletonList("k1"), OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test06_getOzoneResources_whenResourceUnknown_doesNotScheduleCallable() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("x");
+ ctx.setResourceName("unknown");
+
+ Map cfg = new HashMap<>();
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.anyString(), Mockito.anyString(), Mockito.anyMap()))
+ .thenReturn(Mockito.mock(OzoneClient.class)))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.anyLong(), Mockito.any(TimeUnit.class)))
+ .thenThrow(new AssertionError("timedTask should not run"));
+
+ assertNull(OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test07_getOzoneResources_whenResourceNameTrimmedNormalizesCase() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("vp");
+ ctx.setResourceName(" VOLUME ");
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+ Mockito.when(client.getVolumeList(Mockito.eq("vp"))).thenReturn(Collections.singletonList("only"));
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS))).then(inv -> {
+ @SuppressWarnings("unchecked")
+ Callable> callable = inv.getArgument(0);
+
+ return callable.call();
+ });
+
+ assertEquals(Collections.singletonList("only"), OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test08_getOzoneResources_whenServiceNameNull_returnsNull() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("vol");
+ ctx.setResourceName("volume");
+
+ Map cfg = new HashMap<>();
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class)) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.anyLong(), Mockito.any(TimeUnit.class)))
+ .thenThrow(new AssertionError("timedTask should not run"));
+
+ assertNull(OzoneResourceMgr.getOzoneResources(null, "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test09_getOzoneResources_whenUserInputNull_returnsNull() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput(null);
+ ctx.setResourceName("volume");
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class)) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.anyLong(), Mockito.any(TimeUnit.class)))
+ .thenThrow(new AssertionError("timedTask should not run"));
+
+ assertNull(OzoneResourceMgr.getOzoneResources("svc", "ozone", new HashMap<>(), ctx));
+ }
+ }
+
+ @Test
+ void test10_getOzoneResources_whenUserInputEmptyOnVolume_noCallable() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("");
+ ctx.setResourceName("volume");
+
+ Map cfg = new HashMap<>();
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg)))
+ .thenReturn(Mockito.mock(OzoneClient.class)))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.anyLong(), Mockito.any(TimeUnit.class)))
+ .thenThrow(new AssertionError("timedTask should not run"));
+
+ assertNull(OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test11_getOzoneResources_whenOzoneClientNull_returnsNull() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("vol");
+ ctx.setResourceName("volume");
+
+ Map cfg = new HashMap<>();
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())).thenReturn(null))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.anyLong(), Mockito.any(TimeUnit.class)))
+ .thenThrow(new AssertionError("timedTask should not run"));
+
+ assertNull(OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test12_getOzoneResources_whenTimedTaskThrows_propagates() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("v");
+ ctx.setResourceName("volume");
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS)))
+ .thenThrow(new IllegalStateException("timed-fail"));
+
+ assertThrows(IllegalStateException.class, () -> OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test13_getOzoneResources_whenKeyCallableThrows_propagatesException() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("kpre");
+ ctx.setResourceName("key");
+
+ Map> res = new HashMap<>();
+ res.put("volume", Collections.singletonList("v1"));
+ res.put("bucket", Collections.singletonList("b1"));
+ ctx.setResources(res);
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+
+ Mockito.when(client.getKeyList(Mockito.eq("kpre"), Mockito.eq(Collections.singletonList("v1")),
+ Mockito.eq(Collections.singletonList("b1")))).thenThrow(new NullPointerException("simulated"));
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS))).then(inv -> {
+ @SuppressWarnings("unchecked")
+ Callable> callable = inv.getArgument(0);
+
+ return callable.call();
+ });
+
+ assertThrows(NullPointerException.class, () -> OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test14_getOzoneResources_whenVolumePrefix_resolvesViaTimedTask() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("vol");
+ ctx.setResourceName("volume");
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+ List want = Arrays.asList("v1", "v2");
+ Mockito.when(client.getVolumeList(Mockito.eq("vol"))).thenReturn(want);
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS))).then(inv -> {
+ @SuppressWarnings("unchecked")
+ Callable> callable = inv.getArgument(0);
+
+ return callable.call();
+ });
+
+ List out = OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx);
+
+ assertEquals(want, out);
+ }
+ }
+
+ @Test
+ void test15_privateConstructor_rejectsInstantiation() throws Exception {
+ Constructor ctor = OzoneResourceMgr.class.getDeclaredConstructor();
+ ctor.setAccessible(true);
+
+ InvocationTargetException ite = assertThrows(InvocationTargetException.class, ctor::newInstance);
+ assertTrue(ite.getCause() instanceof UnsupportedOperationException);
+ }
+
+ @Test
+ void test16_getOzoneResources_whenResourceNameNull_skipsPrefixes() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("vol");
+ ctx.setResourceName(null);
+
+ Map cfg = new HashMap<>();
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg)))
+ .thenReturn(Mockito.mock(OzoneClient.class)))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.anyLong(), Mockito.any(TimeUnit.class)))
+ .thenThrow(new AssertionError("timedTask should not run"));
+
+ assertNull(OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test17_getOzoneResources_whenResourceMapEmpty_skipsInheritedLists() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("buck");
+ ctx.setResourceName("bucket");
+ ctx.setResources(new HashMap<>());
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+ Mockito.when(client.getBucketList(Mockito.eq("buck"), Mockito.isNull())).thenReturn(Collections.singletonList("only-b"));
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS))).then(inv -> {
+ @SuppressWarnings("unchecked")
+ Callable> callable = inv.getArgument(0);
+
+ return callable.call();
+ });
+
+ assertEquals(Collections.singletonList("only-b"), OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+
+ @Test
+ void test18_getOzoneResources_whenResourceMapHasNoOzoneKeys_listsStayNull() throws Exception {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("bpre");
+ ctx.setResourceName("bucket");
+ ctx.setResources(Collections.singletonMap("other", Collections.singletonList("orphan")));
+
+ Map cfg = new HashMap<>();
+ OzoneClient client = Mockito.mock(OzoneClient.class);
+ Mockito.when(client.getBucketList(Mockito.eq("bpre"), Mockito.isNull())).thenReturn(Collections.singletonList("b2"));
+
+ try (MockedStatic timed = Mockito.mockStatic(TimedEventUtil.class);
+ MockedConstruction ignored = Mockito.mockConstruction(OzoneConnectionMgr.class,
+ (mock, context) -> Mockito.when(mock.getOzoneConnection(Mockito.eq("svc"), Mockito.eq("ozone"), Mockito.eq(cfg))).thenReturn(client))) {
+ timed.when(() -> TimedEventUtil.timedTask(Mockito.any(Callable.class), Mockito.eq(5L), Mockito.eq(TimeUnit.SECONDS))).then(inv -> {
+ @SuppressWarnings("unchecked")
+ Callable> callable = inv.getArgument(0);
+
+ return callable.call();
+ });
+
+ assertEquals(Collections.singletonList("b2"), OzoneResourceMgr.getOzoneResources("svc", "ozone", cfg, ctx));
+ }
+ }
+}