diff --git a/dao/pom.xml b/dao/pom.xml index a987326930..1d2d962ba0 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -206,11 +206,6 @@ org.elasticsearch.client rest - - org.junit.jupiter - junit-jupiter-api - RELEASE - diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index 073ccb912e..1e791635c9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -96,8 +96,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC } List nodes = ruleChainMetaData.getNodes(); - List toAdd = new ArrayList<>(); - List toUpdate = new ArrayList<>(); + List toAddOrUpdate = new ArrayList<>(); List toDelete = new ArrayList<>(); Map ruleNodeIndexMap = new HashMap<>(); @@ -106,7 +105,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC if (node.getId() != null) { ruleNodeIndexMap.put(node.getId(), nodes.indexOf(node)); } else { - toAdd.add(node); + toAddOrUpdate.add(node); } } } @@ -116,12 +115,12 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC deleteEntityRelations(existingNode.getId()); Integer index = ruleNodeIndexMap.get(existingNode.getId()); if (index != null) { - toUpdate.add(ruleChainMetaData.getNodes().get(index)); + toAddOrUpdate.add(ruleChainMetaData.getNodes().get(index)); } else { toDelete.add(existingNode); } } - for (RuleNode node : toAdd) { + for (RuleNode node : toAddOrUpdate) { RuleNode savedNode = ruleNodeDao.save(node); try { createRelation(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(), diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java index ffa9f0e7f5..d083a90262 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java @@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentScope; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.plugin.PluginMetaData; +import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleMetaData; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.asset.AssetService; @@ -52,6 +53,7 @@ import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.plugin.PluginService; import org.thingsboard.server.dao.relation.RelationService; +import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleService; import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.dao.tenant.TenantService; @@ -125,6 +127,9 @@ public abstract class AbstractServiceTest { @Autowired protected AlarmService alarmService; + @Autowired + protected RuleChainService ruleChainService; + @Autowired private ComponentDescriptorService componentDescriptorService; diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java new file mode 100644 index 0000000000..28c61475ee --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseRuleChainServiceTest.java @@ -0,0 +1,362 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed 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.thingsboard.server.dao.service; + +import com.datastax.driver.core.utils.UUIDs; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.TextPageData; +import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.common.data.rule.RuleChainMetaData; +import org.thingsboard.server.common.data.rule.RuleNode; +import org.thingsboard.server.dao.exception.DataValidationException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Created by igor on 3/13/18. + */ +public abstract class BaseRuleChainServiceTest extends AbstractServiceTest { + + private IdComparator idComparator = new IdComparator<>(); + private IdComparator ruleNodeIdComparator = new IdComparator<>(); + + private TenantId tenantId; + + @Before + public void before() { + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant"); + Tenant savedTenant = tenantService.saveTenant(tenant); + Assert.assertNotNull(savedTenant); + tenantId = savedTenant.getId(); + } + + @After + public void after() { + tenantService.deleteTenant(tenantId); + } + + @Test + public void testSaveRuleChain() throws IOException { + RuleChain ruleChain = new RuleChain(); + ruleChain.setTenantId(tenantId); + ruleChain.setName("My RuleChain"); + + RuleChain savedRuleChain = ruleChainService.saveRuleChain(ruleChain); + Assert.assertNotNull(savedRuleChain); + Assert.assertNotNull(savedRuleChain.getId()); + Assert.assertTrue(savedRuleChain.getCreatedTime() > 0); + Assert.assertEquals(ruleChain.getTenantId(), savedRuleChain.getTenantId()); + Assert.assertEquals(ruleChain.getName(), savedRuleChain.getName()); + + savedRuleChain.setName("My new RuleChain"); + + ruleChainService.saveRuleChain(savedRuleChain); + RuleChain foundRuleChain = ruleChainService.findRuleChainById(savedRuleChain.getId()); + Assert.assertEquals(foundRuleChain.getName(), savedRuleChain.getName()); + + ruleChainService.deleteRuleChainById(savedRuleChain.getId()); + } + + @Test(expected = DataValidationException.class) + public void testSaveRuleChainWithEmptyName() { + RuleChain ruleChain = new RuleChain(); + ruleChain.setTenantId(tenantId); + ruleChainService.saveRuleChain(ruleChain); + } + + @Test(expected = DataValidationException.class) + public void testSaveRuleChainWithInvalidTenant() { + RuleChain ruleChain = new RuleChain(); + ruleChain.setName("My RuleChain"); + ruleChain.setTenantId(new TenantId(UUIDs.timeBased())); + ruleChainService.saveRuleChain(ruleChain); + } + + @Test + public void testFindRuleChainById() { + RuleChain ruleChain = new RuleChain(); + ruleChain.setTenantId(tenantId); + ruleChain.setName("My RuleChain"); + RuleChain savedRuleChain = ruleChainService.saveRuleChain(ruleChain); + RuleChain foundRuleChain = ruleChainService.findRuleChainById(savedRuleChain.getId()); + Assert.assertNotNull(foundRuleChain); + Assert.assertEquals(savedRuleChain, foundRuleChain); + ruleChainService.deleteRuleChainById(savedRuleChain.getId()); + } + + @Test + public void testDeleteRuleChain() { + RuleChain ruleChain = new RuleChain(); + ruleChain.setTenantId(tenantId); + ruleChain.setName("My RuleChain"); + RuleChain savedRuleChain = ruleChainService.saveRuleChain(ruleChain); + RuleChain foundRuleChain = ruleChainService.findRuleChainById(savedRuleChain.getId()); + Assert.assertNotNull(foundRuleChain); + ruleChainService.deleteRuleChainById(savedRuleChain.getId()); + foundRuleChain = ruleChainService.findRuleChainById(savedRuleChain.getId()); + Assert.assertNull(foundRuleChain); + } + + @Test + public void testFindRuleChainsByTenantId() { + Tenant tenant = new Tenant(); + tenant.setTitle("Test tenant"); + tenant = tenantService.saveTenant(tenant); + + TenantId tenantId = tenant.getId(); + + List ruleChains = new ArrayList<>(); + for (int i = 0; i < 165; i++) { + RuleChain ruleChain = new RuleChain(); + ruleChain.setTenantId(tenantId); + ruleChain.setName("RuleChain" + i); + ruleChains.add(ruleChainService.saveRuleChain(ruleChain)); + } + + List loadedRuleChains = new ArrayList<>(); + TextPageLink pageLink = new TextPageLink(16); + TextPageData pageData = null; + do { + pageData = ruleChainService.findTenantRuleChains(tenantId, pageLink); + loadedRuleChains.addAll(pageData.getData()); + if (pageData.hasNext()) { + pageLink = pageData.getNextPageLink(); + } + } while (pageData.hasNext()); + + Collections.sort(ruleChains, idComparator); + Collections.sort(loadedRuleChains, idComparator); + + Assert.assertEquals(ruleChains, loadedRuleChains); + + ruleChainService.deleteRuleChainsByTenantId(tenantId); + + pageLink = new TextPageLink(31); + pageData = ruleChainService.findTenantRuleChains(tenantId, pageLink); + Assert.assertFalse(pageData.hasNext()); + Assert.assertTrue(pageData.getData().isEmpty()); + + tenantService.deleteTenant(tenantId); + } + + @Test + public void testFindRuleChainsByTenantIdAndName() { + String name1 = "RuleChain name 1"; + List ruleChainsName1 = new ArrayList<>(); + for (int i = 0; i < 123; i++) { + RuleChain ruleChain = new RuleChain(); + ruleChain.setTenantId(tenantId); + String suffix = RandomStringUtils.randomAlphanumeric((int) (Math.random() * 17)); + String name = name1 + suffix; + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); + ruleChain.setName(name); + ruleChainsName1.add(ruleChainService.saveRuleChain(ruleChain)); + } + String name2 = "RuleChain name 2"; + List ruleChainsName2 = new ArrayList<>(); + for (int i = 0; i < 193; i++) { + RuleChain ruleChain = new RuleChain(); + ruleChain.setTenantId(tenantId); + String suffix = RandomStringUtils.randomAlphanumeric((int) (Math.random() * 15)); + String name = name2 + suffix; + name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); + ruleChain.setName(name); + ruleChainsName2.add(ruleChainService.saveRuleChain(ruleChain)); + } + + List loadedRuleChainsName1 = new ArrayList<>(); + TextPageLink pageLink = new TextPageLink(19, name1); + TextPageData pageData = null; + do { + pageData = ruleChainService.findTenantRuleChains(tenantId, pageLink); + loadedRuleChainsName1.addAll(pageData.getData()); + if (pageData.hasNext()) { + pageLink = pageData.getNextPageLink(); + } + } while (pageData.hasNext()); + + Collections.sort(ruleChainsName1, idComparator); + Collections.sort(loadedRuleChainsName1, idComparator); + + Assert.assertEquals(ruleChainsName1, loadedRuleChainsName1); + + List loadedRuleChainsName2 = new ArrayList<>(); + pageLink = new TextPageLink(4, name2); + do { + pageData = ruleChainService.findTenantRuleChains(tenantId, pageLink); + loadedRuleChainsName2.addAll(pageData.getData()); + if (pageData.hasNext()) { + pageLink = pageData.getNextPageLink(); + } + } while (pageData.hasNext()); + + Collections.sort(ruleChainsName2, idComparator); + Collections.sort(loadedRuleChainsName2, idComparator); + + Assert.assertEquals(ruleChainsName2, loadedRuleChainsName2); + + for (RuleChain ruleChain : loadedRuleChainsName1) { + ruleChainService.deleteRuleChainById(ruleChain.getId()); + } + + pageLink = new TextPageLink(4, name1); + pageData = ruleChainService.findTenantRuleChains(tenantId, pageLink); + Assert.assertFalse(pageData.hasNext()); + Assert.assertEquals(0, pageData.getData().size()); + + for (RuleChain ruleChain : loadedRuleChainsName2) { + ruleChainService.deleteRuleChainById(ruleChain.getId()); + } + + pageLink = new TextPageLink(4, name2); + pageData = ruleChainService.findTenantRuleChains(tenantId, pageLink); + Assert.assertFalse(pageData.hasNext()); + Assert.assertEquals(0, pageData.getData().size()); + } + + @Test + public void testSaveRuleChainMetaData() throws Exception { + + RuleChainMetaData savedRuleChainMetaData = createRuleChainMetadata(); + + Assert.assertEquals(3, savedRuleChainMetaData.getNodes().size()); + Assert.assertEquals(3, savedRuleChainMetaData.getConnections().size()); + + for (RuleNode ruleNode : savedRuleChainMetaData.getNodes()) { + Assert.assertNotNull(ruleNode.getId()); + List relations = ruleChainService.getRuleNodeRelations(ruleNode.getId()); + if ("name1".equals(ruleNode.getName())) { + Assert.assertEquals(2, relations.size()); + } else if ("name2".equals(ruleNode.getName())) { + Assert.assertEquals(1, relations.size()); + } else if ("name3".equals(ruleNode.getName())) { + Assert.assertEquals(0, relations.size()); + } + } + + List loadedRuleNodes = ruleChainService.getRuleChainNodes(savedRuleChainMetaData.getRuleChainId()); + + Collections.sort(savedRuleChainMetaData.getNodes(), ruleNodeIdComparator); + Collections.sort(loadedRuleNodes, ruleNodeIdComparator); + + Assert.assertEquals(savedRuleChainMetaData.getNodes(), loadedRuleNodes); + + ruleChainService.deleteRuleChainById(savedRuleChainMetaData.getRuleChainId()); + } + + @Test + public void testUpdateRuleChainMetaData() throws Exception { + RuleChainMetaData savedRuleChainMetaData = createRuleChainMetadata(); + + List ruleNodes = savedRuleChainMetaData.getNodes(); + int name3Index = -1; + for (int i=0;i relations = ruleChainService.getRuleNodeRelations(ruleNode.getId()); + if ("name1".equals(ruleNode.getName())) { + Assert.assertEquals(2, relations.size()); + } else if ("name2".equals(ruleNode.getName())) { + Assert.assertEquals(1, relations.size()); + } else if ("name4".equals(ruleNode.getName())) { + Assert.assertEquals(0, relations.size()); + } + } + + List loadedRuleNodes = ruleChainService.getRuleChainNodes(savedRuleChainMetaData.getRuleChainId()); + + Collections.sort(updatedRuleChainMetaData.getNodes(), ruleNodeIdComparator); + Collections.sort(loadedRuleNodes, ruleNodeIdComparator); + + Assert.assertEquals(updatedRuleChainMetaData.getNodes(), loadedRuleNodes); + + ruleChainService.deleteRuleChainById(savedRuleChainMetaData.getRuleChainId()); + } + + private RuleChainMetaData createRuleChainMetadata() throws Exception { + RuleChain ruleChain = new RuleChain(); + ruleChain.setName("My RuleChain"); + ruleChain.setTenantId(tenantId); + RuleChain savedRuleChain = ruleChainService.saveRuleChain(ruleChain); + + RuleChainMetaData ruleChainMetaData = new RuleChainMetaData(); + ruleChainMetaData.setRuleChainId(savedRuleChain.getId()); + + ObjectMapper mapper = new ObjectMapper(); + + RuleNode ruleNode1 = new RuleNode(); + ruleNode1.setName("name1"); + ruleNode1.setType("type1"); + ruleNode1.setConfiguration(mapper.readTree("\"key1\": \"val1\"")); + + RuleNode ruleNode2 = new RuleNode(); + ruleNode2.setName("name2"); + ruleNode2.setType("type2"); + ruleNode2.setConfiguration(mapper.readTree("\"key2\": \"val2\"")); + + RuleNode ruleNode3 = new RuleNode(); + ruleNode3.setName("name3"); + ruleNode3.setType("type3"); + ruleNode3.setConfiguration(mapper.readTree("\"key3\": \"val3\"")); + + List ruleNodes = new ArrayList<>(); + ruleNodes.add(ruleNode1); + ruleNodes.add(ruleNode2); + ruleNodes.add(ruleNode3); + ruleChainMetaData.setFirstNodeIndex(0); + ruleChainMetaData.setNodes(ruleNodes); + + ruleChainMetaData.addConnectionInfo(0,1,"success"); + ruleChainMetaData.addConnectionInfo(0,2,"fail"); + ruleChainMetaData.addConnectionInfo(1,2,"success"); + + return ruleChainService.saveRuleChainMetaData(ruleChainMetaData); + } + + +} diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/nosql/RuleChainServiceNoSqlTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/nosql/RuleChainServiceNoSqlTest.java new file mode 100644 index 0000000000..0427eebe05 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/nosql/RuleChainServiceNoSqlTest.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed 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.thingsboard.server.dao.service.nosql; + +import org.thingsboard.server.dao.service.BaseRuleChainServiceTest; +import org.thingsboard.server.dao.service.DaoNoSqlTest; + +@DaoNoSqlTest +public class RuleChainServiceNoSqlTest extends BaseRuleChainServiceTest { +} diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/UnprocessedMsgFilterTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/UnprocessedMsgFilterTest.java index 046b462064..6302e63f89 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/UnprocessedMsgFilterTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/UnprocessedMsgFilterTest.java @@ -23,7 +23,7 @@ import java.util.Collection; import java.util.List; import java.util.UUID; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.Assert.assertEquals; public class UnprocessedMsgFilterTest { diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/sql/RuleChainServiceSqlTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/sql/RuleChainServiceSqlTest.java new file mode 100644 index 0000000000..d877037ddb --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/sql/RuleChainServiceSqlTest.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed 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.thingsboard.server.dao.service.sql; + +import org.thingsboard.server.dao.service.BaseRuleChainServiceTest; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +public class RuleChainServiceSqlTest extends BaseRuleChainServiceTest { +} diff --git a/dao/src/test/resources/sql/drop-all-tables.sql b/dao/src/test/resources/sql/drop-all-tables.sql index dfdc90fc35..c28e5994cd 100644 --- a/dao/src/test/resources/sql/drop-all-tables.sql +++ b/dao/src/test/resources/sql/drop-all-tables.sql @@ -18,4 +18,6 @@ DROP TABLE IF EXISTS ts_kv; DROP TABLE IF EXISTS ts_kv_latest; DROP TABLE IF EXISTS user_credentials; DROP TABLE IF EXISTS widget_type; -DROP TABLE IF EXISTS widgets_bundle; \ No newline at end of file +DROP TABLE IF EXISTS widgets_bundle; +DROP TABLE IF EXISTS rule_node; +DROP TABLE IF EXISTS rule_chain; \ No newline at end of file