From cfb47a1ebbd78e25b061a2c80638c1ac01f73a60 Mon Sep 17 00:00:00 2001 From: isuri Date: Mon, 25 Sep 2023 09:11:52 +0530 Subject: [PATCH] test duplicate addition for device organization and unit tests --- .../dao/DeviceOrganizationDAO.java | 10 ++ .../dao/impl/DeviceOrganizationDAOImpl.java | 53 +++++-- .../exception/BadRequestDaoException.java | 14 ++ .../impl/DeviceOrganizationServiceImpl.java | 106 +++++++++---- .../spi/DeviceOrganizationService.java | 3 + .../device/organization/util/LockManager.java | 47 ++++++ .../device/organization/DAONegativeTest.java | 44 +++--- .../organization/ServiceNegativeTest.java | 142 +++++++++++++++--- .../device/organization/ServiceTest.java | 70 ++++++--- .../conf/datasources/data-source-config.xml | 1 - 10 files changed, 399 insertions(+), 91 deletions(-) create mode 100644 components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/exception/BadRequestDaoException.java create mode 100644 components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/util/LockManager.java diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/DeviceOrganizationDAO.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/DeviceOrganizationDAO.java index bb7a03967d..3e061a741b 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/DeviceOrganizationDAO.java +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/DeviceOrganizationDAO.java @@ -57,6 +57,15 @@ public interface DeviceOrganizationDAO { */ boolean addDeviceOrganization(DeviceOrganization deviceOrganization) throws DeviceOrganizationMgtDAOException; + /** + * check whether a record already exist with same deviceId and parentDeviceId + * @param deviceId + * @param parentDeviceId + * @return + * @throws DeviceOrganizationMgtDAOException + */ + boolean organizationExists(int deviceId, int parentDeviceId) throws DeviceOrganizationMgtDAOException; + /** * update a record in device organization table * @@ -64,6 +73,7 @@ public interface DeviceOrganizationDAO { * @return * @throws DeviceOrganizationMgtDAOException */ + boolean updateDeviceOrganization(DeviceOrganization deviceOrganization) throws DeviceOrganizationMgtDAOException; diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/impl/DeviceOrganizationDAOImpl.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/impl/DeviceOrganizationDAOImpl.java index 833461bd99..7e45907f63 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/impl/DeviceOrganizationDAOImpl.java +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/dao/impl/DeviceOrganizationDAOImpl.java @@ -22,19 +22,19 @@ import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.u import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.util.DeviceOrganizationDaoUtil; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceNode; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization; +import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.BadRequestDaoException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DBConnectionException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtDAOException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.sql.Connection; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -49,10 +49,14 @@ public class DeviceOrganizationDAOImpl implements DeviceOrganizationDAO { public List getChildrenOf(DeviceNode node, int maxDepth, boolean includeDevice) throws DeviceOrganizationMgtDAOException { List childNodes = new ArrayList<>(); Set visited = new HashSet<>(); + // Input validation + if (node == null || maxDepth < 0) { + throw new BadRequestDaoException("Invalid input parameters."); + } try { Connection conn = ConnectionManagerUtil.getDBConnection(); getChildrenRecursive(node, maxDepth, visited, conn, childNodes, includeDevice); - if(!includeDevice){ + if (!includeDevice) { childNodes.add(node); } return childNodes; @@ -103,6 +107,9 @@ public class DeviceOrganizationDAOImpl implements DeviceOrganizationDAO { @Override public List getParentsOf(DeviceNode node, int maxDepth, boolean includeDevice) throws DeviceOrganizationMgtDAOException { + if (node == null || maxDepth <= 0) { + throw new BadRequestDaoException("Invalid input parameters."); + } List parentNodes = new ArrayList<>(); Set visited = new HashSet<>(); try { @@ -165,13 +172,10 @@ public class DeviceOrganizationDAOImpl implements DeviceOrganizationDAO { @Override public boolean addDeviceOrganization(DeviceOrganization deviceOrganization) throws DeviceOrganizationMgtDAOException { - if (deviceOrganization == null) { - return false; + if (deviceOrganization == null || deviceOrganization.getDeviceId() <= 0 || deviceOrganization.getParentDeviceId() <= 0) { + throw new BadRequestDaoException("Invalid input parameters."); } - if (deviceOrganization.getDeviceId() == 0 || deviceOrganization.getParentDeviceId() == 0) { - return false; - } try { String sql = "INSERT INTO DM_DEVICE_ORGANIZATION (DEVICE_ID, PARENT_DEVICE_ID, LAST_UPDATED_TIMESTAMP)" + " VALUES (?, ?, ?)"; @@ -199,6 +203,37 @@ public class DeviceOrganizationDAOImpl implements DeviceOrganizationDAO { } } + @Override + public boolean organizationExists(int deviceId, int parentDeviceId) throws DeviceOrganizationMgtDAOException { + try { + Connection conn = ConnectionManagerUtil.getDBConnection(); + String sql = "SELECT 1 " + + "FROM DM_DEVICE_ORGANIZATION DO " + + "WHERE (DO.DEVICE_ID = ? AND DO.PARENT_DEVICE_ID = ?) " + + "LIMIT 1"; + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, deviceId); + stmt.setInt(2, parentDeviceId); + + try (ResultSet rs = stmt.executeQuery()) { + return rs.next(); // Returns true if a match is found, false otherwise + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining DB connection to check organization existence for deviceId " + + deviceId + " and parentDeviceId " + parentDeviceId; + log.error(msg); + throw new DeviceOrganizationMgtDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while processing SQL to check organization existence for deviceId " + + deviceId + " and parentDeviceId " + parentDeviceId; + log.error(msg); + throw new DeviceOrganizationMgtDAOException(msg, e); + } + } + + @Override public boolean updateDeviceOrganization(DeviceOrganization deviceOrganization) throws DeviceOrganizationMgtDAOException { diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/exception/BadRequestDaoException.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/exception/BadRequestDaoException.java new file mode 100644 index 0000000000..22a4a95579 --- /dev/null +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/exception/BadRequestDaoException.java @@ -0,0 +1,14 @@ +package io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception; + +public class BadRequestDaoException extends DeviceOrganizationMgtDAOException{ + + private static final long serialVersionUID = -6275360486437601206L; + + public BadRequestDaoException(String message) { + super(message); + } + + public BadRequestDaoException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/impl/DeviceOrganizationServiceImpl.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/impl/DeviceOrganizationServiceImpl.java index 093f402738..36787a6f4d 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/impl/DeviceOrganizationServiceImpl.java +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/impl/DeviceOrganizationServiceImpl.java @@ -17,21 +17,20 @@ */ package io.entgra.device.mgt.core.device.mgt.extensions.device.organization.impl; -import io.entgra.device.mgt.core.device.mgt.common.Device; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.DeviceOrganizationDAO; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.DeviceOrganizationDAOFactory; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.util.ConnectionManagerUtil; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceNode; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization; +import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.BadRequestException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DBConnectionException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtDAOException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtPluginException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.spi.DeviceOrganizationService; +import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.util.LockManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.sql.Date; -import java.util.ArrayList; import java.util.List; public class DeviceOrganizationServiceImpl implements DeviceOrganizationService { @@ -47,6 +46,9 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public List getChildrenOf(DeviceNode node, int maxDepth, boolean includeDevice) throws DeviceOrganizationMgtPluginException { + if (node == null || node.getDeviceId() <= 0 || maxDepth < 0) { + throw new BadRequestException("Invalid input parameters."); + } try { // Open a database connection ConnectionManagerUtil.openDBConnection(); @@ -68,6 +70,9 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public List getParentsOf(DeviceNode node, int maxDepth, boolean includeDevice) throws DeviceOrganizationMgtPluginException { + if (node == null || node.getDeviceId() <= 0 || maxDepth < 0) { + throw new BadRequestException("Invalid input parameters."); + } try { // Open a database connection ConnectionManagerUtil.openDBConnection(); @@ -89,38 +94,73 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public boolean addDeviceOrganization(DeviceOrganization deviceOrganization) throws DeviceOrganizationMgtPluginException { + if (deviceOrganization == null || deviceOrganization.getDeviceId() == 0 + || deviceOrganization.getParentDeviceId() == 0) { + throw new BadRequestException("Invalid input parameters."); + } String msg = ""; - if (deviceOrganization == null) { - return false; + // Check if an organization with the same deviceId and parentDeviceId already exists + if (organizationExists(deviceOrganization.getDeviceId(), deviceOrganization.getParentDeviceId())) { + msg = "Device organization with the same deviceId and parentDeviceId already exists."; + log.error(msg); + throw new DeviceOrganizationMgtPluginException(msg); } - if (deviceOrganization.getDeviceId() == 0 || deviceOrganization.getParentDeviceId() == 0) { - return false; - } - try { - ConnectionManagerUtil.beginDBTransaction(); - boolean result = deviceOrganizationDao.addDeviceOrganization(deviceOrganization); - if (result) { - msg = "Device organization added successfully,for " + deviceOrganization.getDeviceId(); - if (log.isDebugEnabled()) { - log.debug(msg); + // Use LockManager to get a lock object based on deviceId and parentDeviceId +// LockManager lockManager = LockManager.getInstance(); +// Object lock = lockManager.getLock(deviceOrganization.getDeviceId(), deviceOrganization.getParentDeviceId()); +// +// synchronized (lock) { + + try { + ConnectionManagerUtil.beginDBTransaction(); + boolean result = deviceOrganizationDao.addDeviceOrganization(deviceOrganization); + if (result) { + msg = "Device organization added successfully, for device ID " + deviceOrganization.getDeviceId() + + " and parent device ID " + deviceOrganization.getParentDeviceId(); + if (log.isDebugEnabled()) { + log.debug(msg); + } + } else { + ConnectionManagerUtil.rollbackDBTransaction(); + msg = "Device organization failed to add, for device ID " + deviceOrganization.getDeviceId() + + " and parent device ID " + deviceOrganization.getParentDeviceId(); + throw new DeviceOrganizationMgtPluginException(msg); } - } else { + ConnectionManagerUtil.commitDBTransaction(); + return true; + } catch (DBConnectionException e) { + msg = "Error occurred while obtaining the database connection to add device organization for device ID " + + deviceOrganization.getDeviceId() + " and parent device ID" + + deviceOrganization.getParentDeviceId(); + log.error(msg); + throw new DeviceOrganizationMgtPluginException(msg, e); + } catch (DeviceOrganizationMgtDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); - msg = "Device organization failed to add,for " + deviceOrganization.getDeviceId(); - throw new DeviceOrganizationMgtPluginException(msg); + msg = "Error occurred in the database level while adding device organization for device ID " + + deviceOrganization.getDeviceId() + " and parent device ID" + + deviceOrganization.getParentDeviceId(); + log.error(msg); + throw new DeviceOrganizationMgtPluginException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); } - ConnectionManagerUtil.commitDBTransaction(); - return true; +// } + } + + // Helper method to check if an organization with the same deviceId and parentDeviceId already exists + @Override + public boolean organizationExists(int deviceId, int parentDeviceId) throws DeviceOrganizationMgtPluginException { + try { + ConnectionManagerUtil.openDBConnection(); + boolean exists = deviceOrganizationDao.organizationExists(deviceId, parentDeviceId); + return exists; } catch (DBConnectionException e) { - msg = "Error occurred while obtaining the database connection to add device organization for " + - deviceOrganization.getDeviceId(); + String msg = "Error occurred while obtaining the database connection to check organization existence."; log.error(msg); throw new DeviceOrganizationMgtPluginException(msg, e); } catch (DeviceOrganizationMgtDAOException e) { - ConnectionManagerUtil.rollbackDBTransaction(); - msg = "Error occurred in the database level while adding device organization for " + - deviceOrganization.getDeviceId(); + String msg = "Error occurred in the database level while checking organization existence."; log.error(msg); throw new DeviceOrganizationMgtPluginException(msg, e); } finally { @@ -131,12 +171,14 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public boolean updateDeviceOrganization(DeviceOrganization organization) throws DeviceOrganizationMgtPluginException { + if (organization == null || organization.getOrganizationId() <= 0) { + throw new BadRequestException("Invalid input parameters."); + } String msg = ""; DeviceOrganization deviceOrganization = getDeviceOrganizationByID(organization.getOrganizationId()); if (deviceOrganization == null) { String errorMsg = "Cannot find device organization for organization ID " + organization.getOrganizationId(); log.error(errorMsg); -// throw new DeviceOrganizationMgtPluginException(); return false; } @@ -174,6 +216,9 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public DeviceOrganization getDeviceOrganizationByID(int organizationId) throws DeviceOrganizationMgtPluginException { + if (organizationId <= 0) { + throw new BadRequestException("Invalid input parameters."); + } try { // Open a database connection ConnectionManagerUtil.openDBConnection(); @@ -196,6 +241,9 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public boolean deleteDeviceOrganizationByID(int organizationId) throws DeviceOrganizationMgtPluginException { + if (organizationId <= 0) { + throw new BadRequestException("Invalid input parameters."); + } String msg = ""; DeviceOrganization deviceOrganization = getDeviceOrganizationByID(organizationId); @@ -238,6 +286,9 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public boolean deleteDeviceAssociations(int deviceId) throws DeviceOrganizationMgtPluginException { + if (deviceId <= 0) { + throw new BadRequestException("Invalid input parameters."); + } String msg = ""; boolean deviceIdExist = doesDeviceIdExist(deviceId); @@ -280,6 +331,9 @@ public class DeviceOrganizationServiceImpl implements DeviceOrganizationService @Override public boolean doesDeviceIdExist(int deviceId) throws DeviceOrganizationMgtPluginException { + if (deviceId <= 0) { + throw new BadRequestException("Invalid input parameters."); + } try { // Open a database connection ConnectionManagerUtil.openDBConnection(); diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/spi/DeviceOrganizationService.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/spi/DeviceOrganizationService.java index 8f6f92477b..8134b59a58 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/spi/DeviceOrganizationService.java +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/spi/DeviceOrganizationService.java @@ -38,6 +38,9 @@ public interface DeviceOrganizationService { DeviceOrganization getDeviceOrganizationByID(int organizationId) throws DeviceOrganizationMgtPluginException; + boolean organizationExists(int deviceId, int parentDeviceId) + throws DeviceOrganizationMgtPluginException; + boolean doesDeviceIdExist(int deviceId) throws DeviceOrganizationMgtPluginException; diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/util/LockManager.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/util/LockManager.java new file mode 100644 index 0000000000..9f1def92ae --- /dev/null +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/util/LockManager.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.extensions.device.organization.util; + +import java.util.HashMap; +import java.util.Map; + +/** + * This class handle locks to manage concurrency issues when adding device organization + */ +public class LockManager { + private static final LockManager INSTANCE = new LockManager(); + private final Map lockMap = new HashMap<>(); + + private LockManager() { + } + + public static LockManager getInstance() { + return INSTANCE; + } + + public Object getLock(int deviceId, int parentDeviceId) { + String lockKey = deviceId + "-" + parentDeviceId; + synchronized (lockMap) { + if (!lockMap.containsKey(lockKey)) { + lockMap.put(lockKey, new Object()); + } + return lockMap.get(lockKey); + } + } +} + diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/DAONegativeTest.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/DAONegativeTest.java index 8f26028025..d1eca38d50 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/DAONegativeTest.java +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/DAONegativeTest.java @@ -3,6 +3,7 @@ package io.entgra.device.mgt.core.device.mgt.extensions.device.organization; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.DeviceOrganizationDAO; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.DeviceOrganizationDAOFactory; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dao.util.ConnectionManagerUtil; +import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceNode; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DBConnectionException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtDAOException; @@ -24,28 +25,35 @@ public class DAONegativeTest extends BaseDeviceOrganizationTest { log.info("DAO test initialized"); } - @Test(description = "This method tests the add device organization method under negative circumstances with null " + - "data") - public void testAddDeviceOrganization() throws DeviceOrganizationMgtDAOException { - DeviceOrganization deviceOrganization = new DeviceOrganization() { - }; + @Test(expectedExceptions = DeviceOrganizationMgtDAOException.class, description = "This method tests the addDeviceOrganization method under negative circumstances with null input") + public void testAddDeviceOrganizationWithNullInput() throws DeviceOrganizationMgtDAOException { + DeviceOrganization invalidDeviceOrg = null; + deviceOrganizationDAO.addDeviceOrganization(invalidDeviceOrg); + } + + @Test(description = "Test with invalid input parameters (bad request)") + public void testGetChildrenOfWithInvalidInput() { + // Create an invalid input (e.g., null node and negative maxDepth) + DeviceNode invalidNode = null; + int invalidMaxDepth = -1; + boolean includeDevice = true; + try { - ConnectionManagerUtil.beginDBTransaction(); - deviceOrganizationDAO.addDeviceOrganization(deviceOrganization); - ConnectionManagerUtil.commitDBTransaction(); + deviceOrganizationDAO.getChildrenOf(invalidNode, invalidMaxDepth, includeDevice); + assert false : "Expected exception for bad request was not thrown."; } catch (DeviceOrganizationMgtDAOException e) { - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Error occurred while processing SQL to insert device organization"; - log.error(msg); - throw new DeviceOrganizationMgtDAOException(msg, e); - } catch (DBConnectionException e) { - String msg = "Error occurred while obtaining DB connection to insert device organization"; - log.error(msg); - throw new DeviceOrganizationMgtDAOException(msg, e); - } finally { - ConnectionManagerUtil.closeDBConnection(); + log.info("Expected exception for bad request was thrown: " + e.getMessage()); } } + @Test(expectedExceptions = DeviceOrganizationMgtDAOException.class, description = "This method tests the " + + "getParentsOf method under negative circumstances with invalid input") + public void testGetParentsOfWithInvalidInput() throws DeviceOrganizationMgtDAOException { + DeviceNode invalidNode = null; + int invalidMaxDepth = -1; + boolean includeDevice = true; + deviceOrganizationDAO.getParentsOf(invalidNode, invalidMaxDepth, includeDevice); + } + } diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceNegativeTest.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceNegativeTest.java index 6b610063b6..15758a1d42 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceNegativeTest.java +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceNegativeTest.java @@ -1,16 +1,19 @@ package io.entgra.device.mgt.core.device.mgt.extensions.device.organization; +import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceNode; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.dto.DeviceOrganization; +import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.BadRequestException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.exception.DeviceOrganizationMgtPluginException; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.impl.DeviceOrganizationServiceImpl; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.mock.BaseDeviceOrganizationTest; import io.entgra.device.mgt.core.device.mgt.extensions.device.organization.spi.DeviceOrganizationService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import java.sql.Date; +import java.util.Date; public class ServiceNegativeTest extends BaseDeviceOrganizationTest { @@ -24,24 +27,127 @@ public class ServiceNegativeTest extends BaseDeviceOrganizationTest { log.info("Service test initialized"); } - @Test(description = "This method tests Add Device Organization method under negative circumstances with null data") + @Test(description = "This method tests Get Children Of method under negative circumstances with null data", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testGetChildrenOfWithInvalidInput() throws DeviceOrganizationMgtPluginException { + DeviceNode invalidNode = null; + int maxDepth = -1; + boolean includeDevice = true; + deviceOrganizationService.getChildrenOf(invalidNode, maxDepth, includeDevice); + } + + @Test(description = "This method tests Get Children Of method under negative circumstances with an invalid DeviceNode", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testGetChildrenOfWithInvalidDeviceNode() throws DeviceOrganizationMgtPluginException { + DeviceNode invalidNode = new DeviceNode(); // Provide an invalid DeviceNode + int maxDepth = 2; + boolean includeDevice = true; + deviceOrganizationService.getChildrenOf(invalidNode, maxDepth, includeDevice); + } + + @Test(description = "This method tests Get Parents Of method under negative circumstances with null data", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testGetParentsOfWithInvalidInput() throws DeviceOrganizationMgtPluginException { + DeviceNode invalidNode = null; + int maxDepth = -1; + boolean includeDevice = true; + deviceOrganizationService.getParentsOf(invalidNode, maxDepth, includeDevice); + } + + @Test(description = "This method tests Get Parents Of method under negative circumstances with an invalid DeviceNode", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testGetParentsOfWithInvalidDeviceNode() throws DeviceOrganizationMgtPluginException { + DeviceNode invalidNode = new DeviceNode(); // Provide an invalid DeviceNode + int maxDepth = 2; + boolean includeDevice = true; + deviceOrganizationService.getParentsOf(invalidNode, maxDepth, includeDevice); + } + - public void testAddDeviceOrganization() throws DeviceOrganizationMgtPluginException { + @Test(description = "This method tests Add Device Organization method under negative circumstances with null data", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}, + expectedExceptionsMessageRegExp = ".*Invalid input parameters.*") + public void testAddDeviceOrganizationWithInvalidInput() throws DeviceOrganizationMgtPluginException { + DeviceOrganization invalidOrganization = new DeviceOrganization() { + }; + deviceOrganizationService.addDeviceOrganization(invalidOrganization); + } + + @Test(description = "This method tests organizationExists method under negative circumstances with an organization that doesn't exist") + public void testOrganizationDoesNotExist() throws DeviceOrganizationMgtPluginException { + int nonExistentDeviceId = 9999; // An ID that doesn't exist + int nonExistentParentDeviceId = 8888; // An ID that doesn't exist + boolean exists = deviceOrganizationService.organizationExists(nonExistentDeviceId, nonExistentParentDeviceId); + Assert.assertFalse(exists, "Organization should not exist for non-existent IDs."); + } - DeviceOrganization deviceOrganization = new DeviceOrganization() { + @Test(description = "This method tests Exception Handling when adding a duplicate Device Organization", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testAddDuplicateDeviceOrganization() throws DeviceOrganizationMgtPluginException { + // Create a valid organization + DeviceOrganization validOrganization = new DeviceOrganization() { }; - boolean result = deviceOrganizationService.addDeviceOrganization(deviceOrganization); - } - -// @Test(description = "This method tests Update Device Organization method under negative circumstances with " + -// "invalid data") -// -// public void testUpdateDeviceOrganization() throws DeviceOrganizationMgtPluginException { -// DeviceOrganization deviceOrganization = new DeviceOrganization() { -// }; -// deviceOrganization.setOrganizationId(2); -// deviceOrganization.setDeviceId(7); -// deviceOrganization.setParentDeviceId(6); -// boolean result = deviceOrganizationService.updateDeviceOrganization(deviceOrganization); -// } + validOrganization.setDeviceId(4); + validOrganization.setParentDeviceId(3); + validOrganization.setUpdateTime(new Date(System.currentTimeMillis())); + + try { + // Add the organization once + deviceOrganizationService.addDeviceOrganization(validOrganization); + + // Attempt to add the same organization again, which should throw an exception + deviceOrganizationService.addDeviceOrganization(validOrganization); + } finally { + // Clean up: Delete the added organization if it was successfully added to avoid conflicts in future tests + deviceOrganizationService.deleteDeviceAssociations(validOrganization.getDeviceId()); + } + } + + @Test(description = "This method tests Update Device Organization method under negative circumstances with null " + + "data", expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testUpdateDeviceOrganizationWithInvalidInput() throws DeviceOrganizationMgtPluginException { + DeviceOrganization invalidOrganization = new DeviceOrganization() { + }; + deviceOrganizationService.updateDeviceOrganization(invalidOrganization); + } + + @Test(description = "This method tests Update Device Organization method under negative circumstances with an invalid organization ID", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testUpdateDeviceOrganizationWithInvalidID() throws DeviceOrganizationMgtPluginException { + DeviceOrganization invalidOrganization = new DeviceOrganization() { + }; + invalidOrganization.setOrganizationId(-1); // Provide an invalid organization ID + deviceOrganizationService.updateDeviceOrganization(invalidOrganization); + } + + + @Test(description = "This method tests Get Device Organization By ID method under negative circumstances with " + + "invalid input", + expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testGetDeviceOrganizationByIDWithInvalidInput() throws DeviceOrganizationMgtPluginException { + int invalidOrganizationId = 0; + deviceOrganizationService.getDeviceOrganizationByID(invalidOrganizationId); + } + + @Test(description = "This method tests Delete Device Organization By ID method under negative circumstances with " + + "invalid input", expectedExceptions = {DeviceOrganizationMgtPluginException.class}) + public void testDeleteDeviceOrganizationByIDWithInvalidInput() throws DeviceOrganizationMgtPluginException { + int invalidOrganizationId = 0; + deviceOrganizationService.deleteDeviceOrganizationByID(invalidOrganizationId); + } + + @Test(description = "This method tests Does Device ID Exist method under negative circumstances with invalid input", + expectedExceptions = {BadRequestException.class}) + public void testDoesDeviceIdExistWithInvalidInput() throws DeviceOrganizationMgtPluginException { + int invalidDeviceId = 0; + deviceOrganizationService.doesDeviceIdExist(invalidDeviceId); + } + + @Test(description = "This method tests Delete Device Associations method under negative circumstances with invalid " + + "input", expectedExceptions = {BadRequestException.class}) + public void testDeleteDeviceAssociationsWithInvalidInput() throws DeviceOrganizationMgtPluginException { + int invalidDeviceId = 0; + deviceOrganizationService.deleteDeviceAssociations(invalidDeviceId); + } + } diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceTest.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceTest.java index 2cd52550fa..604d68604e 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceTest.java +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/java/io/entgra/device/mgt/core/device/mgt/extensions/device/organization/ServiceTest.java @@ -12,7 +12,6 @@ import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import java.util.Date; import java.util.List; public class ServiceTest extends BaseDeviceOrganizationTest { @@ -32,7 +31,9 @@ public class ServiceTest extends BaseDeviceOrganizationTest { DeviceNode deviceNode = new DeviceNode(); deviceNode.setDeviceId(2); - List childrenList = deviceOrganizationService.getChildrenOf(deviceNode, 2, true); + int maxDepth = 2; + boolean includeDevice = false; + List childrenList = deviceOrganizationService.getChildrenOf(deviceNode, maxDepth, includeDevice); Assert.assertNotNull(childrenList, "Cannot be null"); } @@ -42,12 +43,16 @@ public class ServiceTest extends BaseDeviceOrganizationTest { DeviceNode deviceNode = new DeviceNode(); deviceNode.setDeviceId(4); - List parentList = deviceOrganizationService.getParentsOf(deviceNode, 2, true); + int maxDepth = 2; + boolean includeDevice = true; + List parentList = deviceOrganizationService.getParentsOf(deviceNode, maxDepth, includeDevice); Assert.assertNotNull(parentList, "Cannot be null"); } - @Test + @Test( +// expectedExceptions = {DeviceOrganizationMgtPluginException.class} + ) public void testAddDeviceOrganization() throws DeviceOrganizationMgtPluginException { @@ -55,25 +60,52 @@ public class ServiceTest extends BaseDeviceOrganizationTest { }; deviceOrganization.setDeviceId(4); deviceOrganization.setParentDeviceId(3); - deviceOrganization.setUpdateTime(new Date(System.currentTimeMillis())); - boolean result = deviceOrganizationService.addDeviceOrganization(deviceOrganization); - DeviceOrganization deviceOrganization1 = new DeviceOrganization() { + DeviceOrganization deviceOrganizationOne = new DeviceOrganization() { }; - deviceOrganization.setDeviceId(3); - deviceOrganization.setParentDeviceId(2); - deviceOrganization.setUpdateTime(new Date(System.currentTimeMillis())); - boolean result1 = deviceOrganizationService.addDeviceOrganization(deviceOrganization); - DeviceOrganization deviceOrganization2 = new DeviceOrganization() { + deviceOrganizationOne.setDeviceId(3); + deviceOrganizationOne.setParentDeviceId(2); + DeviceOrganization deviceOrganizationTwo = new DeviceOrganization() { }; - deviceOrganization.setDeviceId(4); - deviceOrganization.setParentDeviceId(2); - deviceOrganization.setUpdateTime(new Date(System.currentTimeMillis())); - boolean result2 = deviceOrganizationService.addDeviceOrganization(deviceOrganization); - - Assert.assertNotNull(result, "Cannot be null"); + deviceOrganizationTwo.setDeviceId(4); + deviceOrganizationTwo.setParentDeviceId(2); + + try { + boolean result = deviceOrganizationService.addDeviceOrganization(deviceOrganization); + boolean result1 = deviceOrganizationService.addDeviceOrganization(deviceOrganizationOne); + boolean result2 = deviceOrganizationService.addDeviceOrganization(deviceOrganizationTwo); + Assert.assertNotNull(result, "Cannot be null"); + Assert.assertNotNull(result1, "Cannot be null"); + Assert.assertNotNull(result2, "Cannot be null"); + } catch (DeviceOrganizationMgtPluginException e){ + // Clean up: Delete the added organization if it was successfully added to avoid conflicts in future tests + deviceOrganizationService.deleteDeviceAssociations(deviceOrganization.getDeviceId()); + } } +// @Test(description = "This method tests Concurrent Access to Add Device Organization", +// expectedExceptions = {DeviceOrganizationMgtPluginException.class}) +// public void testConcurrentAddDeviceOrganization() throws InterruptedException { +// ExecutorService executor = Executors.newFixedThreadPool(4); +// final DeviceOrganization validOrganization = new DeviceOrganization(){}; +// validOrganization.setDeviceId(3); +// validOrganization.setParentDeviceId(2); +// validOrganization.setUpdateTime(new Date(System.currentTimeMillis())); +// +// for (int i = 0; i < 4; i++) { +// executor.execute(() -> { +// try { +// deviceOrganizationService.addDeviceOrganization(validOrganization); +// } catch (DeviceOrganizationMgtPluginException e) { +// // Handle the exception +// } +// }); +// } +// +// executor.shutdown(); +// executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); +// } + @Test(dependsOnMethods = "testAddDeviceOrganization") public void testUpdateDeviceOrganization() throws DeviceOrganizationMgtPluginException { @@ -96,7 +128,7 @@ public class ServiceTest extends BaseDeviceOrganizationTest { @Test(dependsOnMethods = "testAddDeviceOrganization") public void testDoesDeviceIdExist() throws DeviceOrganizationMgtPluginException { - boolean deviceIdExist = deviceOrganizationService.doesDeviceIdExist(1); + boolean deviceIdExist = deviceOrganizationService.doesDeviceIdExist(1); Assert.assertNotNull(deviceIdExist, "Cannot be null"); } diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/resources/carbon-home/repository/conf/datasources/data-source-config.xml b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/resources/carbon-home/repository/conf/datasources/data-source-config.xml index ad8165fc67..a9c81a4710 100644 --- a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/resources/carbon-home/repository/conf/datasources/data-source-config.xml +++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.device.organization/src/test/resources/carbon-home/repository/conf/datasources/data-source-config.xml @@ -1,4 +1,3 @@ -