diff --git a/plugin-kylin/pom.xml b/plugin-kylin/pom.xml
index bd689ff2f9b..2f01840fbdc 100644
--- a/plugin-kylin/pom.xml
+++ b/plugin-kylin/pom.xml
@@ -252,6 +252,13 @@
org.mockito
mockito-core
+ ${mockito.version}
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
test
diff --git a/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/TestRangerServiceKylin.java b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/TestRangerServiceKylin.java
new file mode 100644
index 00000000000..2e236d031fd
--- /dev/null
+++ b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/TestRangerServiceKylin.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.services.kylin;
+
+import org.apache.ranger.plugin.client.HadoopException;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+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 RangerServiceKylin
+ */
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestRangerServiceKylin {
+ @Test
+ void test01_validateConfig_whenConfigsNull_returnsEmptyMap() {
+ RangerServiceKylin svc = new RangerServiceKylin();
+ svc.setConfigs(null);
+
+ Map res = svc.validateConfig();
+
+ assertNotNull(res);
+ assertTrue(res.isEmpty());
+ }
+
+ @Test
+ void test02_validateConfig_whenConfigsEmptyMap_propagatesHadoopException() {
+ RangerServiceKylin svc = new RangerServiceKylin();
+ svc.setServiceName("svc");
+ svc.setConfigs(Collections.emptyMap());
+
+ assertThrows(HadoopException.class, svc::validateConfig);
+ }
+
+ @Test
+ void test03_lookupResource_whenContextNull_returnsEmptyList() {
+ RangerServiceKylin svc = new RangerServiceKylin();
+ svc.setServiceName("svc");
+ svc.setConfigs(kylinClientConfigs("http://127.0.0.1:13"));
+
+ List res = svc.lookupResource(null);
+
+ assertTrue(res.isEmpty());
+ }
+
+ @Test
+ void test04_lookupResource_whenConnectionConfigEmpty_returnsNull() {
+ RangerServiceKylin svc = new RangerServiceKylin();
+ svc.setServiceName("svc");
+ svc.setConfigs(Collections.emptyMap());
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("any");
+
+ List res = svc.lookupResource(ctx);
+
+ assertNull(res);
+ }
+
+ @Test
+ void test05_init_whenServiceDefAndServicePresent_populatesBaseStateFromService() {
+ RangerServiceKylin svc = new RangerServiceKylin();
+ RangerServiceDef def = new RangerServiceDef();
+ Map cfg = new HashMap<>();
+ cfg.put("kylin.url", "http://localhost:7070");
+ RangerService rs = new RangerService("kylin", "kylin-svc", null, null, cfg);
+
+ svc.init(def, rs);
+
+ assertSame(def, svc.getServiceDef());
+ assertSame(rs, svc.getService());
+ assertEquals(cfg, svc.getConfigs());
+ assertEquals("kylin-svc", svc.getServiceName());
+ assertEquals("kylin", svc.getServiceType());
+ }
+
+ @Test
+ void test06_init_whenServiceNull_throwsNullPointerException() {
+ RangerServiceKylin svc = new RangerServiceKylin();
+
+ assertThrows(NullPointerException.class, () -> svc.init(new RangerServiceDef(), null));
+ }
+
+ @Test
+ void test07_lookupResource_whenGetKylinResourcesThrows_propagatesSameException() {
+ RangerServiceKylin svc = new RangerServiceKylin();
+ svc.setServiceName("svc");
+ svc.setConfigs(kylinClientConfigs("http://127.0.0.1:13"));
+ ResourceLookupContext ctx = new ResourceLookupContextThrowsOnResources();
+ ctx.setUserInput("q");
+
+ IllegalStateException ex =
+ assertThrows(IllegalStateException.class, () -> svc.lookupResource(ctx));
+
+ assertEquals("simulated resource lookup failure", ex.getMessage());
+ }
+
+ private static Map kylinClientConfigs(String kylinUrl) {
+ Map configs = new HashMap<>();
+ configs.put("kylin.url", kylinUrl);
+ configs.put("username", "u");
+ configs.put("password", "p");
+ configs.put("authtype", "simple");
+ configs.put("hadoop.security.authentication", "simple");
+ return configs;
+ }
+
+ private static final class ResourceLookupContextThrowsOnResources extends ResourceLookupContext {
+ @Override
+ public Map> getResources() {
+ throw new IllegalStateException("simulated resource lookup failure");
+ }
+ }
+}
diff --git a/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/TestKylinClient.java b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/TestKylinClient.java
new file mode 100644
index 00000000000..29f3076c7e1
--- /dev/null
+++ b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/TestKylinClient.java
@@ -0,0 +1,296 @@
+/*
+ * 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.kylin.client;
+
+import org.apache.ranger.plugin.client.HadoopException;
+import org.apache.ranger.services.kylin.client.json.model.KylinProjectResponse;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.security.auth.Subject;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+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.assertFalse;
+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.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.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for KylinClient
+ */
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+class TestKylinClient {
+ @Test
+ void test01_constructor_whenConfigsComplete_buildsClient() {
+ assertNotNull(new KylinClient("svc", kylinClientConfigs("http://127.0.0.1:7070")));
+ }
+
+ @Test
+ void test02_constructor_whenKylinUrlMissing_stillInstantiates() {
+ Map configs = new HashMap<>();
+ configs.put("kylin.url", "");
+ configs.put("username", "u");
+ configs.put("password", "p");
+ configs.put("authtype", "simple");
+ configs.put("hadoop.security.authentication", "simple");
+
+ assertNotNull(new KylinClient("svc", configs));
+ }
+
+ @Test
+ void test03_getKylinClient_whenConfigsPresent_returnsClient() {
+ assertNotNull(KylinClient.getKylinClient("svc", kylinClientConfigs("http://127.0.0.1:9")));
+ }
+
+ @Test
+ void test04_getKylinClient_whenConfigsEmpty_throwsHadoopException() {
+ assertThrows(HadoopException.class, () -> KylinClient.getKylinClient("svc", Collections.emptyMap()));
+ }
+
+ @Test
+ void test05_getProjectList_whenSubjectNull_returnsEmpty() {
+ KylinClient client = new KylinClientOverrideSubject("svc", kylinClientConfigs("http://127.0.0.1:1"), null);
+ assertTrue(client.getProjectList("x", null).isEmpty());
+ }
+
+ @Test
+ void test06_getKylinProjectResponse_whenNullResponse_throws() throws Exception {
+ KylinClient client = new KylinClient("svc", kylinClientConfigs("http://parse.test:2"));
+ Method m = KylinClient.class.getDeclaredMethod("getKylinProjectResponse", Response.class);
+ m.setAccessible(true);
+ InvocationTargetException ite =
+ assertThrows(InvocationTargetException.class, () -> m.invoke(client, (Response) null));
+ assertTrue(ite.getCause() instanceof HadoopException);
+ }
+
+ @Test
+ void test07_getProjectFromResponse_filtersAndMatches() throws Exception {
+ List parsed = new ArrayList<>();
+ KylinProjectResponse a = new KylinProjectResponse();
+ a.setName("Apple");
+ KylinProjectResponse b = new KylinProjectResponse();
+ b.setName("Berry");
+ parsed.add(a);
+ parsed.add(b);
+
+ Method m = KylinClient.class.getDeclaredMethod(
+ "getProjectFromResponse", String.class, List.class, List.class);
+ m.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ List out = (List) m.invoke(null, "b", Collections.singletonList("Apple"), parsed);
+ assertEquals(Collections.singletonList("Berry"), out);
+ }
+
+ @Test
+ void test08_getProjectFromResponse_whenWildcardPrefix_includesNonExcluded() throws Exception {
+ List parsed = new ArrayList<>();
+ KylinProjectResponse x = new KylinProjectResponse();
+ x.setName("m1");
+ KylinProjectResponse y = new KylinProjectResponse();
+ y.setName("m2");
+ parsed.add(x);
+ parsed.add(y);
+
+ Method m = KylinClient.class.getDeclaredMethod(
+ "getProjectFromResponse", String.class, List.class, List.class);
+ m.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ List out = (List) m.invoke(null, "*z", Collections.singletonList("m2"), parsed);
+ assertEquals(Collections.singletonList("m1"), out);
+ }
+
+ @Test
+ void test09_getClientResponse_whenSplitYieldsNoUrls_returnsNull() throws Exception {
+ Method m = KylinClient.class.getDeclaredMethod("getClientResponse", String.class, String.class, String.class);
+ m.setAccessible(true);
+ assertNull(m.invoke(null, ",", "u", "p"));
+ }
+
+ @Test
+ void test10_getKylinProjectResponse_whenOkAndEmptyJsonArray_returnsEmptyList() throws Exception {
+ Response response = mock(Response.class);
+ KylinClient client = new KylinClient("svc", kylinClientConfigs("http://empty-json:1"));
+ when(response.getStatus()).thenReturn(200);
+ when(response.readEntity(String.class)).thenReturn("[]");
+
+ Method m = KylinClient.class.getDeclaredMethod("getKylinProjectResponse", Response.class);
+ m.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ List parsed = (List) m.invoke(client, response);
+ assertTrue(parsed.isEmpty());
+ verify(response).close();
+ }
+
+ @Test
+ void test11_getProjectResponse_whenGetThrows_returnsNull() throws Exception {
+ Client client = mock(Client.class);
+ when(client.target(anyString())).thenThrow(new ProcessingException("no-http"));
+
+ Method m = KylinClient.class.getDeclaredMethod("getProjectResponse", String.class, Client.class);
+ m.setAccessible(true);
+
+ assertNull(m.invoke(null, "http://fail.local/kylin/api/projects", client));
+ }
+
+ @Test
+ void test12_getProjectResponse_whenStatusNotOk_returnsResponse() throws Exception {
+ Response mockResponse = mock(Response.class);
+ Invocation.Builder builder = mock(Invocation.Builder.class);
+ WebTarget webTarget = mock(WebTarget.class);
+ Client client = mock(Client.class);
+
+ when(mockResponse.getStatus()).thenReturn(500);
+ when(mockResponse.readEntity(String.class)).thenReturn("err-body");
+ when(builder.get()).thenReturn(mockResponse);
+ when(webTarget.request(MediaType.APPLICATION_JSON)).thenReturn(builder);
+ when(client.target(anyString())).thenReturn(webTarget);
+
+ Method m = KylinClient.class.getDeclaredMethod("getProjectResponse", String.class, Client.class);
+ m.setAccessible(true);
+ Response res = (Response) m.invoke(null, "http://bad:9/kylin/api/projects", client);
+ assertSame(mockResponse, res);
+ }
+
+ @Test
+ void test13_getKylinProjectResponse_whenHttpNotOk_throws() throws Exception {
+ Response response = mock(Response.class);
+ KylinClient client = new KylinClient("svc", kylinClientConfigs("http://host:1"));
+ when(response.getStatus()).thenReturn(503);
+
+ Method m = KylinClient.class.getDeclaredMethod("getKylinProjectResponse", Response.class);
+ m.setAccessible(true);
+ InvocationTargetException ite =
+ assertThrows(InvocationTargetException.class, () -> m.invoke(client, response));
+ assertTrue(ite.getCause() instanceof HadoopException);
+ }
+
+ @Test
+ void test14_getKylinProjectResponse_whenOkButInvalidJson_wrapsInHadoopException() throws Exception {
+ Response response = mock(Response.class);
+ KylinClient client = new KylinClient("svc", kylinClientConfigs("http://host:2"));
+ when(response.getStatus()).thenReturn(200);
+ when(response.readEntity(String.class)).thenReturn("{ not valid json");
+
+ Method m = KylinClient.class.getDeclaredMethod("getKylinProjectResponse", Response.class);
+ m.setAccessible(true);
+ InvocationTargetException ite =
+ assertThrows(InvocationTargetException.class, () -> m.invoke(client, response));
+ assertTrue(ite.getCause() instanceof HadoopException);
+ verify(response).close();
+ }
+
+ @Test
+ void test15_getKylinProjectResponse_whenOkAndValidJson_returnsList() throws Exception {
+ Response response = mock(Response.class);
+ KylinClient client = new KylinClient("svc", kylinClientConfigs("http://host:3"));
+ when(response.getStatus()).thenReturn(200);
+ when(response.readEntity(String.class)).thenReturn("[{\"name\":\"P1\"}]");
+
+ Method m = KylinClient.class.getDeclaredMethod("getKylinProjectResponse", Response.class);
+ m.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ List parsed = (List) m.invoke(client, response);
+ assertEquals(1, parsed.size());
+ assertEquals("P1", parsed.get(0).getName());
+ verify(response).close();
+ }
+
+ @Test
+ void test16_connectionTest_whenProjectListNonEmpty_setsConnectivitySuccess() {
+ Map configs = kylinClientConfigs("http://unused:1");
+ try (MockedStatic kylin = Mockito.mockStatic(KylinClient.class, Mockito.CALLS_REAL_METHODS)) {
+ KylinClient delegate = mock(KylinClient.class);
+ kylin.when(() -> KylinClient.getKylinClient(anyString(), any())).thenReturn(delegate);
+ when(delegate.getProjectList(isNull(), isNull())).thenReturn(Collections.singletonList("p1"));
+
+ Map res = KylinClient.connectionTest("svc", configs);
+
+ assertTrue(Boolean.TRUE.equals(res.get("connectivityStatus")));
+ assertEquals("ConnectionTest Successful", res.get("message"));
+ assertEquals("ConnectionTest Successful", res.get("description"));
+ }
+ }
+
+ @Test
+ void test17_connectionTest_whenProjectListEmpty_setsConnectivityFailure() {
+ Map configs = kylinClientConfigs("http://unused:2");
+ try (MockedStatic kylin = Mockito.mockStatic(KylinClient.class, Mockito.CALLS_REAL_METHODS)) {
+ KylinClient delegate = mock(KylinClient.class);
+ kylin.when(() -> KylinClient.getKylinClient(anyString(), any())).thenReturn(delegate);
+ when(delegate.getProjectList(isNull(), isNull())).thenReturn(Collections.emptyList());
+
+ Map res = KylinClient.connectionTest("svc", configs);
+
+ assertFalse(Boolean.TRUE.equals(res.get("connectivityStatus")));
+ assertTrue(String.valueOf(res.get("message")).contains("Unable to retrieve any kylin projects"));
+ }
+ }
+
+ private static Map kylinClientConfigs(String kylinUrl) {
+ Map configs = new HashMap<>();
+ configs.put("kylin.url", kylinUrl);
+ configs.put("username", "u");
+ configs.put("password", "p");
+ configs.put("authtype", "simple");
+ configs.put("hadoop.security.authentication", "simple");
+ return configs;
+ }
+
+ private static final class KylinClientOverrideSubject extends KylinClient {
+ private final Subject subjectOverride;
+
+ KylinClientOverrideSubject(String serviceName, Map configs, Subject subjectOverride) {
+ super(serviceName, configs);
+ this.subjectOverride = subjectOverride;
+ }
+
+ @Override
+ protected Subject getLoginSubject() {
+ return subjectOverride;
+ }
+ }
+}
diff --git a/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/TestKylinResourceMgr.java b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/TestKylinResourceMgr.java
new file mode 100644
index 00000000000..c9a6ca29ccb
--- /dev/null
+++ b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/TestKylinResourceMgr.java
@@ -0,0 +1,165 @@
+/*
+ * 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.kylin.client;
+
+import org.apache.ranger.plugin.client.HadoopException;
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+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.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for KylinResourceMgr
+ */
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(MockitoExtension.class)
+class TestKylinResourceMgr {
+ @Test
+ void test01_validateConfig_whenConnectionConfigEmpty_propagatesHadoopException() {
+ assertThrows(HadoopException.class, () -> KylinResourceMgr.validateConfig("svc", Collections.emptyMap()));
+ }
+
+ @Test
+ void test02_getKylinResources_whenConfigsEmpty_returnsNull() {
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("p");
+
+ List res = KylinResourceMgr.getKylinResources("svc", Collections.emptyMap(), ctx);
+
+ assertNull(res);
+ }
+
+ @Test
+ void test03_privateConstructor_isReflectivelyCallable() throws Exception {
+ Constructor ctor = KylinResourceMgr.class.getDeclaredConstructor();
+ ctor.setAccessible(true);
+ assertNotNull(ctor.newInstance());
+ }
+
+ @Test
+ void test04_getKylinResources_whenUserInputEmpty_defaultsToWildcardAndUsesProjectResourceList() {
+ Map configs = kylinClientConfigs("http://resource-mgr:1");
+
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("");
+ Map> resourceMap = new HashMap<>();
+ resourceMap.put(KylinResourceMgr.PROJECT, Collections.singletonList("existing"));
+ ctx.setResources(resourceMap);
+
+ try (MockedStatic kylin = Mockito.mockStatic(KylinClient.class, Mockito.CALLS_REAL_METHODS)) {
+ KylinClient delegate = mock(KylinClient.class);
+ kylin.when(() -> KylinClient.getKylinClient(anyString(), any())).thenReturn(delegate);
+ List expected = Collections.singletonList("from-kylin");
+ when(delegate.getProjectList(eq("*"), eq(Collections.singletonList("existing")))).thenReturn(expected);
+
+ List res = KylinResourceMgr.getKylinResources("svc", configs, ctx);
+
+ assertEquals(expected, res);
+ verify(delegate).getProjectList(eq("*"), eq(Collections.singletonList("existing")));
+ }
+ }
+
+ @Test
+ void test05_getKylinResources_whenResourceMapNull_passesNullProjectList() {
+ Map configs = kylinClientConfigs("http://resource-mgr:2");
+
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("prod");
+ ctx.setResources(null);
+
+ try (MockedStatic kylin = Mockito.mockStatic(KylinClient.class, Mockito.CALLS_REAL_METHODS)) {
+ KylinClient delegate = mock(KylinClient.class);
+ kylin.when(() -> KylinClient.getKylinClient(anyString(), any())).thenReturn(delegate);
+ when(delegate.getProjectList(eq("prod"), isNull())).thenReturn(Collections.emptyList());
+
+ List res = KylinResourceMgr.getKylinResources("svc", configs, ctx);
+
+ assertTrue(res.isEmpty());
+ verify(delegate).getProjectList(eq("prod"), isNull());
+ }
+ }
+
+ @Test
+ void test06_getKylinResources_whenResourceMapWithoutProjectKey_passesNullProjectList() {
+ Map configs = kylinClientConfigs("http://resource-mgr:3");
+
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("q");
+ Map> resourceMap = new HashMap<>();
+ resourceMap.put("other-resource", Collections.singletonList("v"));
+ ctx.setResources(resourceMap);
+
+ try (MockedStatic kylin = Mockito.mockStatic(KylinClient.class, Mockito.CALLS_REAL_METHODS)) {
+ KylinClient delegate = mock(KylinClient.class);
+ kylin.when(() -> KylinClient.getKylinClient(anyString(), any())).thenReturn(delegate);
+ when(delegate.getProjectList(eq("q"), isNull())).thenReturn(Collections.emptyList());
+
+ KylinResourceMgr.getKylinResources("svc", configs, ctx);
+
+ verify(delegate).getProjectList(eq("q"), isNull());
+ }
+ }
+
+ @Test
+ void test07_getKylinResources_whenKylinClientNull_returnsNull() {
+ Map configs = kylinClientConfigs("http://resource-mgr:4");
+
+ ResourceLookupContext ctx = new ResourceLookupContext();
+ ctx.setUserInput("any");
+
+ try (MockedStatic kylin = Mockito.mockStatic(KylinClient.class, Mockito.CALLS_REAL_METHODS)) {
+ kylin.when(() -> KylinClient.getKylinClient(anyString(), any())).thenReturn(null);
+
+ assertNull(KylinResourceMgr.getKylinResources("svc", configs, ctx));
+ }
+ }
+
+ private static Map kylinClientConfigs(String kylinUrl) {
+ Map configs = new HashMap<>();
+ configs.put("kylin.url", kylinUrl);
+ configs.put("username", "u");
+ configs.put("password", "p");
+ configs.put("authtype", "simple");
+ configs.put("hadoop.security.authentication", "simple");
+ return configs;
+ }
+}
diff --git a/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/json/model/TestKylinProjectResponse.java b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/json/model/TestKylinProjectResponse.java
new file mode 100644
index 00000000000..c33931b7992
--- /dev/null
+++ b/plugin-kylin/src/test/java/org/apache/ranger/services/kylin/client/json/model/TestKylinProjectResponse.java
@@ -0,0 +1,80 @@
+/*
+ * 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.kylin.client.json.model;
+
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for KylinProjectResponse
+ */
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestKylinProjectResponse {
+ @Test
+ void test01_gettersAndSetters_roundTripValues() {
+ KylinProjectResponse response = new KylinProjectResponse();
+ List tables = Collections.singletonList("t1");
+ List models = Arrays.asList("m1", "m2");
+
+ response.setUuid("uuid-1");
+ response.setVersion("v1");
+ response.setName("my-project");
+ response.setOwner("owner1");
+ response.setStatus("ACTIVE");
+ response.setDescription("desc");
+ response.setTables(tables);
+ response.setModels(models);
+
+ assertEquals("uuid-1", response.getUuid());
+ assertEquals("v1", response.getVersion());
+ assertEquals("my-project", response.getName());
+ assertEquals("owner1", response.getOwner());
+ assertEquals("ACTIVE", response.getStatus());
+ assertEquals("desc", response.getDescription());
+ assertEquals(tables, response.getTables());
+ assertEquals(models, response.getModels());
+ }
+
+ @Test
+ void test02_toString_containsKeyFieldsWhenSomeFieldsNull() {
+ KylinProjectResponse response = new KylinProjectResponse();
+ response.setName("only-name");
+
+ String text = response.toString();
+ assertTrue(text.contains("only-name"));
+ assertTrue(text.contains("KylinProjectResponse"));
+ }
+
+ @Test
+ void test03_toString_whenAllFieldsNull_containsClassName() {
+ KylinProjectResponse response = new KylinProjectResponse();
+
+ String text = response.toString();
+
+ assertTrue(text.contains("KylinProjectResponse"));
+ }
+}