From 2264f0ba664356231a3c20738fe000aecdf6186a Mon Sep 17 00:00:00 2001 From: Bhavesh Amre Date: Tue, 26 May 2026 14:47:57 +0530 Subject: [PATCH] RANGER-5591:Add unit test cases for plugin-sqoop Module --- plugin-sqoop/pom.xml | 6 + .../authorizer/RangerSqoopAuthorizerTest.java | 163 +++--- .../authorizer/TestRangerSqoopAuthorizer.java | 165 ++++++ .../sqoop/TestRangerServiceSqoop.java | 251 +++++++++ .../sqoop/client/TestSqoopClient.java | 519 ++++++++++++++++++ .../sqoop/client/TestSqoopResourceMgr.java | 254 +++++++++ .../model/TestSqoopConnectorResponse.java | 53 ++ .../model/TestSqoopConnectorsResponse.java | 57 ++ .../json/model/TestSqoopJobResponse.java | 61 ++ .../json/model/TestSqoopJobsResponse.java | 57 ++ .../json/model/TestSqoopLinkResponse.java | 55 ++ .../json/model/TestSqoopLinksResponse.java | 57 ++ 12 files changed, 1629 insertions(+), 69 deletions(-) create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/TestRangerSqoopAuthorizer.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/TestRangerServiceSqoop.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopClient.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopResourceMgr.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorResponse.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorsResponse.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobResponse.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobsResponse.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinkResponse.java create mode 100644 plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinksResponse.java diff --git a/plugin-sqoop/pom.xml b/plugin-sqoop/pom.xml index cf4a99dce44..e9976025e7d 100644 --- a/plugin-sqoop/pom.xml +++ b/plugin-sqoop/pom.xml @@ -217,5 +217,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizerTest.java b/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizerTest.java index aa019632fa0..6eb0480de76 100644 --- a/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizerTest.java +++ b/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizerTest.java @@ -23,6 +23,7 @@ import org.apache.sqoop.core.SqoopConfiguration; import org.apache.sqoop.model.MJob; import org.apache.sqoop.model.MLink; +import org.apache.sqoop.model.MPrincipal; import org.apache.sqoop.repository.Repository; import org.apache.sqoop.repository.RepositoryManager; import org.apache.sqoop.security.AuthorizationManager; @@ -36,6 +37,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -43,6 +45,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +/** + * @generated by Cursor + * @description : Unit Test cases for RangerSqoopAuthorizer + */ + /** * Here we plug the Ranger RangerSqoopAuthorizer into Sqoop. *

@@ -57,7 +64,7 @@ * e) A user "yuwen" can do "read" and "write" on the job "oracle2hdfs-job"; */ @TestMethodOrder(MethodOrderer.MethodName.class) -public class RangerSqoopAuthorizerTest { +class RangerSqoopAuthorizerTest { private static final List allConnectors = new ArrayList<>(); private static final String SQOOP = "sqoop"; @@ -104,7 +111,7 @@ public static void cleanup() throws Exception { * sqoop read all connectors success */ @Test - public void readConnectorAllWithAllPermissions() { + void readConnectorAllWithAllPermissions() { String user = SQOOP; for (String connector : allConnectors) { AuthorizationEngine.readConnector(user, connector); @@ -115,7 +122,7 @@ public void readConnectorAllWithAllPermissions() { * zhangqiang read kafka-connector success */ @Test - public void readConnectorKafkaWithReadPermission() { + void readConnectorKafkaWithReadPermission() { String user = ZHANGQIANG; String connector = KAFKA_CONNECTOR; AuthorizationEngine.readConnector(user, connector); @@ -125,7 +132,7 @@ public void readConnectorKafkaWithReadPermission() { * zhangqiang read hdfs-connector failed */ @Test - public void readConnectorHdfsWithoutPermission() { + void readConnectorHdfsWithoutPermission() { String user = ZHANGQIANG; String connector = HDFS_CONNECTOR; assertThrows(SqoopException.class, () -> AuthorizationEngine.readConnector(user, connector)); @@ -135,7 +142,7 @@ public void readConnectorHdfsWithoutPermission() { * yuwen read oracle-jdbc-connector success */ @Test - public void readConnectorOracleJdbcWithAllPermissions() { + void readConnectorOracleJdbcWithAllPermissions() { String user = YUWEN; String connector = ORACLE_JDBC_CONNECTOR; AuthorizationEngine.readConnector(user, connector); @@ -147,7 +154,7 @@ public void readConnectorOracleJdbcWithAllPermissions() { * yuwen read hdfs-connector success */ @Test - public void readConnectorHdfsWithAllPermissions() { + void readConnectorHdfsWithAllPermissions() { String user = YUWEN; String connector = HDFS_CONNECTOR; AuthorizationEngine.readConnector(user, connector); @@ -157,7 +164,7 @@ public void readConnectorHdfsWithAllPermissions() { * yuwen read kafka-connector failed */ @Test - public void readConnectorKafkaWithoutPermission() { + void readConnectorKafkaWithoutPermission() { String user = YUWEN; String connector = KAFKA_CONNECTOR; assertThrows(SqoopException.class, () -> AuthorizationEngine.readConnector(user, connector)); @@ -167,7 +174,7 @@ public void readConnectorKafkaWithoutPermission() { * sqoop read any link success */ @Test - public void readLinkAnyWithAllPermissions() { + void readLinkAnyWithAllPermissions() { String user = SQOOP; String link = getRandomLinkName(); AuthorizationEngine.readLink(user, link); @@ -177,7 +184,7 @@ public void readLinkAnyWithAllPermissions() { * zhangqiang read any link success */ @Test - public void readLinkAnyAsCreater() { + void readLinkAnyAsCreater() { String user = ZHANGQIANG; String link = getRandomLinkName(); AuthorizationEngine.readLink(user, link); @@ -187,7 +194,7 @@ public void readLinkAnyAsCreater() { * yuwen read oracle-link success */ @Test - public void readLinkOracleWithReadPermission() { + void readLinkOracleWithReadPermission() { String user = YUWEN; String link = ORACLE_LINK; AuthorizationEngine.readLink(user, link); @@ -197,7 +204,7 @@ public void readLinkOracleWithReadPermission() { * yuwen read hdfs-link success */ @Test - public void readLinkHdfsWithReadPermission() { + void readLinkHdfsWithReadPermission() { String user = YUWEN; String link = HDFS_LINK; AuthorizationEngine.readLink(user, link); @@ -211,7 +218,7 @@ public void readLinkHdfsWithReadPermission() { * yuwen read any link failed */ @Test - public void readLinkAnyWithoutPermission() { + void readLinkAnyWithoutPermission() { String user = YUWEN; String link = getRandomLinkName(); assertThrows(SqoopException.class, () -> AuthorizationEngine.readLink(user, link)); @@ -221,7 +228,7 @@ public void readLinkAnyWithoutPermission() { * sqoop create link by all connectors success */ @Test - public void createLinkByAllConnectorsWithAllPermissions() { + void createLinkByAllConnectorsWithAllPermissions() { String user = SQOOP; for (String connector : allConnectors) { AuthorizationEngine.createLink(user, connector); @@ -232,7 +239,7 @@ public void createLinkByAllConnectorsWithAllPermissions() { * zhangqiang create link by kafka-connector success */ @Test - public void createLinkByKafkaConnectorWithReadPermission() { + void createLinkByKafkaConnectorWithReadPermission() { String user = ZHANGQIANG; String connector = KAFKA_CONNECTOR; AuthorizationEngine.createLink(user, connector); @@ -242,7 +249,7 @@ public void createLinkByKafkaConnectorWithReadPermission() { * zhangqiang create link by hdfs-connector failed */ @Test - public void createLinkByHdfsConnectorWithoutPermission() { + void createLinkByHdfsConnectorWithoutPermission() { String user = ZHANGQIANG; String connector = HDFS_CONNECTOR; assertThrows(SqoopException.class, () -> AuthorizationEngine.createLink(user, connector)); @@ -252,7 +259,7 @@ public void createLinkByHdfsConnectorWithoutPermission() { * yuwen create link by oracle-jdbc-connector success */ @Test - public void createLinkByOracleJdbcConnectorWithReadPermission() { + void createLinkByOracleJdbcConnectorWithReadPermission() { String user = YUWEN; String connector = ORACLE_JDBC_CONNECTOR; AuthorizationEngine.createLink(user, connector); @@ -266,7 +273,7 @@ public void createLinkByOracleJdbcConnectorWithReadPermission() { * yuwen create link by hdfs-connector success */ @Test - public void createLinkByHdfsConnectorWithReadPermission() { + void createLinkByHdfsConnectorWithReadPermission() { String user = YUWEN; String connector = HDFS_CONNECTOR; AuthorizationEngine.createLink(user, connector); @@ -276,7 +283,7 @@ public void createLinkByHdfsConnectorWithReadPermission() { * yuwen create link by kafka-connector failed */ @Test - public void createLinkByKafkaConnectorWithoutPermission() { + void createLinkByKafkaConnectorWithoutPermission() { String user = YUWEN; String connector = KAFKA_CONNECTOR; assertThrows(SqoopException.class, () -> AuthorizationEngine.createLink(user, connector)); @@ -286,7 +293,7 @@ public void createLinkByKafkaConnectorWithoutPermission() { * sqoop update any link created by all connectors success */ @Test - public void updateLinkAnyByAllConnectorsWithAllPermissions() { + void updateLinkAnyByAllConnectorsWithAllPermissions() { String user = SQOOP; for (String connector : allConnectors) { String link = getRandomLinkName(); @@ -298,7 +305,7 @@ public void updateLinkAnyByAllConnectorsWithAllPermissions() { * zhangqiang update any link created by kafka-connector success */ @Test - public void updateLinkAnyByKafkaConnectorAsCreater() { + void updateLinkAnyByKafkaConnectorAsCreater() { String user = ZHANGQIANG; String connector = KAFKA_CONNECTOR; String link = getRandomLinkName(); @@ -309,7 +316,7 @@ public void updateLinkAnyByKafkaConnectorAsCreater() { * zhangqiang update any link created by hdfs-connector failed */ @Test - public void updateLinkAnyByHdfsConnectorWithoutPermission() { + void updateLinkAnyByHdfsConnectorWithoutPermission() { String user = ZHANGQIANG; String connector = HDFS_CONNECTOR; String link = getRandomLinkName(); @@ -320,7 +327,7 @@ public void updateLinkAnyByHdfsConnectorWithoutPermission() { * yuwen update link created by oracle-jdbc-connector success */ @Test - public void updateLinkByOracleJdbcConnectorWithWritePermission() { + void updateLinkByOracleJdbcConnectorWithWritePermission() { String user = YUWEN; String connector = ORACLE_JDBC_CONNECTOR; String link = ORACLE_LINK; @@ -335,7 +342,7 @@ public void updateLinkByOracleJdbcConnectorWithWritePermission() { * yuwen update link created by hdfs-connector success */ @Test - public void updateLinkByHdfsConnectorWithReadPermission() { + void updateLinkByHdfsConnectorWithReadPermission() { String user = YUWEN; String connector = HDFS_CONNECTOR; String link = HDFS_LINK; @@ -346,7 +353,7 @@ public void updateLinkByHdfsConnectorWithReadPermission() { * yuwen update link created by kafka-connector failed */ @Test - public void updateLinkByKafkaConnectorWithoutPermission() { + void updateLinkByKafkaConnectorWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String connector = KAFKA_CONNECTOR; @@ -359,7 +366,7 @@ public void updateLinkByKafkaConnectorWithoutPermission() { * sqoop delete any link success */ @Test - public void deleteLinkAnyWithAllPermissions() { + void deleteLinkAnyWithAllPermissions() { String user = SQOOP; String link = getRandomLinkName(); AuthorizationEngine.deleteLink(user, link); @@ -369,7 +376,7 @@ public void deleteLinkAnyWithAllPermissions() { * zhangqiang delete any link success */ @Test - public void deleteLinkAnyAsCreater() { + void deleteLinkAnyAsCreater() { String user = ZHANGQIANG; String link = getRandomLinkName(); AuthorizationEngine.deleteLink(user, link); @@ -379,7 +386,7 @@ public void deleteLinkAnyAsCreater() { * yuwen delete oracle-link success */ @Test - public void deleteLinkOracleWithWritePermission() { + void deleteLinkOracleWithWritePermission() { String user = YUWEN; String link = ORACLE_LINK; AuthorizationEngine.deleteLink(user, link); @@ -389,7 +396,7 @@ public void deleteLinkOracleWithWritePermission() { * yuwen delete hdfs-link success */ @Test - public void deleteLinkHdfsWithWritePermission() { + void deleteLinkHdfsWithWritePermission() { String user = YUWEN; String link = HDFS_LINK; AuthorizationEngine.deleteLink(user, link); @@ -403,7 +410,7 @@ public void deleteLinkHdfsWithWritePermission() { * yuwen delete any link failed */ @Test - public void deleteLinkAnyWithoutPermission() { + void deleteLinkAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String link = getRandomLinkName(); @@ -415,7 +422,7 @@ public void deleteLinkAnyWithoutPermission() { * sqoop enable disable any link success */ @Test - public void enableDisableLinkAnyWithAllPermissions() { + void enableDisableLinkAnyWithAllPermissions() { String user = SQOOP; String link = getRandomLinkName(); AuthorizationEngine.enableDisableLink(user, link); @@ -425,7 +432,7 @@ public void enableDisableLinkAnyWithAllPermissions() { * zhangqiang enable disable any link success */ @Test - public void enableDisableLinkAnyAsCreater() { + void enableDisableLinkAnyAsCreater() { String user = ZHANGQIANG; String link = getRandomLinkName(); AuthorizationEngine.enableDisableLink(user, link); @@ -435,7 +442,7 @@ public void enableDisableLinkAnyAsCreater() { * yuwen enable disable oracle-link success */ @Test - public void enableDisableLinkOracleWithWritePermission() { + void enableDisableLinkOracleWithWritePermission() { String user = YUWEN; String link = ORACLE_LINK; AuthorizationEngine.enableDisableLink(user, link); @@ -445,7 +452,7 @@ public void enableDisableLinkOracleWithWritePermission() { * yuwen enable disable hdfs-link success */ @Test - public void enableDisableLinkHdfsWithWritePermission() { + void enableDisableLinkHdfsWithWritePermission() { String user = YUWEN; String link = HDFS_LINK; AuthorizationEngine.enableDisableLink(user, link); @@ -459,7 +466,7 @@ public void enableDisableLinkHdfsWithWritePermission() { * yuwen enable disable any link failed */ @Test - public void enableDisableLinkAnyWithoutPermission() { + void enableDisableLinkAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String link = getRandomLinkName(); @@ -471,7 +478,7 @@ public void enableDisableLinkAnyWithoutPermission() { * sqoop read any job success */ @Test - public void readJobAnyWithAllPermissions() { + void readJobAnyWithAllPermissions() { String user = SQOOP; String job = getRandomJobName(); AuthorizationEngine.readJob(user, job); @@ -481,7 +488,7 @@ public void readJobAnyWithAllPermissions() { * zhangqiang read any job success */ @Test - public void readJobAnyAsCreater() { + void readJobAnyAsCreater() { String user = ZHANGQIANG; String job = getRandomJobName(); AuthorizationEngine.readJob(user, job); @@ -491,7 +498,7 @@ public void readJobAnyAsCreater() { * yuwen read oracle2hdfs-job success */ @Test - public void readJobOracle2HdfsWithReadPermission() { + void readJobOracle2HdfsWithReadPermission() { String user = YUWEN; String job = ORACLE2HDFS_JOB; AuthorizationEngine.readJob(user, job); @@ -501,7 +508,7 @@ public void readJobOracle2HdfsWithReadPermission() { * yuwen read any job failed */ @Test - public void readJobAnyWithoutPermission() { + void readJobAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String job = getRandomJobName(); @@ -517,7 +524,7 @@ public void readJobAnyWithoutPermission() { * sqoop create job by any two links success */ @Test - public void createJobByAnyTwoLinksWithAllPermissions() { + void createJobByAnyTwoLinksWithAllPermissions() { String user = SQOOP; String link1 = getRandomLinkName(); String link2 = getRandomLinkName(); @@ -528,7 +535,7 @@ public void createJobByAnyTwoLinksWithAllPermissions() { * zhangqiang create job by any two links success */ @Test - public void createJobByAnyTwoLinksAsCreater() { + void createJobByAnyTwoLinksAsCreater() { String user = ZHANGQIANG; String link1 = getRandomLinkName(); String link2 = getRandomLinkName(); @@ -539,7 +546,7 @@ public void createJobByAnyTwoLinksAsCreater() { * yuwen create job from oracle-link to hdfs-link success */ @Test - public void createJobFromOracle2HdfsLinkWithReadPermission() { + void createJobFromOracle2HdfsLinkWithReadPermission() { String user = YUWEN; String link1 = ORACLE_LINK; String link2 = HDFS_LINK; @@ -550,7 +557,7 @@ public void createJobFromOracle2HdfsLinkWithReadPermission() { * yuwen create job from oracle-link to any link failed */ @Test - public void createJobFromOracle2AnyLinkWithoutPermission() { + void createJobFromOracle2AnyLinkWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String link1 = ORACLE_LINK; @@ -567,7 +574,7 @@ public void createJobFromOracle2AnyLinkWithoutPermission() { * yuwen create job by any two links failed */ @Test - public void createJobByAnyTwoLinksWithoutPermission() { + void createJobByAnyTwoLinksWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String link1 = getRandomLinkName(); @@ -580,7 +587,7 @@ public void createJobByAnyTwoLinksWithoutPermission() { * sqoop update any job created by any two links success */ @Test - public void updateJobAnyByAnyTwoLinksWithAllPermissions() { + void updateJobAnyByAnyTwoLinksWithAllPermissions() { String user = SQOOP; String link1 = getRandomLinkName(); String link2 = getRandomLinkName(); @@ -592,7 +599,7 @@ public void updateJobAnyByAnyTwoLinksWithAllPermissions() { * zhangqiang update any job created by any two links success */ @Test - public void updateJobAnyByAnyTwoLinksAsCreater() { + void updateJobAnyByAnyTwoLinksAsCreater() { String user = ZHANGQIANG; String link1 = getRandomLinkName(); String link2 = getRandomLinkName(); @@ -605,7 +612,7 @@ public void updateJobAnyByAnyTwoLinksAsCreater() { * success */ @Test - public void updateJobOracle2HdfsByTwoLinksWithWritePermission() { + void updateJobOracle2HdfsByTwoLinksWithWritePermission() { String user = YUWEN; String link1 = ORACLE_LINK; String link2 = HDFS_LINK; @@ -618,7 +625,7 @@ public void updateJobOracle2HdfsByTwoLinksWithWritePermission() { * failed */ @Test - public void updateJobOracle2HdfsByTwoLinksWithoutPermission() { + void updateJobOracle2HdfsByTwoLinksWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String link1 = "new_" + ORACLE_LINK; @@ -636,7 +643,7 @@ public void updateJobOracle2HdfsByTwoLinksWithoutPermission() { * yuwen update any job created from oracle-link to hdfs-link failed */ @Test - public void updateJobAnyByTwoLinksWithoutPermission() { + void updateJobAnyByTwoLinksWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String link1 = ORACLE_LINK; @@ -650,7 +657,7 @@ public void updateJobAnyByTwoLinksWithoutPermission() { * yuwen update any job created from oracle-link to hdfs-link failed */ @Test - public void updateJobAnyByAnyLinksWithoutPermission() { + void updateJobAnyByAnyLinksWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String link1 = getRandomLinkName(); @@ -664,7 +671,7 @@ public void updateJobAnyByAnyLinksWithoutPermission() { * sqoop delete any job success */ @Test - public void deleteJobAnyWithAllPermissions() { + void deleteJobAnyWithAllPermissions() { String user = SQOOP; String job = getRandomJobName(); AuthorizationEngine.deleteJob(user, job); @@ -674,7 +681,7 @@ public void deleteJobAnyWithAllPermissions() { * zhangqiang delete any job success */ @Test - public void deleteJobAnyAsCreater() { + void deleteJobAnyAsCreater() { String user = ZHANGQIANG; String job = getRandomJobName(); AuthorizationEngine.deleteJob(user, job); @@ -684,7 +691,7 @@ public void deleteJobAnyAsCreater() { * yuwen delete oracle2hdfs-job success */ @Test - public void deleteJobOracle2HdfsWithWritePermission() { + void deleteJobOracle2HdfsWithWritePermission() { String user = YUWEN; String job = ORACLE2HDFS_JOB; AuthorizationEngine.deleteJob(user, job); @@ -694,7 +701,7 @@ public void deleteJobOracle2HdfsWithWritePermission() { * yuwen delete any job failed */ @Test - public void deleteJobAnyWithoutPermission() { + void deleteJobAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String job = getRandomJobName(); @@ -710,7 +717,7 @@ public void deleteJobAnyWithoutPermission() { * sqoop enable disable any job success */ @Test - public void enableDisableJobAnyWithAllPermissions() { + void enableDisableJobAnyWithAllPermissions() { String user = SQOOP; String job = getRandomJobName(); AuthorizationEngine.enableDisableJob(user, job); @@ -720,7 +727,7 @@ public void enableDisableJobAnyWithAllPermissions() { * zhangqiang enable disable any job success */ @Test - public void enableDisableJobAnyAsCreater() { + void enableDisableJobAnyAsCreater() { String user = ZHANGQIANG; String job = getRandomJobName(); AuthorizationEngine.enableDisableJob(user, job); @@ -730,7 +737,7 @@ public void enableDisableJobAnyAsCreater() { * yuwen enable disable oracle2hdfs-job success */ @Test - public void enableDisableJobOracle2HdfsWithWritePermission() { + void enableDisableJobOracle2HdfsWithWritePermission() { String user = YUWEN; String job = ORACLE2HDFS_JOB; AuthorizationEngine.enableDisableJob(user, job); @@ -740,7 +747,7 @@ public void enableDisableJobOracle2HdfsWithWritePermission() { * yuwen enable disable any job failed */ @Test - public void enableDisableJobAnyWithoutPermission() { + void enableDisableJobAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String job = getRandomJobName(); @@ -756,7 +763,7 @@ public void enableDisableJobAnyWithoutPermission() { * sqoop start any job success */ @Test - public void startJobAnyWithAllPermissions() { + void startJobAnyWithAllPermissions() { String user = SQOOP; String job = getRandomJobName(); AuthorizationEngine.startJob(user, job); @@ -766,7 +773,7 @@ public void startJobAnyWithAllPermissions() { * zhangqiang start any job success */ @Test - public void startJobAnyAsCreater() { + void startJobAnyAsCreater() { String user = ZHANGQIANG; String job = getRandomJobName(); AuthorizationEngine.startJob(user, job); @@ -776,7 +783,7 @@ public void startJobAnyAsCreater() { * yuwen start oracle2hdfs-job success */ @Test - public void startJobOracle2HdfsWithWritePermission() { + void startJobOracle2HdfsWithWritePermission() { String user = YUWEN; String job = ORACLE2HDFS_JOB; AuthorizationEngine.startJob(user, job); @@ -786,7 +793,7 @@ public void startJobOracle2HdfsWithWritePermission() { * yuwen start any job failed */ @Test - public void startJobAnyWithoutPermission() { + void startJobAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String job = getRandomJobName(); @@ -802,7 +809,7 @@ public void startJobAnyWithoutPermission() { * sqoop stop any job success */ @Test - public void stopJobAnyWithAllPermissions() { + void stopJobAnyWithAllPermissions() { String user = SQOOP; String job = getRandomJobName(); AuthorizationEngine.stopJob(user, job); @@ -812,7 +819,7 @@ public void stopJobAnyWithAllPermissions() { * zhangqiang start any job success */ @Test - public void stopJobAnyAsCreater() { + void stopJobAnyAsCreater() { String user = ZHANGQIANG; String job = getRandomJobName(); AuthorizationEngine.stopJob(user, job); @@ -822,7 +829,7 @@ public void stopJobAnyAsCreater() { * yuwen stop oracle2hdfs-job success */ @Test - public void stopJobOracle2HdfsWithWritePermission() { + void stopJobOracle2HdfsWithWritePermission() { String user = YUWEN; String job = ORACLE2HDFS_JOB; AuthorizationEngine.stopJob(user, job); @@ -832,7 +839,7 @@ public void stopJobOracle2HdfsWithWritePermission() { * yuwen stop any job failed */ @Test - public void stopJobAnyWithoutPermission() { + void stopJobAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String job = getRandomJobName(); @@ -848,7 +855,7 @@ public void stopJobAnyWithoutPermission() { * sqoop status any job success */ @Test - public void statusJobAnyWithAllPermissions() { + void statusJobAnyWithAllPermissions() { String user = SQOOP; String job = getRandomJobName(); AuthorizationEngine.statusJob(user, job); @@ -858,7 +865,7 @@ public void statusJobAnyWithAllPermissions() { * zhangqiang status any job success */ @Test - public void statusJobAnyAsCreater() { + void statusJobAnyAsCreater() { String user = ZHANGQIANG; String job = getRandomJobName(); AuthorizationEngine.statusJob(user, job); @@ -868,7 +875,7 @@ public void statusJobAnyAsCreater() { * yuwen status oracle2hdfs-job success */ @Test - public void statusJobOracle2HdfsWithReadPermission() { + void statusJobOracle2HdfsWithReadPermission() { String user = YUWEN; String job = ORACLE2HDFS_JOB; AuthorizationEngine.statusJob(user, job); @@ -878,7 +885,7 @@ public void statusJobOracle2HdfsWithReadPermission() { * yuwen status status job failed */ @Test - public void statusJobAnyWithoutPermission() { + void statusJobAnyWithoutPermission() { assertThrows(SqoopException.class, () -> { String user = YUWEN; String job = getRandomJobName(); @@ -949,4 +956,22 @@ private String getRandomJobName() { } // No.14 statusJob test end + + /** + * Verifies empty privilege collections short-circuit before policy evaluation. + */ + @Test + void rangerAuthorizerCheckPrivilegesWithEmptyPrivilegeCollectionReturnsImmediately() { + RangerSqoopAuthorizer authorizer = new RangerSqoopAuthorizer(); + authorizer.checkPrivileges(mock(MPrincipal.class), Collections.emptyList()); + } + + /** + * Verifies null privilege collections are treated as empty input. + */ + @Test + void rangerAuthorizerCheckPrivilegesWithNullPrivilegeCollectionReturnsImmediately() { + RangerSqoopAuthorizer authorizer = new RangerSqoopAuthorizer(); + authorizer.checkPrivileges(mock(MPrincipal.class), null); + } } diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/TestRangerSqoopAuthorizer.java b/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/TestRangerSqoopAuthorizer.java new file mode 100644 index 00000000000..cab645c8428 --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/TestRangerSqoopAuthorizer.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.authorization.sqoop.authorizer; + +import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl; +import org.apache.ranger.services.sqoop.client.SqoopResourceMgr; +import org.apache.sqoop.model.MPrincipal; +import org.apache.sqoop.model.MPrivilege; +import org.apache.sqoop.model.MResource; +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.Constructor; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @generated by Cursor + * @description : Unit Test cases for RangerSqoopAuthorizer + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestRangerSqoopAuthorizer { + @Test + void testCheckPrivilegesPositiveSkipsPolicyEvaluationWhenPluginUnset() throws Exception { + RangerSqoopAuthorizer auth = new RangerSqoopAuthorizer(); + Field pluginField = RangerSqoopAuthorizer.class.getDeclaredField("sqoopPlugin"); + pluginField.setAccessible(true); + Object previous = pluginField.get(null); + try { + pluginField.set(null, null); + MPrivilege privilege = mock(MPrivilege.class); + MPrincipal principal = mock(MPrincipal.class); + List privileges = Collections.singletonList(privilege); + auth.checkPrivileges(principal, privileges); + } finally { + pluginField.set(null, previous); + if (pluginField.get(null) == null) { + new RangerSqoopAuthorizer(); + } + } + } + + @Test + void testRangerSqoopAccessRequestPositiveHandlesGroupPrincipal() throws Exception { + Class clazz = Class.forName(RangerSqoopAuthorizer.class.getName() + "$RangerSqoopAccessRequest"); + Constructor ctor = clazz.getDeclaredConstructor(MPrincipal.class, MPrivilege.class, String.class); + ctor.setAccessible(true); + + MPrincipal principal = mock(MPrincipal.class); + MPrivilege privilege = mock(MPrivilege.class); + MResource resource = mock(MResource.class); + + when(principal.getType()).thenReturn(MPrincipal.TYPE.GROUP.name()); + when(principal.getName()).thenReturn("admins"); + when(privilege.getResource()).thenReturn(resource); + when(privilege.getAction()).thenReturn("READ"); + when(resource.getType()).thenReturn(MResource.TYPE.JOB.name()); + when(resource.getName()).thenReturn("etl-job"); + + Object request = ctor.newInstance(principal, privilege, "192.168.1.10"); + + assertNotNull(request); + } + + @Test + void testRangerSqoopAccessRequestPositiveHandlesUserPrincipal() throws Exception { + Class clazz = Class.forName(RangerSqoopAuthorizer.class.getName() + "$RangerSqoopAccessRequest"); + Constructor ctor = clazz.getDeclaredConstructor(MPrincipal.class, MPrivilege.class, String.class); + ctor.setAccessible(true); + + MPrincipal principal = mock(MPrincipal.class); + MPrivilege privilege = mock(MPrivilege.class); + MResource resource = mock(MResource.class); + + when(principal.getType()).thenReturn(MPrincipal.TYPE.USER.name()); + when(principal.getName()).thenReturn("alice"); + when(privilege.getResource()).thenReturn(resource); + when(privilege.getAction()).thenReturn("WRITE"); + when(resource.getType()).thenReturn(MResource.TYPE.CONNECTOR.name()); + when(resource.getName()).thenReturn("jdbc"); + + Object request = ctor.newInstance(principal, privilege, "10.0.0.2"); + + assertNotNull(request); + } + + @Test + void testRangerSqoopResourcePositiveRegistersConnectorLinkJobAttributes() throws Exception { + Class clazz = Class.forName(RangerSqoopAuthorizer.class.getName() + "$RangerSqoopResource"); + Constructor ctor = clazz.getDeclaredConstructor(MResource.class); + ctor.setAccessible(true); + + MResource connector = mock(MResource.class); + when(connector.getType()).thenReturn(MResource.TYPE.CONNECTOR.name()); + when(connector.getName()).thenReturn("c1"); + RangerAccessResourceImpl resConnector = (RangerAccessResourceImpl) ctor.newInstance(connector); + assertNotNull(resConnector.getValue(SqoopResourceMgr.CONNECTOR)); + + MResource link = mock(MResource.class); + when(link.getType()).thenReturn(MResource.TYPE.LINK.name()); + when(link.getName()).thenReturn("l1"); + RangerAccessResourceImpl resLink = (RangerAccessResourceImpl) ctor.newInstance(link); + assertNotNull(resLink.getValue(SqoopResourceMgr.LINK)); + + MResource job = mock(MResource.class); + when(job.getType()).thenReturn(MResource.TYPE.JOB.name()); + when(job.getName()).thenReturn("j1"); + RangerAccessResourceImpl resJob = (RangerAccessResourceImpl) ctor.newInstance(job); + assertNotNull(resJob.getValue(SqoopResourceMgr.JOB)); + } + + @Test + void testInitPositiveSecondCallIsNoOpWhenPluginAlreadyLoaded() { + RangerSqoopAuthorizer auth = new RangerSqoopAuthorizer(); + assertDoesNotThrow(auth::init); + } + + @Test + void testInitUsesSafeDefaultsWhenInetAddressLookupFails() throws Exception { + Field pluginField = RangerSqoopAuthorizer.class.getDeclaredField("sqoopPlugin"); + pluginField.setAccessible(true); + Object previous = pluginField.get(null); + try { + pluginField.set(null, null); + try (MockedStatic inet = mockStatic(InetAddress.class)) { + inet.when(InetAddress::getLocalHost).thenThrow(new UnknownHostException("missing-host")); + assertDoesNotThrow(() -> new RangerSqoopAuthorizer()); + } + } finally { + pluginField.set(null, previous); + if (pluginField.get(null) == null) { + new RangerSqoopAuthorizer(); + } + } + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/TestRangerServiceSqoop.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/TestRangerServiceSqoop.java new file mode 100644 index 00000000000..ffd3da91fba --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/TestRangerServiceSqoop.java @@ -0,0 +1,251 @@ +/* + * 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.sqoop; + +import org.apache.ranger.plugin.client.BaseClient; +import org.apache.ranger.plugin.model.RangerService; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.apache.ranger.services.sqoop.client.SqoopClient; +import org.apache.ranger.services.sqoop.client.SqoopResourceMgr; +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.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.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.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @generated by Cursor + * @description : Unit Test cases for RangerServiceSqoop + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestRangerServiceSqoop { + @Test + void testConstructorCreatesDistinctInstances() { + RangerServiceSqoop first = new RangerServiceSqoop(); + RangerServiceSqoop second = new RangerServiceSqoop(); + assertNotNull(first); + assertNotNull(second); + assertNotSame(first, second); + } + + @Test + void testConstructorProducesNonNullServiceHandle() { + assertNotNull(new RangerServiceSqoop()); + } + + @Test + void testInitPropagatesConfigurationFromRangerService() { + RangerServiceSqoop svc = new RangerServiceSqoop(); + RangerServiceDef def = mock(RangerServiceDef.class); + RangerService rs = mock(RangerService.class); + Map cfgs = new HashMap<>(); + cfgs.put("sqoop.url", "http://127.0.0.1:1"); + cfgs.put("username", "integration-user"); + + when(rs.getConfigs()).thenReturn(cfgs); + when(rs.getName()).thenReturn("sqoop-test"); + + svc.init(def, rs); + + assertNotNull(svc.getConfigs()); + assertTrue(svc.getConfigs().containsKey("sqoop.url")); + assertFalse(svc.getConfigs().isEmpty()); + } + + @Test + void testInitFailsWhenServiceThrowsWhileReadingMetadata() { + RangerServiceSqoop svc = new RangerServiceSqoop(); + RangerServiceDef def = mock(RangerServiceDef.class); + RangerService rs = mock(RangerService.class); + + when(rs.getConfigs()).thenThrow(new RuntimeException("simulated failure")); + + assertThrows(RuntimeException.class, () -> svc.init(def, rs)); + } + + @Test + void testValidateConfigWhenConfigsNullReturnsEmptyResultMap() throws Exception { + RangerServiceSqoop svc = new RangerServiceSqoop(); + + Map result = svc.validateConfig(); + + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + void testValidateConfigWhenConfigsPresentReturnsConnectivityPayload() throws Exception { + RangerServiceSqoop svc = new RangerServiceSqoop(); + RangerServiceDef def = mock(RangerServiceDef.class); + RangerService rs = mock(RangerService.class); + Map cfgs = new HashMap<>(); + cfgs.put("sqoop.url", "http://127.0.0.1:1"); + cfgs.put("username", "integration-user"); + + when(rs.getConfigs()).thenReturn(cfgs); + when(rs.getName()).thenReturn("sqoop-test"); + + svc.init(def, rs); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.connectionTest(anyString(), any())).thenAnswer(invocation -> { + Map responseData = new HashMap<>(); + BaseClient.generateResponseDataMap(true, "ok", "ok", null, null, responseData); + return responseData; + }); + + Map result = svc.validateConfig(); + + assertNotNull(result); + assertTrue(Boolean.TRUE.equals(result.get("connectivityStatus"))); + } + } + + @Test + void testLookupResourceWhenContextNullReturnsEmptyList() { + RangerServiceSqoop svc = new RangerServiceSqoop(); + + List names = svc.lookupResource(null); + + assertNotNull(names); + assertTrue(names.isEmpty()); + } + + @Test + void testLookupResourceWhenContextPresentReturnsResourceNamesOrEmpty() { + RangerServiceSqoop svc = new RangerServiceSqoop(); + RangerServiceDef def = mock(RangerServiceDef.class); + RangerService rs = mock(RangerService.class); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + Map cfgs = new HashMap<>(); + cfgs.put("sqoop.url", "http://127.0.0.1:1"); + cfgs.put("username", "integration-user"); + + when(rs.getConfigs()).thenReturn(cfgs); + when(rs.getName()).thenReturn("sqoop-test"); + when(ctx.getUserInput()).thenReturn("pre"); + when(ctx.getResourceName()).thenReturn(SqoopResourceMgr.CONNECTOR); + when(ctx.getResources()).thenReturn(Collections.singletonMap( + SqoopResourceMgr.CONNECTOR, + Collections.emptyList())); + + svc.init(def, rs); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenAnswer(invocation -> { + String serviceName = invocation.getArgument(0); + Map cfg = invocation.getArgument(1); + return new SqoopClient(serviceName, cfg) { + @Override + protected Subject getLoginSubject() { + return null; + } + }; + }); + + List names = svc.lookupResource(ctx); + + assertNotNull(names); + assertTrue(names.isEmpty()); + } + } + + @Test + void testLookupResourceNegativePropagatesWhenResourceLookupFails() { + RangerServiceSqoop svc = new RangerServiceSqoop(); + RangerServiceDef def = mock(RangerServiceDef.class); + RangerService rs = mock(RangerService.class); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + Map cfgs = new HashMap<>(); + cfgs.put("sqoop.url", "http://localhost"); + cfgs.put("username", "u"); + when(rs.getConfigs()).thenReturn(cfgs); + when(rs.getName()).thenReturn("svc-name"); + svc.init(def, rs); + + try (MockedStatic mocked = mockStatic(SqoopResourceMgr.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopResourceMgr.getSqoopResources(anyString(), any(), any())) + .thenThrow(new IllegalStateException("lookup failure")); + + assertThrows(IllegalStateException.class, () -> svc.lookupResource(ctx)); + } + } + + @Test + void testLookupResourcePositiveAllowsNullResultFromDelegate() { + RangerServiceSqoop svc = new RangerServiceSqoop(); + RangerServiceDef def = mock(RangerServiceDef.class); + RangerService rs = mock(RangerService.class); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + Map cfgs = new HashMap<>(); + cfgs.put("sqoop.url", "http://localhost"); + cfgs.put("username", "u"); + when(rs.getConfigs()).thenReturn(cfgs); + when(rs.getName()).thenReturn("svc-name"); + svc.init(def, rs); + + try (MockedStatic mocked = mockStatic(SqoopResourceMgr.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopResourceMgr.getSqoopResources(anyString(), any(), any())).thenReturn(null); + + assertNull(svc.lookupResource(ctx)); + } + } + + @Test + void testValidateConfigNegativePropagatesWhenResourceMgrFails() throws Exception { + RangerServiceSqoop svc = new RangerServiceSqoop(); + RangerServiceDef def = mock(RangerServiceDef.class); + RangerService rs = mock(RangerService.class); + Map cfgs = new HashMap<>(); + cfgs.put("sqoop.url", "http://localhost"); + cfgs.put("username", "u"); + when(rs.getConfigs()).thenReturn(cfgs); + when(rs.getName()).thenReturn("svc-name"); + svc.init(def, rs); + + try (MockedStatic mocked = mockStatic(SqoopResourceMgr.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopResourceMgr.validateConfig(anyString(), any())) + .thenThrow(new UnsupportedOperationException("bad")); + + assertThrows(UnsupportedOperationException.class, () -> svc.validateConfig()); + } + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopClient.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopClient.java new file mode 100644 index 00000000000..97fb5b48e0f --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopClient.java @@ -0,0 +1,519 @@ +/* + * 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.sqoop.client; + +import org.apache.http.HttpStatus; +import org.apache.ranger.plugin.client.HadoopException; +import org.apache.ranger.plugin.util.RangerJersey2ClientBuilder; +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 org.mockito.stubbing.OngoingStubbing; + +import javax.security.auth.Subject; +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; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +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.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.CALLS_REAL_METHODS; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopClient + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopClient { + private Map minimalReachableConfiguration() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://127.0.0.1:1"); + configs.put("username", "integration-user"); + return configs; + } + + private SqoopClient clientSkippingRemoteCalls(String serviceName, Map configs) { + return new SqoopClient(serviceName, configs) { + @Override + protected Subject getLoginSubject() { + return null; + } + }; + } + + private SqoopClient clientWithSubject(String serviceName, Map configs) { + return new SqoopClient(serviceName, configs) { + @Override + protected Subject getLoginSubject() { + return new Subject(); + } + }; + } + + private Client jerseyClientReturning(Response first, Response... rest) { + Client client = mock(Client.class); + WebTarget target = mock(WebTarget.class); + Invocation.Builder builder = mock(Invocation.Builder.class); + doReturn(target).when(client).target(anyString()); + doReturn(builder).when(target).request(MediaType.APPLICATION_JSON); + OngoingStubbing sequence = when(builder.get()).thenReturn(first); + for (Response next : rest) { + sequence = sequence.thenReturn(next); + } + return client; + } + + @Test + void testConnectionTestNegativeFailsFastWithoutConnectivityDetails() { + assertThrows(HadoopException.class, () -> SqoopClient.connectionTest("sqoop-svc", Collections.emptyMap())); + } + + @Test + void testConnectionTestPositiveRecordsFailureWhenConnectorDiscoveryReturnsEmpty() { + Map configs = minimalReachableConfiguration(); + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenAnswer(invocation -> { + String serviceName = invocation.getArgument(0); + Map cfg = invocation.getArgument(1); + return clientSkippingRemoteCalls(serviceName, cfg); + }); + + Map payload = SqoopClient.connectionTest("sqoop-svc", configs); + + assertNotNull(payload); + assertTrue(payload.containsKey("connectivityStatus")); + assertFalse(Boolean.TRUE.equals(payload.get("connectivityStatus"))); + } + } + + @Test + void testConnectionTestPositiveSucceedsWhenConnectorNamesReturned() { + Map configs = minimalReachableConfiguration(); + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"connectors\":[{\"name\":\"hdfs\",\"id\":1}]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenAnswer(invocation -> { + String serviceName = invocation.getArgument(0); + Map cfg = invocation.getArgument(1); + return clientWithSubject(serviceName, cfg); + }); + + Map payload = SqoopClient.connectionTest("sqoop-svc", configs); + + assertTrue(Boolean.TRUE.equals(payload.get("connectivityStatus"))); + } + } + } + + @Test + void testConstructorNegativeNullConfigurationMapThrowsNullPointerException() { + assertThrows(NullPointerException.class, () -> new SqoopClient("sqoop-svc", null)); + } + + @Test + void testConstructorPositiveAcceptsMissingOptionalKeysAndStillBuilds() { + Map sparse = new HashMap<>(); + sparse.put("username", "u"); + SqoopClient client = clientSkippingRemoteCalls("svc", sparse); + assertNotNull(client); + } + + @Test + void testConstructorPositiveInitializesWithProvidedProperties() { + SqoopClient client = clientSkippingRemoteCalls("sqoop-svc", minimalReachableConfiguration()); + assertNotNull(client); + assertNotNull(client.getSerivceName()); + } + + @Test + void testGetConnectorListNegativeThrowsWhenHttpStatusNotOk() { + Response bad = mock(Response.class); + when(bad.getStatus()).thenReturn(HttpStatus.SC_NOT_FOUND); + Map configs = minimalReachableConfiguration(); + Client jerseyStubClient = jerseyClientReturning(bad); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", configs); + assertThrows(HadoopException.class, () -> client.getConnectorList("*", Collections.emptyList())); + } + } + + @Test + void testGetConnectorListNegativeThrowsWhenJsonMalformedForOkResponse() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("not-json"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + assertThrows(HadoopException.class, () -> client.getConnectorList("*", Collections.emptyList())); + } + } + + @Test + void testGetConnectorListNegativeThrowsWhenRemoteResponseInvalid() { + SqoopClient client = SqoopClient.getSqoopClient("sqoop-svc", minimalReachableConfiguration()); + assertThrows(HadoopException.class, () -> client.getConnectorList("___prefix___", Collections.emptyList())); + } + + @Test + void testGetConnectorListNegativeThrowsWhenRestInvocationFails() { + Client clientMock = mock(Client.class); + WebTarget target = mock(WebTarget.class); + Invocation.Builder builder = mock(Invocation.Builder.class); + doReturn(target).when(clientMock).target(anyString()); + doReturn(builder).when(target).request(MediaType.APPLICATION_JSON); + when(builder.get()).thenThrow(new ProcessingException("network")); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(clientMock); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + assertThrows(HadoopException.class, () -> client.getConnectorList("*", Collections.emptyList())); + } + } + + @Test + void testGetConnectorListPositiveMatchesPrefixCaseInsensitiveAndWildcard() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn( + "{\"connectors\":[{\"name\":\"HdfsConn\",\"id\":1},{\"name\":\"kafka\",\"id\":2}]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + + List lowerPrefix = client.getConnectorList("hdfs", Collections.emptyList()); + assertEquals(Collections.singletonList("HdfsConn"), lowerPrefix); + + List kafkaPrefix = client.getConnectorList("kaf", Collections.emptyList()); + assertEquals(Collections.singletonList("kafka"), kafkaPrefix); + } + } + + @Test + void testGetConnectorListPositiveReturnsEmptyListWithoutSubject() { + SqoopClient client = clientSkippingRemoteCalls("sqoop-svc", minimalReachableConfiguration()); + List connectors = client.getConnectorList("*", Collections.emptyList()); + assertNotNull(connectors); + assertTrue(connectors.isEmpty()); + } + + @Test + void testGetConnectorListPositiveSkipsExistingResourcesAndSupportsSemicolonUrls() { + Response fail = mock(Response.class); + when(fail.getStatus()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR); + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"connectors\":[{\"name\":\"a\"},{\"name\":\"b\"}]}"); + Client jerseyStubClient = jerseyClientReturning(fail, ok); + + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://bad.example;http://good.example"); + configs.put("username", "u"); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("svc", configs); + List names = client.getConnectorList(null, Collections.singletonList("a")); + + assertEquals(Collections.singletonList("b"), names); + } + } + + @Test + void testGetJobListNegativeThrowsWhenRemoteResponseInvalid() { + SqoopClient client = SqoopClient.getSqoopClient("sqoop-svc", minimalReachableConfiguration()); + assertThrows(HadoopException.class, () -> client.getJobList("___prefix___", Collections.emptyList())); + } + + @Test + void testGetJobListPositiveParsesJobsPayload() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"jobs\":[{\"name\":\"daily\",\"id\":3}]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + List jobs = client.getJobList("dai", Collections.emptyList()); + + assertEquals(Collections.singletonList("daily"), jobs); + } + } + + @Test + void testGetJobListPositiveReturnsEmptyListWithoutSubject() { + SqoopClient client = clientSkippingRemoteCalls("sqoop-svc", minimalReachableConfiguration()); + List jobs = client.getJobList("*", Collections.emptyList()); + assertNotNull(jobs); + assertTrue(jobs.isEmpty()); + } + + @Test + void testGetLinkListNegativeThrowsWhenRemoteResponseInvalid() { + SqoopClient client = SqoopClient.getSqoopClient("sqoop-svc", minimalReachableConfiguration()); + assertThrows(HadoopException.class, () -> client.getLinkList("___prefix___", Collections.emptyList())); + } + + @Test + void testGetLinkListPositiveParsesLinksPayload() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"links\":[{\"name\":\"oracle-link\",\"id\":4}]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + List links = client.getLinkList("oracle", Collections.emptyList()); + + assertEquals(Collections.singletonList("oracle-link"), links); + } + } + + @Test + void testGetLinkListPositiveReturnsEmptyListWithoutSubject() { + SqoopClient client = clientSkippingRemoteCalls("sqoop-svc", minimalReachableConfiguration()); + List links = client.getLinkList("*", Collections.emptyList()); + assertNotNull(links); + assertTrue(links.isEmpty()); + } + + @Test + void testGetSqoopClientNegativeThrowsWhenConfigsMapEmpty() { + assertThrows(HadoopException.class, () -> SqoopClient.getSqoopClient("sqoop-svc", Collections.emptyMap())); + } + + @Test + void testGetSqoopClientPositiveReturnsConnectedClientInstance() { + SqoopClient client = SqoopClient.getSqoopClient("sqoop-svc", minimalReachableConfiguration()); + assertNotNull(client); + } + + @Test + void testListsReturnEmptyWhenWrappedCollectionsAreEmpty() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"connectors\":[]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + List connectors = client.getConnectorList("*", Collections.emptyList()); + + assertNotNull(connectors); + assertTrue(connectors.isEmpty()); + } + } + + @Test + void testConstructorPositiveLogsWhenUsernameMissingValue() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://localhost"); + configs.put("username", ""); + SqoopClient client = clientSkippingRemoteCalls("svc", configs); + assertNotNull(client); + } + + @Test + void testFilterNegativeExcludesResourcesThatDoNotMatchPrefix() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"connectors\":[{\"name\":\"alpha\"},{\"name\":\"beta\"}]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + List names = client.getConnectorList("nomatch-prefix", Collections.emptyList()); + + assertTrue(names.isEmpty()); + } + } + + @Test + void testGetClientResponseInnerLoopCatchesLinkageErrorsThenFailsClosed() { + Client clientMock = mock(Client.class); + WebTarget target = mock(WebTarget.class); + Invocation.Builder builder = mock(Invocation.Builder.class); + doReturn(target).when(clientMock).target(anyString()); + doReturn(builder).when(target).request(MediaType.APPLICATION_JSON); + when(builder.get()).thenThrow(new LinkageError("simulated failure")); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(clientMock); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + assertThrows(HadoopException.class, () -> client.getConnectorList("*", Collections.emptyList())); + } + } + + @Test + void testGetConnectorListPositiveAcceptsWildcardStyleMatchingToken() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"connectors\":[{\"name\":\"first\"},{\"name\":\"second\"}]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + List names = client.getConnectorList("*tail", Collections.emptyList()); + + assertEquals(2, names.size()); + } + } + + @Test + void testGetJobListPositiveReturnsEmptyWhenJobsArrayEmpty() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"jobs\":[]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + List jobs = client.getJobList("*", Collections.emptyList()); + + assertNotNull(jobs); + assertTrue(jobs.isEmpty()); + } + } + + @Test + void testGetLinkListPositiveReturnsEmptyWhenLinksArrayEmpty() { + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"links\":[]}"); + Client jerseyStubClient = jerseyClientReturning(ok); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + List links = client.getLinkList("*", Collections.emptyList()); + + assertNotNull(links); + assertTrue(links.isEmpty()); + } + } + + @Test + void testJerseyGetThrowsWebApplicationExceptionMapsToHadoopFailure() { + Client clientMock = mock(Client.class); + WebTarget target = mock(WebTarget.class); + Invocation.Builder builder = mock(Invocation.Builder.class); + doReturn(target).when(clientMock).target(anyString()); + doReturn(builder).when(target).request(MediaType.APPLICATION_JSON); + Response jaxRsFailure = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + when(builder.get()).thenThrow(new WebApplicationException(jaxRsFailure)); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(clientMock); + + SqoopClient client = clientWithSubject("sqoop-svc", minimalReachableConfiguration()); + assertThrows(HadoopException.class, () -> client.getConnectorList("*", Collections.emptyList())); + } + } + + @Test + void testNonOkResponseBodyReadBranchDoesNotBreakClientFlow() { + Response warn = mock(Response.class); + when(warn.getStatus()).thenReturn(HttpStatus.SC_BAD_REQUEST); + when(warn.readEntity(String.class)).thenReturn("{\"error\":\"bad\"}"); + Response ok = mock(Response.class); + when(ok.getStatus()).thenReturn(HttpStatus.SC_OK); + when(ok.readEntity(String.class)).thenReturn("{\"links\":[{\"name\":\"ok-link\"}]}"); + Client jerseyStubClient = jerseyClientReturning(warn, ok); + + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://first,http://second"); + configs.put("username", "u"); + + try (MockedStatic jersey = mockStatic(RangerJersey2ClientBuilder.class, + CALLS_REAL_METHODS)) { + jersey.when(RangerJersey2ClientBuilder::newClient).thenReturn(jerseyStubClient); + + SqoopClient client = clientWithSubject("svc", configs); + List links = client.getLinkList("ok", Collections.emptyList()); + + assertEquals(Collections.singletonList("ok-link"), links); + } + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopResourceMgr.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopResourceMgr.java new file mode 100644 index 00000000000..ae2d7d97dbd --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/TestSqoopResourceMgr.java @@ -0,0 +1,254 @@ +/* + * 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.sqoop.client; + +import org.apache.ranger.plugin.client.BaseClient; +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.junit.jupiter.MockitoExtension; + +import javax.security.auth.Subject; + +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.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopResourceMgr + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopResourceMgr { + @Test + void testGetSqoopResourcesNegativeReturnsNullWhenConfigsMissing() { + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + + List discovered = SqoopResourceMgr.getSqoopResources("sqoop-svc", Collections.emptyMap(), ctx); + + assertNull(discovered); + } + + @Test + void testGetSqoopResourcesNegativeReturnsNullWhenResourceNameUnknown() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://localhost"); + configs.put("username", "u"); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + when(ctx.getUserInput()).thenReturn("x"); + when(ctx.getResourceName()).thenReturn("unknown-kind"); + when(ctx.getResources()).thenReturn(Collections.emptyMap()); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenAnswer(invocation -> { + String serviceName = invocation.getArgument(0); + Map cfg = invocation.getArgument(1); + return new SqoopClient(serviceName, cfg) { + @Override + protected Subject getLoginSubject() { + return null; + } + }; + }); + + assertNull(SqoopResourceMgr.getSqoopResources("svc", configs, ctx)); + } + } + + @Test + void testGetSqoopResourcesNegativeReturnsNullWhenResourceNameBlank() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://localhost"); + configs.put("username", "u"); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + when(ctx.getUserInput()).thenReturn("z"); + when(ctx.getResourceName()).thenReturn(""); + when(ctx.getResources()).thenReturn(Collections.emptyMap()); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenAnswer(invocation -> { + String serviceName = invocation.getArgument(0); + Map cfg = invocation.getArgument(1); + return new SqoopClient(serviceName, cfg) { + @Override + protected Subject getLoginSubject() { + return null; + } + }; + }); + + assertNull(SqoopResourceMgr.getSqoopResources("svc", configs, ctx)); + } + } + + @Test + void testGetSqoopResourcesNegativeReturnsNullWhenSqoopClientMissing() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://localhost"); + configs.put("username", "u"); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + when(ctx.getUserInput()).thenReturn("pre"); + when(ctx.getResourceName()).thenReturn(SqoopResourceMgr.CONNECTOR); + when(ctx.getResources()).thenReturn(Collections.singletonMap(SqoopResourceMgr.CONNECTOR, Collections.emptyList())); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenReturn(null); + + assertNull(SqoopResourceMgr.getSqoopResources("svc", configs, ctx)); + } + } + + @Test + void testGetSqoopResourcesPositiveHandlesConnectorLookupWithoutFailure() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://127.0.0.1:1"); + configs.put("username", "integration-user"); + + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + when(ctx.getUserInput()).thenReturn("*"); + when(ctx.getResourceName()).thenReturn(SqoopResourceMgr.CONNECTOR); + when(ctx.getResources()).thenReturn(Collections.singletonMap(SqoopResourceMgr.CONNECTOR, Collections.emptyList())); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenAnswer(invocation -> { + String serviceName = invocation.getArgument(0); + Map cfg = invocation.getArgument(1); + return new SqoopClient(serviceName, cfg) { + @Override + protected Subject getLoginSubject() { + return null; + } + }; + }); + + List discovered = SqoopResourceMgr.getSqoopResources("sqoop-svc", configs, ctx); + + assertNotNull(discovered); + assertTrue(discovered.isEmpty()); + } + } + + @Test + void testGetSqoopResourcesPositiveJobBranchDelegatesToClient() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://localhost"); + configs.put("username", "u"); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + when(ctx.getUserInput()).thenReturn(""); + when(ctx.getResourceName()).thenReturn(SqoopResourceMgr.JOB); + when(ctx.getResources()).thenReturn(Collections.singletonMap(SqoopResourceMgr.JOB, Collections.emptyList())); + + SqoopClient mockClient = mock(SqoopClient.class); + when(mockClient.getJobList(any(), any())).thenReturn(Collections.singletonList("job-a")); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenReturn(mockClient); + + List out = SqoopResourceMgr.getSqoopResources("svc", configs, ctx); + + assertEquals(Collections.singletonList("job-a"), out); + } + } + + @Test + void testGetSqoopResourcesPositiveLinkBranchDelegatesToClient() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://localhost"); + configs.put("username", "u"); + ResourceLookupContext ctx = mock(ResourceLookupContext.class); + when(ctx.getUserInput()).thenReturn(null); + when(ctx.getResourceName()).thenReturn(SqoopResourceMgr.LINK); + when(ctx.getResources()).thenReturn(Collections.singletonMap(SqoopResourceMgr.LINK, Collections.emptyList())); + + SqoopClient mockClient = mock(SqoopClient.class); + when(mockClient.getLinkList(any(), any())).thenReturn(Collections.singletonList("link-b")); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.getSqoopClient(anyString(), any())).thenReturn(mockClient); + + List out = SqoopResourceMgr.getSqoopResources("svc", configs, ctx); + + assertEquals(Collections.singletonList("link-b"), out); + } + } + + @Test + void testPrivateConstructorInstantiableOnlyThroughReflection() throws Exception { + Constructor ctor = SqoopResourceMgr.class.getDeclaredConstructor(); + ctor.setAccessible(true); + SqoopResourceMgr instance = ctor.newInstance(); + assertNotNull(instance); + } + + @Test + void testValidateConfigNegativePropagatesWhenConnectionConfigsAbsent() { + assertThrows(HadoopException.class, () -> SqoopResourceMgr.validateConfig("sqoop-svc", Collections.emptyMap())); + } + + @Test + void testValidateConfigNegativePropagatesUncheckedFailuresFromConnectionTest() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://localhost"); + configs.put("username", "u"); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.connectionTest(anyString(), any())).thenThrow(new IllegalStateException("boom")); + + assertThrows(IllegalStateException.class, () -> SqoopResourceMgr.validateConfig("svc", configs)); + } + } + + @Test + void testValidateConfigPositiveReturnsStructuredConnectivityPayload() { + Map configs = new HashMap<>(); + configs.put("sqoop.url", "http://127.0.0.1:1"); + configs.put("username", "integration-user"); + + try (MockedStatic mocked = mockStatic(SqoopClient.class, CALLS_REAL_METHODS)) { + mocked.when(() -> SqoopClient.connectionTest(anyString(), any())).thenAnswer(invocation -> { + Map responseData = new HashMap<>(); + BaseClient.generateResponseDataMap(true, "ok", "ok", null, null, responseData); + return responseData; + }); + + Map outcome = SqoopResourceMgr.validateConfig("sqoop-svc", configs); + + assertNotNull(outcome); + assertTrue(Boolean.TRUE.equals(outcome.get("connectivityStatus"))); + } + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorResponse.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorResponse.java new file mode 100644 index 00000000000..437718d7634 --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorResponse.java @@ -0,0 +1,53 @@ +/* + * 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.sqoop.client.json.model; + +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.assertNotNull; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopConnectorResponse + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopConnectorResponse { + @Test + void testAccessorsPositivePreserveSuppliedValues() { + SqoopConnectorResponse model = new SqoopConnectorResponse(); + model.setId(42L); + model.setName("jdbc"); + model.setVersion("1"); + + assertEquals(42L, model.getId()); + assertEquals("jdbc", model.getName()); + assertEquals("1", model.getVersion()); + } + + @Test + void testToStringNegativeDoesNotFailWhenOptionalFieldsUnset() { + SqoopConnectorResponse model = new SqoopConnectorResponse(); + assertNotNull(model.toString()); + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorsResponse.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorsResponse.java new file mode 100644 index 00000000000..7439a30a3a7 --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopConnectorsResponse.java @@ -0,0 +1,57 @@ +/* + * 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.sqoop.client.json.model; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopConnectorsResponse + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopConnectorsResponse { + @Test + void testAccessorsPositivePreserveSuppliedValues() { + SqoopConnectorsResponse root = new SqoopConnectorsResponse(); + List connectors = new ArrayList<>(); + SqoopConnectorResponse child = new SqoopConnectorResponse(); + child.setName("hdfs"); + connectors.add(child); + root.setConnectors(connectors); + + assertEquals(1, root.getConnectors().size()); + assertEquals("hdfs", root.getConnectors().get(0).getName()); + } + + @Test + void testToStringNegativeDoesNotFailWhenOptionalFieldsUnset() { + SqoopConnectorsResponse root = new SqoopConnectorsResponse(); + assertNotNull(root.toString()); + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobResponse.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobResponse.java new file mode 100644 index 00000000000..32169d1e4cb --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobResponse.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ranger.services.sqoop.client.json.model; + +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.assertNotNull; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopJobResponse + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopJobResponse { + @Test + void testAccessorsPositivePreserveSuppliedValues() { + SqoopJobResponse model = new SqoopJobResponse(); + model.setId(9L); + model.setName("etl"); + model.setFromLinkName("src"); + model.setToLinkName("dst"); + model.setFromConnectorName("ora"); + model.setToConnectorName("hdfs"); + model.setCreationUser("alice"); + + assertEquals(9L, model.getId()); + assertEquals("etl", model.getName()); + assertEquals("src", model.getFromLinkName()); + assertEquals("dst", model.getToLinkName()); + assertEquals("ora", model.getFromConnectorName()); + assertEquals("hdfs", model.getToConnectorName()); + assertEquals("alice", model.getCreationUser()); + } + + @Test + void testToStringNegativeDoesNotFailWhenOptionalFieldsUnset() { + SqoopJobResponse model = new SqoopJobResponse(); + assertNotNull(model.toString()); + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobsResponse.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobsResponse.java new file mode 100644 index 00000000000..7881da2d281 --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopJobsResponse.java @@ -0,0 +1,57 @@ +/* + * 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.sqoop.client.json.model; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopJobsResponse + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopJobsResponse { + @Test + void testAccessorsPositivePreserveSuppliedValues() { + SqoopJobsResponse root = new SqoopJobsResponse(); + List jobs = new ArrayList<>(); + SqoopJobResponse job = new SqoopJobResponse(); + job.setName("daily"); + jobs.add(job); + root.setJobs(jobs); + + assertEquals(1, root.getJobs().size()); + assertEquals("daily", root.getJobs().get(0).getName()); + } + + @Test + void testToStringNegativeDoesNotFailWhenOptionalFieldsUnset() { + SqoopJobsResponse root = new SqoopJobsResponse(); + assertNotNull(root.toString()); + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinkResponse.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinkResponse.java new file mode 100644 index 00000000000..9feb0e86ddd --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinkResponse.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ranger.services.sqoop.client.json.model; + +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.assertNotNull; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopLinkResponse + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopLinkResponse { + @Test + void testAccessorsPositivePreserveSuppliedValues() { + SqoopLinkResponse model = new SqoopLinkResponse(); + model.setId(3L); + model.setName("warehouse"); + model.setConnectorName("hdfs"); + model.setCreationUser("bob"); + + assertEquals(3L, model.getId()); + assertEquals("warehouse", model.getName()); + assertEquals("hdfs", model.getConnectorName()); + assertEquals("bob", model.getCreationUser()); + } + + @Test + void testToStringNegativeDoesNotFailWhenOptionalFieldsUnset() { + SqoopLinkResponse model = new SqoopLinkResponse(); + assertNotNull(model.toString()); + } +} diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinksResponse.java b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinksResponse.java new file mode 100644 index 00000000000..d5299de7fb1 --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/services/sqoop/client/json/model/TestSqoopLinksResponse.java @@ -0,0 +1,57 @@ +/* + * 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.sqoop.client.json.model; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * @generated by Cursor + * @description : Unit Test cases for SqoopLinksResponse + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestSqoopLinksResponse { + @Test + void testAccessorsPositivePreserveSuppliedValues() { + SqoopLinksResponse root = new SqoopLinksResponse(); + List links = new ArrayList<>(); + SqoopLinkResponse link = new SqoopLinkResponse(); + link.setName("staging"); + links.add(link); + root.setLinks(links); + + assertEquals(1, root.getLinks().size()); + assertEquals("staging", root.getLinks().get(0).getName()); + } + + @Test + void testToStringNegativeDoesNotFailWhenOptionalFieldsUnset() { + SqoopLinksResponse root = new SqoopLinksResponse(); + assertNotNull(root.toString()); + } +}