Tests added to validate DefaultRuleChains and EdgeDefaultRuleChains json templates
This commit is contained in:
parent
88f10881b2
commit
eaa9a9b9cc
@ -28,7 +28,6 @@ import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.WidgetTypeId;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
|
||||
@ -104,7 +103,7 @@ public class InstallScripts {
|
||||
@Autowired
|
||||
private ResourceService resourceService;
|
||||
|
||||
private Path getTenantRuleChainsDir() {
|
||||
Path getTenantRuleChainsDir() {
|
||||
return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR);
|
||||
}
|
||||
|
||||
@ -112,7 +111,7 @@ public class InstallScripts {
|
||||
return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, DEVICE_PROFILE_DIR, "rule_chain_template.json");
|
||||
}
|
||||
|
||||
private Path getEdgeRuleChainsDir() {
|
||||
Path getEdgeRuleChainsDir() {
|
||||
return Paths.get(getDataDir(), JSON_DIR, EDGE_DIR, RULE_CHAINS_DIR);
|
||||
}
|
||||
|
||||
@ -148,8 +147,8 @@ public class InstallScripts {
|
||||
}
|
||||
|
||||
private void loadRuleChainsFromPath(TenantId tenantId, Path ruleChainsPath) throws IOException {
|
||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(ruleChainsPath, path -> path.toString().endsWith(InstallScripts.JSON_EXT))) {
|
||||
dirStream.forEach(
|
||||
findRuleChainsFromPath(ruleChainsPath)
|
||||
.forEach(
|
||||
path -> {
|
||||
try {
|
||||
createRuleChainFromFile(tenantId, path, null);
|
||||
@ -157,9 +156,15 @@ public class InstallScripts {
|
||||
log.error("Unable to load rule chain from json: [{}]", path.toString());
|
||||
throw new RuntimeException("Unable to load rule chain from json", e);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
List<Path> findRuleChainsFromPath(Path ruleChainsPath) throws IOException {
|
||||
List<Path> paths = new ArrayList<>();
|
||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(ruleChainsPath, path -> path.toString().endsWith(InstallScripts.JSON_EXT))) {
|
||||
dirStream.forEach(paths::add);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
public RuleChain createDefaultRuleChain(TenantId tenantId, String ruleChainName) throws IOException {
|
||||
|
||||
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright © 2016-2023 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.service.install;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
|
||||
import org.thingsboard.server.dao.dashboard.DashboardService;
|
||||
import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
|
||||
import org.thingsboard.server.dao.resource.ResourceService;
|
||||
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||
import org.thingsboard.server.dao.service.validator.RuleChainDataValidator;
|
||||
import org.thingsboard.server.dao.tenant.TenantService;
|
||||
import org.thingsboard.server.dao.usagerecord.ApiLimitService;
|
||||
import org.thingsboard.server.dao.widget.WidgetTypeService;
|
||||
import org.thingsboard.server.dao.widget.WidgetsBundleService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.willReturn;
|
||||
|
||||
@SpringBootTest(classes = {InstallScripts.class, RuleChainDataValidator.class})
|
||||
class InstallScriptsTest {
|
||||
|
||||
@MockBean
|
||||
RuleChainService ruleChainService;
|
||||
@MockBean
|
||||
DashboardService dashboardService;
|
||||
@MockBean
|
||||
WidgetTypeService widgetTypeService;
|
||||
@MockBean
|
||||
WidgetsBundleService widgetsBundleService;
|
||||
@MockBean
|
||||
OAuth2ConfigTemplateService oAuth2TemplateService;
|
||||
@MockBean
|
||||
ResourceService resourceService;
|
||||
@SpyBean
|
||||
InstallScripts installScripts;
|
||||
|
||||
@MockBean
|
||||
TenantService tenantService;
|
||||
@MockBean
|
||||
ApiLimitService apiLimitService;
|
||||
@SpyBean
|
||||
RuleChainDataValidator ruleChainValidator;
|
||||
TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da"));
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
willReturn(true).given(tenantService).tenantExists(tenantId);
|
||||
willReturn(true).given(apiLimitService).checkEntitiesLimit(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultRuleChainsTemplates() throws IOException {
|
||||
Path tenantRuleChainsDir = installScripts.getTenantRuleChainsDir();
|
||||
List<Path> ruleChainsFromPath = installScripts.findRuleChainsFromPath(tenantRuleChainsDir);
|
||||
ruleChainsFromPath.forEach(this::validateRuleChainTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultEdgeRuleChainsTemplates() throws IOException {
|
||||
Path edgeChainsDir = installScripts.getEdgeRuleChainsDir();
|
||||
List<Path> ruleChainsFromPath = installScripts.findRuleChainsFromPath(edgeChainsDir);
|
||||
ruleChainsFromPath.forEach(this::validateRuleChainTemplate);
|
||||
}
|
||||
|
||||
private void validateRuleChainTemplate(Path templateFilePath) {
|
||||
JsonNode ruleChainJson = JacksonUtil.toJsonNode(templateFilePath.toFile());
|
||||
|
||||
RuleChain ruleChain = JacksonUtil.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class);
|
||||
ruleChain.setTenantId(tenantId);
|
||||
ruleChainValidator.validate(ruleChain, RuleChain::getTenantId);
|
||||
ruleChain.setId(new RuleChainId(UUID.randomUUID()));
|
||||
|
||||
RuleChainMetaData ruleChainMetaData = JacksonUtil.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class);
|
||||
ruleChainMetaData.setRuleChainId(ruleChain.getId());
|
||||
List<Throwable> throwables = RuleChainDataValidator.validateMetaData(ruleChainMetaData);
|
||||
|
||||
assertThat(throwables).as("templateFilePath " + templateFilePath)
|
||||
.containsExactlyInAnyOrderElementsOf(Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
|
||||
import org.thingsboard.server.common.data.rule.RuleNode;
|
||||
import org.thingsboard.server.common.data.util.ReflectionUtils;
|
||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||
import org.thingsboard.server.dao.rule.RuleChainDao;
|
||||
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||
import org.thingsboard.server.dao.service.ConstraintValidator;
|
||||
import org.thingsboard.server.dao.service.DataValidator;
|
||||
@ -41,15 +40,14 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RuleChainDataValidator extends DataValidator<RuleChain> {
|
||||
|
||||
@Autowired
|
||||
private RuleChainDao ruleChainDao;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RuleChainService ruleChainService;
|
||||
@ -88,15 +86,19 @@ public class RuleChainDataValidator extends DataValidator<RuleChain> {
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateMetaData(RuleChainMetaData ruleChainMetaData) {
|
||||
public static List<Throwable> validateMetaData(RuleChainMetaData ruleChainMetaData) {
|
||||
ConstraintValidator.validateFields(ruleChainMetaData);
|
||||
ruleChainMetaData.getNodes().forEach(RuleChainDataValidator::validateRuleNode);
|
||||
List<Throwable> throwables = ruleChainMetaData.getNodes().stream()
|
||||
.map(RuleChainDataValidator::validateRuleNode)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtils.isNotEmpty(ruleChainMetaData.getConnections())) {
|
||||
validateCircles(ruleChainMetaData.getConnections());
|
||||
}
|
||||
return throwables;
|
||||
}
|
||||
|
||||
public static void validateRuleNode(RuleNode ruleNode) {
|
||||
public static Throwable validateRuleNode(RuleNode ruleNode) {
|
||||
String errorPrefix = "'" + ruleNode.getName() + "' node configuration is invalid: ";
|
||||
ConstraintValidator.validateFields(ruleNode, errorPrefix);
|
||||
Object nodeConfig;
|
||||
@ -104,11 +106,12 @@ public class RuleChainDataValidator extends DataValidator<RuleChain> {
|
||||
Class<Object> nodeConfigType = ReflectionUtils.getAnnotationProperty(ruleNode.getType(),
|
||||
"org.thingsboard.rule.engine.api.RuleNode", "configClazz");
|
||||
nodeConfig = JacksonUtil.treeToValue(ruleNode.getConfiguration(), nodeConfigType);
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to validate node configuration: {}", ExceptionUtils.getRootCauseMessage(e));
|
||||
return;
|
||||
} catch (Throwable t) {
|
||||
log.warn("Failed to validate node configuration: {}", ExceptionUtils.getRootCauseMessage(t));
|
||||
return t;
|
||||
}
|
||||
ConstraintValidator.validateFields(nodeConfig, errorPrefix);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void validateCircles(List<NodeConnectionInfo> connectionInfos) {
|
||||
|
||||
@ -23,7 +23,6 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
import org.thingsboard.server.common.data.rule.RuleChainType;
|
||||
import org.thingsboard.server.dao.rule.RuleChainDao;
|
||||
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||
import org.thingsboard.server.dao.tenant.TenantService;
|
||||
|
||||
@ -35,8 +34,6 @@ import static org.mockito.Mockito.verify;
|
||||
@SpringBootTest(classes = RuleChainDataValidator.class)
|
||||
class RuleChainDataValidatorTest {
|
||||
|
||||
@MockBean
|
||||
RuleChainDao ruleChainDao;
|
||||
@MockBean
|
||||
RuleChainService ruleChainService;
|
||||
@MockBean
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user