diff --git a/plugin-nifi/pom.xml b/plugin-nifi/pom.xml
index 43bb1980115..d1751ad70d6 100644
--- a/plugin-nifi/pom.xml
+++ b/plugin-nifi/pom.xml
@@ -170,5 +170,11 @@
${mockito.version}
test
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
+ test
+
diff --git a/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/TestRangerServiceNiFi.java b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/TestRangerServiceNiFi.java
new file mode 100644
index 00000000000..b770a7db11a
--- /dev/null
+++ b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/TestRangerServiceNiFi.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.nifi;
+
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.apache.ranger.services.nifi.client.NiFiClient;
+import org.apache.ranger.services.nifi.client.NiFiConfigs;
+import org.apache.ranger.services.nifi.client.NiFiConnectionMgr;
+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.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.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for RangerServiceNiFi
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestRangerServiceNiFi {
+ @Test
+ void validateConfig_throwsWhenConfigsNull() {
+ RangerServiceNiFi service = new RangerServiceNiFi();
+ service.setConfigs(null);
+
+ assertThrows(IllegalStateException.class, service::validateConfig);
+ }
+
+ @Test
+ void validateConfig_propagatesWhenConnectionTestThrows() {
+ RangerServiceNiFi service = new RangerServiceNiFi();
+ service.setServiceName("nifi-svc");
+ Map configs = new HashMap<>();
+ configs.put(NiFiConfigs.NIFI_URL, "http://localhost:8080/nifi-api/resources");
+ configs.put(NiFiConfigs.NIFI_AUTHENTICATION_TYPE, "NONE");
+ service.setConfigs(configs);
+
+ try (MockedStatic mgr = Mockito.mockStatic(NiFiConnectionMgr.class)) {
+ mgr.when(() -> NiFiConnectionMgr.connectionTest(anyString(), any()))
+ .thenThrow(new RuntimeException("connection test failure"));
+
+ assertThrows(RuntimeException.class, service::validateConfig);
+ }
+ }
+
+ @Test
+ void lookupResource_returnsResourcesFromClient() throws Exception {
+ RangerServiceNiFi service = new RangerServiceNiFi();
+ service.setServiceName("nifi-svc");
+ Map configs = new HashMap<>();
+ configs.put(NiFiConfigs.NIFI_URL, "http://localhost:8080/nifi-api/resources");
+ configs.put(NiFiConfigs.NIFI_AUTHENTICATION_TYPE, "NONE");
+ service.setConfigs(configs);
+
+ ResourceLookupContext context = Mockito.mock(ResourceLookupContext.class);
+ NiFiClient client = Mockito.mock(NiFiClient.class);
+ Mockito.when(client.getResources(context)).thenReturn(List.of("/flow", "/system"));
+
+ try (MockedStatic mgr = Mockito.mockStatic(NiFiConnectionMgr.class)) {
+ mgr.when(() -> NiFiConnectionMgr.getNiFiClient("nifi-svc", configs)).thenReturn(client);
+
+ List resources = service.lookupResource(context);
+
+ assertEquals(2, resources.size());
+ assertTrue(resources.contains("/flow"));
+ }
+ }
+
+ @Test
+ void lookupResource_propagatesExceptionFromClient() throws Exception {
+ RangerServiceNiFi service = new RangerServiceNiFi();
+ service.setServiceName("nifi-svc");
+ Map configs = new HashMap<>();
+ configs.put(NiFiConfigs.NIFI_URL, "http://localhost:8080/nifi-api/resources");
+ configs.put(NiFiConfigs.NIFI_AUTHENTICATION_TYPE, "NONE");
+ service.setConfigs(configs);
+
+ ResourceLookupContext context = Mockito.mock(ResourceLookupContext.class);
+ NiFiClient client = Mockito.mock(NiFiClient.class);
+ Mockito.when(client.getResources(context)).thenThrow(new Exception("lookup failed"));
+
+ try (MockedStatic mgr = Mockito.mockStatic(NiFiConnectionMgr.class)) {
+ mgr.when(() -> NiFiConnectionMgr.getNiFiClient("nifi-svc", configs)).thenReturn(client);
+
+ Exception ex = assertThrows(Exception.class, () -> service.lookupResource(context));
+ assertTrue(ex.getMessage().contains("lookup failed"));
+ }
+ }
+
+ @Test
+ void validateConfig_successPathWhenConnectionTestReturnsSuccessMap() {
+ RangerServiceNiFi service = new RangerServiceNiFi();
+ service.setServiceName("nifi-svc");
+ Map configs = new HashMap<>();
+ configs.put(NiFiConfigs.NIFI_URL, "http://localhost:8080/nifi-api/resources");
+ configs.put(NiFiConfigs.NIFI_AUTHENTICATION_TYPE, "NONE");
+ service.setConfigs(configs);
+
+ HashMap expected = new HashMap<>();
+ expected.put("connectivityStatus", true);
+ expected.put("message", "ok");
+
+ try (MockedStatic mgr = Mockito.mockStatic(NiFiConnectionMgr.class)) {
+ mgr.when(() -> NiFiConnectionMgr.connectionTest(anyString(), any())).thenReturn(expected);
+
+ Map result = service.validateConfig();
+
+ assertTrue((Boolean) result.get("connectivityStatus"));
+ assertEquals("ok", result.get("message"));
+ }
+ }
+
+ @Test
+ void validateConfig_returnsFailureMapWhenConnectionTestReturnsFailureWithoutThrowing() {
+ RangerServiceNiFi service = new RangerServiceNiFi();
+ service.setServiceName("nifi-svc");
+ Map configs = new HashMap<>();
+ configs.put(NiFiConfigs.NIFI_URL, "http://localhost:8080/nifi-api/resources");
+ configs.put(NiFiConfigs.NIFI_AUTHENTICATION_TYPE, "NONE");
+ service.setConfigs(configs);
+
+ HashMap expected = new HashMap<>();
+ expected.put("connectivityStatus", false);
+ expected.put("message", "Error creating NiFi client");
+
+ try (MockedStatic mgr = Mockito.mockStatic(NiFiConnectionMgr.class)) {
+ mgr.when(() -> NiFiConnectionMgr.connectionTest(anyString(), any())).thenReturn(expected);
+
+ Map result = service.validateConfig();
+
+ assertFalse((Boolean) result.get("connectivityStatus"));
+ assertEquals("Error creating NiFi client", result.get("message"));
+ }
+ }
+}
diff --git a/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiAuthType.java b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiAuthType.java
new file mode 100644
index 00000000000..7edae2ad288
--- /dev/null
+++ b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiAuthType.java
@@ -0,0 +1,47 @@
+/*
+ * 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.nifi.client;
+
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for NiFiAuthType
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestNiFiAuthType {
+ @Test
+ void valueOfReturnsConstantForValidName() {
+ assertEquals(NiFiAuthType.NONE, NiFiAuthType.valueOf("NONE"));
+ assertEquals(NiFiAuthType.SSL, NiFiAuthType.valueOf("SSL"));
+ }
+
+ @Test
+ void valueOfThrowsForInvalidName() {
+ assertThrows(IllegalArgumentException.class, () -> NiFiAuthType.valueOf("UNKNOWN"));
+ }
+}
diff --git a/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiClient.java b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiClient.java
index 589ea29ef67..015bee424b1 100644
--- a/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiClient.java
+++ b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiClient.java
@@ -20,11 +20,17 @@
import org.apache.ranger.plugin.service.ResourceLookupContext;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.stubbing.OngoingStubbing;
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
@@ -42,7 +48,13 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
-public class TestNiFiClient {
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for NiFiClient
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestNiFiClient {
private static final String RESOURCES_RESPONSE = "{\n" +
" \"revision\": {\n" +
" \"clientId\": \"0daac173-025c-4aa7-b644-97f7b10435d2\"\n" +
@@ -77,18 +89,18 @@ public class TestNiFiClient {
private NiFiClient niFiClient;
- @BeforeEach
- public void setup() {
- niFiClient = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ private static NiFiClient newNiFiClientWithMockResourcesResponse(boolean stubReadEntityForOkStatus) {
+ return new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
@Override
protected Client buildClient() {
- return new MockNiFiClient(RESOURCES_RESPONSE, 200).buildClient();
+ return new MockNiFiClient(RESOURCES_RESPONSE, 200, stubReadEntityForOkStatus).buildClient();
}
};
}
@Test
- public void testGetResourcesNoUserInput() throws Exception {
+ void testGetResourcesNoUserInput() throws Exception {
+ niFiClient = newNiFiClientWithMockResourcesResponse(true);
ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class);
when(resourceLookupContext.getUserInput()).thenReturn("");
@@ -109,7 +121,8 @@ public void testGetResourcesNoUserInput() throws Exception {
}
@Test
- public void testGetResourcesWithUserInputBeginning() throws Exception {
+ void testGetResourcesWithUserInputBeginning() throws Exception {
+ niFiClient = newNiFiClientWithMockResourcesResponse(true);
ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class);
when(resourceLookupContext.getUserInput()).thenReturn("/pr");
@@ -126,7 +139,8 @@ public void testGetResourcesWithUserInputBeginning() throws Exception {
}
@Test
- public void testGetResourcesWithUserInputAnywhere() throws Exception {
+ void testGetResourcesWithUserInputAnywhere() throws Exception {
+ niFiClient = newNiFiClientWithMockResourcesResponse(true);
ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class);
when(resourceLookupContext.getUserInput()).thenReturn("trol");
@@ -142,7 +156,7 @@ public void testGetResourcesWithUserInputAnywhere() throws Exception {
}
@Test
- public void testGetResourcesErrorResponse() throws NoSuchAlgorithmException, KeyManagementException {
+ void testGetResourcesErrorResponse() throws NoSuchAlgorithmException, KeyManagementException {
final String errorMsg = "unknown error";
niFiClient = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
@@ -153,7 +167,6 @@ protected Client buildClient() {
};
ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class);
- when(resourceLookupContext.getUserInput()).thenReturn("");
try {
niFiClient.getResources(resourceLookupContext);
@@ -164,14 +177,15 @@ protected Client buildClient() {
}
@Test
- public void testConnectionTestSuccess() {
+ void testConnectionTestSuccess() {
+ niFiClient = newNiFiClientWithMockResourcesResponse(false);
HashMap ret = niFiClient.connectionTest();
Assertions.assertNotNull(ret);
Assertions.assertEquals(NiFiClient.SUCCESS_MSG, ret.get("message"));
}
@Test
- public void testConnectionTestFailure() {
+ void testConnectionTestFailure() {
final String errorMsg = "unknown error";
niFiClient = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
@@ -186,19 +200,136 @@ protected Client buildClient() {
Assertions.assertEquals(NiFiClient.FAILURE_MSG, ret.get("message"));
}
+ @Test
+ void testConnectionTestProcessingExceptionMessageNullUsesUnknownError() {
+ NiFiClient client = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ @Override
+ protected Client buildClient() {
+ Client mockClient = Mockito.mock(Client.class);
+ WebTarget mockWebTarget = Mockito.mock(WebTarget.class);
+ Invocation.Builder mockBuilder = Mockito.mock(Invocation.Builder.class);
+ when(mockClient.target(anyString())).thenReturn(mockWebTarget);
+ when(mockWebTarget.request(any(String.class))).thenReturn(mockBuilder);
+ ProcessingException processingException = Mockito.mock(ProcessingException.class);
+ Mockito.when(processingException.getMessage()).thenReturn(null);
+ when(mockBuilder.get()).thenThrow(processingException);
+ return mockClient;
+ }
+ };
+
+ HashMap ret = client.connectionTest();
+ Assertions.assertNotNull(ret);
+ Assertions.assertEquals(NiFiClient.FAILURE_MSG, ret.get("message"));
+ Assertions.assertTrue(ret.get("description").toString().contains("Unknown error"));
+ }
+
+ @Test
+ void testConnectionTestWebApplicationException() {
+ NiFiClient client = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ @Override
+ protected Client buildClient() {
+ Client mockClient = Mockito.mock(Client.class);
+ WebTarget mockWebTarget = Mockito.mock(WebTarget.class);
+ Invocation.Builder mockBuilder = Mockito.mock(Invocation.Builder.class);
+ when(mockClient.target(anyString())).thenReturn(mockWebTarget);
+ when(mockWebTarget.request(any(String.class))).thenReturn(mockBuilder);
+ when(mockBuilder.get()).thenThrow(new WebApplicationException("bad gateway"));
+ return mockClient;
+ }
+ };
+
+ HashMap ret = client.connectionTest();
+ Assertions.assertFalse((Boolean) ret.get("connectivityStatus"));
+ Assertions.assertTrue(ret.get("description").toString().contains("bad gateway"));
+ }
+
+ @Test
+ void testConnectionTestGenericExceptionFromGet() {
+ NiFiClient client = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ @Override
+ protected Client buildClient() {
+ Client mockClient = Mockito.mock(Client.class);
+ WebTarget mockWebTarget = Mockito.mock(WebTarget.class);
+ Invocation.Builder mockBuilder = Mockito.mock(Invocation.Builder.class);
+ when(mockClient.target(anyString())).thenReturn(mockWebTarget);
+ when(mockWebTarget.request(any(String.class))).thenReturn(mockBuilder);
+ when(mockBuilder.get()).thenThrow(new IllegalStateException("unexpected"));
+ return mockClient;
+ }
+ };
+
+ HashMap ret = client.connectionTest();
+ Assertions.assertFalse((Boolean) ret.get("connectivityStatus"));
+ Assertions.assertTrue(ret.get("description").toString().contains("unexpected"));
+ }
+
+ @Test
+ void testGetResourcesBlankWhitespaceUserInputReturnsAllIdentifiers() throws Exception {
+ NiFiClient client = newNiFiClientWithMockResourcesResponse(true);
+
+ ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class);
+ when(resourceLookupContext.getUserInput()).thenReturn(" ");
+
+ List resources = client.getResources(resourceLookupContext);
+ Assertions.assertEquals(6, resources.size());
+ }
+
+ @Test
+ void testGetResourcesMalformedJsonThrows() {
+ NiFiClient client = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ @Override
+ protected Client buildClient() {
+ return new MockNiFiClient("not-json", 200).buildClient();
+ }
+ };
+
+ ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class);
+
+ Assertions.assertThrows(Exception.class, () -> client.getResources(resourceLookupContext));
+ }
+
+ @Test
+ void testGetSslContextHostnameVerifierAndUrlWithSslContext() throws Exception {
+ SSLContext sslContext = SSLContext.getDefault();
+ NiFiClient client = new NiFiClient("https://localhost:8443/nifi-api/resources", sslContext) {
+ @Override
+ protected Client buildClient() {
+ return Mockito.mock(Client.class);
+ }
+ };
+
+ Assertions.assertEquals("https://localhost:8443/nifi-api/resources", client.getUrl());
+ Assertions.assertSame(sslContext, client.getSslContext());
+ Assertions.assertNotNull(client.getHostnameVerifier());
+ }
+
+ @Test
+ void testBuildClientInvokesSecureBuilderWhenSslContextNonNull() throws Exception {
+ SSLContext sslContext = SSLContext.getDefault();
+ NiFiClient client = new NiFiClient("https://localhost:8443/nifi-api/resources", sslContext);
+ Assertions.assertNotNull(client);
+ Assertions.assertSame(sslContext, client.getSslContext());
+ }
+
/**
* Extend NiFiClient to return mock responses.
*/
private static final class MockNiFiClient {
- private final int statusCode;
- private final String responseEntity;
+ private final int statusCode;
+ private final String responseEntity;
+ private final boolean stubReadEntityForOkStatus;
+
+ MockNiFiClient(String responseEntity, int statusCode) {
+ this(responseEntity, statusCode, true);
+ }
- public MockNiFiClient(String responseEntity, int statusCode) {
- this.statusCode = statusCode;
- this.responseEntity = responseEntity;
+ MockNiFiClient(String responseEntity, int statusCode, boolean stubReadEntityForOkStatus) {
+ this.statusCode = statusCode;
+ this.responseEntity = responseEntity;
+ this.stubReadEntityForOkStatus = stubReadEntityForOkStatus;
}
- public Client buildClient() {
+ Client buildClient() {
Client mockClient = Mockito.mock(Client.class);
WebTarget mockWebTarget = Mockito.mock(WebTarget.class);
Invocation.Builder mockBuilder = Mockito.mock(Invocation.Builder.class);
@@ -213,7 +344,10 @@ public Client buildClient() {
if (statusCode == 200) {
ongoingStubbing.thenReturn(mockResponse);
when(mockResponse.getStatus()).thenReturn(statusCode);
- when(mockResponse.readEntity(any(Class.class))).thenReturn(new ByteArrayInputStream(responseEntity.getBytes(StandardCharsets.UTF_8)));
+ if (stubReadEntityForOkStatus) {
+ when(mockResponse.readEntity(any(Class.class))).thenReturn(
+ new ByteArrayInputStream(responseEntity.getBytes(StandardCharsets.UTF_8)));
+ }
} else {
ongoingStubbing.thenReturn(mockResponse);
when(mockResponse.getStatus()).thenReturn(statusCode);
diff --git a/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiClientAdditionalScenarios.java b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiClientAdditionalScenarios.java
new file mode 100644
index 00000000000..9c278af45e6
--- /dev/null
+++ b/plugin-nifi/src/test/java/org/apache/ranger/services/nifi/client/TestNiFiClientAdditionalScenarios.java
@@ -0,0 +1,268 @@
+/*
+ * 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.nifi.client;
+
+import org.apache.ranger.plugin.service.ResourceLookupContext;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+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.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for NiFiConfigs
+ */
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+class TestNiFiClientAdditionalScenarios {
+ @Test
+ void connectionTest_nonOkResponse_appendsErrorBodyReadAsInputStream() {
+ NiFiClient client = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ @Override
+ protected Client buildClient() {
+ Client mockClient = Mockito.mock(Client.class);
+ WebTarget mockWebTarget = Mockito.mock(WebTarget.class);
+ Invocation.Builder mockBuilder = Mockito.mock(Invocation.Builder.class);
+ Response mockResponse = Mockito.mock(Response.class);
+ when(mockClient.target(anyString())).thenReturn(mockWebTarget);
+ when(mockWebTarget.request(any(String.class))).thenReturn(mockBuilder);
+ when(mockBuilder.get()).thenReturn(mockResponse);
+ when(mockResponse.getStatus()).thenReturn(502);
+ when(mockResponse.readEntity(java.io.InputStream.class)).thenReturn(
+ new ByteArrayInputStream("upstream failure".getBytes(StandardCharsets.UTF_8)));
+ return mockClient;
+ }
+ };
+
+ HashMap ret = client.connectionTest();
+
+ assertFalse((Boolean) ret.get("connectivityStatus"));
+ assertTrue(ret.get("description").toString().contains("502"));
+ assertTrue(ret.get("description").toString().contains("upstream failure"));
+ }
+
+ @Test
+ void connectionTest_nonOkWhenReadingErrorBodyThrows_stillReportsFailure() {
+ NiFiClient client = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ @Override
+ protected Client buildClient() {
+ Client mockClient = Mockito.mock(Client.class);
+ WebTarget mockWebTarget = Mockito.mock(WebTarget.class);
+ Invocation.Builder mockBuilder = Mockito.mock(Invocation.Builder.class);
+ Response mockResponse = Mockito.mock(Response.class);
+ when(mockClient.target(anyString())).thenReturn(mockWebTarget);
+ when(mockWebTarget.request(any(String.class))).thenReturn(mockBuilder);
+ when(mockBuilder.get()).thenReturn(mockResponse);
+ when(mockResponse.getStatus()).thenReturn(500);
+ when(mockResponse.readEntity(java.io.InputStream.class)).thenThrow(new IllegalStateException("broken stream"));
+ return mockClient;
+ }
+ };
+
+ HashMap ret = client.connectionTest();
+
+ assertFalse((Boolean) ret.get("connectivityStatus"));
+ assertTrue(ret.get("description").toString().contains("broken stream"));
+ }
+
+ @Test
+ void getResources_jsonMissingResourcesNode_throws() throws Exception {
+ String body = "{\"revision\":{\"clientId\":\"x\"}}";
+ NiFiClient client = new NiFiClient("http://localhost:8080/nifi-api/resources", null) {
+ @Override
+ protected Client buildClient() {
+ return mockClientReturningJson(body, 200);
+ }
+ };
+
+ ResourceLookupContext ctx = Mockito.mock(ResourceLookupContext.class);
+
+ assertThrows(Throwable.class, () -> client.getResources(ctx));
+ }
+
+ @Test
+ void hostnameVerifier_firstCertificateNotX509_returnsFalse() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ Certificate plain = Mockito.mock(Certificate.class);
+ when(session.getPeerCertificates()).thenReturn(new Certificate[] {plain});
+
+ assertFalse(verifier.verify("my-host", session));
+ }
+
+ @Test
+ void hostnameVerifier_peerCertificatesEmpty_returnsFalse() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ when(session.getPeerCertificates()).thenReturn(new Certificate[] {});
+
+ assertFalse(verifier.verify("my-host", session));
+ }
+
+ @Test
+ void hostnameVerifier_peerCertificatesNull_returnsFalse() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ when(session.getPeerCertificates()).thenReturn(null);
+
+ assertFalse(verifier.verify("my-host", session));
+ }
+
+ @Test
+ void hostnameVerifier_sslPeerUnverified_returnsFalse() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ when(session.getPeerCertificates()).thenThrow(new SSLPeerUnverifiedException("peer"));
+
+ assertFalse(verifier.verify("my-host", session));
+ }
+
+ @Test
+ void hostnameVerifier_subjectAltParsingFails_returnsFalse() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ X509Certificate cert = Mockito.mock(X509Certificate.class);
+ when(cert.getSubjectAlternativeNames()).thenThrow(new CertificateParsingException("bad san"));
+ when(session.getPeerCertificates()).thenReturn(new Certificate[] {cert});
+
+ assertFalse(verifier.verify("my-host", session));
+ }
+
+ @Test
+ void hostnameVerifier_subjectAltListExcludesHostname_returnsFalse() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ X509Certificate cert = Mockito.mock(X509Certificate.class);
+ List> sans = new ArrayList<>();
+ sans.add(List.of(2, "other.example.com"));
+ when(cert.getSubjectAlternativeNames()).thenReturn(sans);
+ when(session.getPeerCertificates()).thenReturn(new Certificate[] {cert});
+
+ assertFalse(verifier.verify("my-host", session));
+ }
+
+ @Test
+ void hostnameVerifier_subjectAltNullList_hostnameDoesNotMatch_returnsFalse() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ X509Certificate cert = Mockito.mock(X509Certificate.class);
+ when(cert.getSubjectAlternativeNames()).thenReturn(null);
+ when(session.getPeerCertificates()).thenReturn(new Certificate[] {cert});
+
+ assertFalse(verifier.verify("my-host", session));
+ }
+
+ @Test
+ void hostnameVerifier_subjectAltNameMatches_returnsTrue() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ X509Certificate cert = Mockito.mock(X509Certificate.class);
+ List> sans = new ArrayList<>();
+ sans.add(List.of(2, "NiFi.example.COM"));
+ when(cert.getSubjectAlternativeNames()).thenReturn(sans);
+ when(session.getPeerCertificates()).thenReturn(new Certificate[] {cert});
+
+ assertTrue(verifier.verify("nifi.example.com", session));
+ }
+
+ @Test
+ void hostnameVerifier_skipsGeneralNameWhenSecondElementNotString() throws Exception {
+ HostnameVerifier verifier = newHostnameVerifier();
+ SSLSession session = Mockito.mock(SSLSession.class);
+ X509Certificate cert = Mockito.mock(X509Certificate.class);
+ List> sans = new ArrayList<>();
+ List