From 13b3d5d42bae10ce2733c86814177c3e31eb2014 Mon Sep 17 00:00:00 2001 From: "mark.j.leonard" Date: Thu, 14 Feb 2019 13:51:11 +0000 Subject: Add support for common rules across types Refactor the Rule Driven Validator implementation for loading the Groovy rules. Firstly, support multiple top-level folders. Secondly, include each top-level folder in the set of paths to search for *.groovy files. Pull a common rule up to the top-level to remove the duplication. Add tests to exercise the exception handling code. Change-Id: Ib70fe03ab5b1f2f8c1711760236b07850aaaa398 Issue-ID: AAI-2155 Signed-off-by: mark.j.leonard --- .../etc/rules/aai-event/entity-generic-vnf.groovy | 21 +-- bundleconfig/etc/rules/common_rules.groovy | 30 +++++ .../etc/rules/gizmo-event/common_rules.groovy | 27 ---- .../etc/rules/spike-event/common_rules.groovy | 27 ---- .../validation/ruledriven/RuleDrivenValidator.java | 141 +++++++++++++++------ .../aai/validation/ruledriven/rule/GroovyRule.java | 16 ++- .../onap/aai/validation/ruledriven/rule/Rule.java | 15 ++- .../ruledriven/mock/TestDefaultRules.java | 23 ++-- .../ruledriven/rule/TestConfigurationLoader.java | 48 +++---- .../ruledriven/validator/TestDataDictionary.java | 5 + .../validator/TestRuleDrivenValidator.java | 86 ++++++++----- .../dummy_event_type/oxm_missing.groovy | 39 ++++++ 12 files changed, 292 insertions(+), 186 deletions(-) create mode 100644 bundleconfig/etc/rules/common_rules.groovy delete mode 100644 bundleconfig/etc/rules/gizmo-event/common_rules.groovy delete mode 100644 bundleconfig/etc/rules/spike-event/common_rules.groovy create mode 100644 src/test/resources/rule-driven-validator/missing_oxm/dummy_event_type/oxm_missing.groovy diff --git a/bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy b/bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy index d813eea..71bbd6a 100644 --- a/bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy +++ b/bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy @@ -1,7 +1,10 @@ /* - * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs - * ============================================================================ + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ * 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 @@ -13,7 +16,7 @@ * 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. - * ============LICENSE_END===================================================== + * ============LICENSE_END========================================================= */ entity { @@ -34,16 +37,6 @@ entity { } } -rule { - name 'valid_ipv4_addr' - category 'INVALID_VALUE' - description 'Validate an IPv4 address' - errorText 'Invalid value - attribute is not a valid IPv4 address' - severity 'MINOR' - attributes 'ipaddr' - validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' -} - // If generic-vnf.equipment-role="UCPE" and there is an l-interface - then there must be an IPV4 address related to the l-interface rule { name 'ipv4_addr_present' diff --git a/bundleconfig/etc/rules/common_rules.groovy b/bundleconfig/etc/rules/common_rules.groovy new file mode 100644 index 0000000..36e8132 --- /dev/null +++ b/bundleconfig/etc/rules/common_rules.groovy @@ -0,0 +1,30 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +rule { + name 'valid_ipv4_addr' + category 'INVALID_VALUE' + description 'Validate an IPv4 address' + errorText 'Invalid value - attribute is not a valid IPv4 address' + severity 'MINOR' + attributes 'ipaddr' + validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' +} \ No newline at end of file diff --git a/bundleconfig/etc/rules/gizmo-event/common_rules.groovy b/bundleconfig/etc/rules/gizmo-event/common_rules.groovy deleted file mode 100644 index b30816e..0000000 --- a/bundleconfig/etc/rules/gizmo-event/common_rules.groovy +++ /dev/null @@ -1,27 +0,0 @@ -/* - * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs - * ============================================================================ - * 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. - * ============LICENSE_END===================================================== - */ - -rule { - name 'valid_ipv4_addr' - category 'INVALID_VALUE' - description 'Validate an IPv4 address' - errorText 'Invalid value - attribute is not a valid IPv4 address' - severity 'MINOR' - attributes 'ipaddr' - validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' -} diff --git a/bundleconfig/etc/rules/spike-event/common_rules.groovy b/bundleconfig/etc/rules/spike-event/common_rules.groovy deleted file mode 100644 index b30816e..0000000 --- a/bundleconfig/etc/rules/spike-event/common_rules.groovy +++ /dev/null @@ -1,27 +0,0 @@ -/* - * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs - * ============================================================================ - * 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. - * ============LICENSE_END===================================================== - */ - -rule { - name 'valid_ipv4_addr' - category 'INVALID_VALUE' - description 'Validate an IPv4 address' - errorText 'Invalid value - attribute is not a valid IPv4 address' - severity 'MINOR' - attributes 'ipaddr' - validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' -} diff --git a/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java b/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java index 4b22d77..5ca7025 100644 --- a/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java +++ b/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java @@ -27,7 +27,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -36,6 +35,8 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang.StringUtils; import org.onap.aai.validation.Validator; @@ -68,7 +69,12 @@ public class RuleDrivenValidator implements Validator { private static final String RULES_CONFIG_FILE_SUFFIX = ".groovy"; - private Path configurationPath; + /** + * The set of directories/folders containing the rules configuration files. Rules that are common to all event types + * will be stored in a file directly under a specified Path. Rules which are specific to a named event type will be + * stored in a direct child directory. + */ + private Collection configurationPaths; private OxmReader oxmReader; private EventReader eventReader; private Optional ruleIndexingConfig; @@ -78,17 +84,17 @@ public class RuleDrivenValidator implements Validator { /** * Construct a Validator that is configured using rule files. * - * @param configurationPath - * path to the Groovy rules files + * @param configurationPaths + * paths to the Groovy rules files and sub-folders * @param oxmReader * required for validating entity types * @param eventReader * a reader for extracting entities from each event to be validated * @param ruleIndexingConfig */ - public RuleDrivenValidator(final Path configurationPath, final OxmReader oxmReader, final EventReader eventReader, - final RuleIndexingConfig ruleIndexingConfig) { - this.configurationPath = configurationPath; + public RuleDrivenValidator(final List configurationPaths, final OxmReader oxmReader, + final EventReader eventReader, final RuleIndexingConfig ruleIndexingConfig) { + this.configurationPaths = configurationPaths; this.oxmReader = oxmReader; this.eventReader = eventReader; this.ruleIndexingConfig = Optional.ofNullable(ruleIndexingConfig); @@ -104,38 +110,6 @@ public class RuleDrivenValidator implements Validator { validateRulesConfiguration(); } - private RuleManager loadRulesConfiguration(String eventType) throws ValidationServiceException { - StringBuilder rulesText = new StringBuilder(); - try (Stream paths = Files.find(configurationPath.resolve(eventType), 1, - (path, basicFileAttributes) -> path.toFile().getName().matches(".*\\" + RULES_CONFIG_FILE_SUFFIX));) { - paths.forEach(appendFileContent(rulesText)); - } catch (IOException e) { - throw new ValidationServiceException(ValidationServiceError.RULES_FILE_ERROR, - configurationPath.toAbsolutePath(), e); - } - - try { - return RulesConfigurationLoader.loadConfiguration(rulesText.toString()); - } catch (GroovyConfigurationException e) { - throw new ValidationServiceException(ValidationServiceError.RULES_FILE_ERROR, e, - configurationPath.toAbsolutePath() + File.separator + "*" + RULES_CONFIG_FILE_SUFFIX); - } - } - - private void validateRulesConfiguration() throws ValidationServiceException { - for (RuleManager ruleManager : ruleManagers.values()) { - for (EntitySection entity : ruleManager.getEntities()) { - if (ruleIndexingConfig.isPresent() && ruleIndexingConfig.get().skipOxmValidation(entity.getName())) { - continue; - } - if (oxmReader != null && oxmReader.getPrimaryKeys(entity.getName()).isEmpty()) { - throw new ValidationServiceException(ValidationServiceError.OXM_MISSING_KEY, - entity.getName() + " defined in " + configurationPath.toAbsolutePath() + File.separator - + "*" + RULES_CONFIG_FILE_SUFFIX); - } - } - } - } /** * Helper method to expose the configured rules. This simplifies testing of the validator. @@ -203,6 +177,81 @@ public class RuleDrivenValidator implements Validator { return validationResults; } + /** + * Find and concatenate the text content of all common rules files, and all the eventType-specific rules files. + * Invoke the Configuration Loader to parse the text content and create the Groovy Rules. + * + * @param eventType + * @return + * @throws ValidationServiceException + */ + private RuleManager loadRulesConfiguration(String eventType) throws ValidationServiceException { + StringBuilder rulesText = new StringBuilder(); + + Stream.concat(getGroovyRulePaths(Optional.of(eventType)), getGroovyRulePaths(Optional.empty())) + .forEach(appendFileContent(rulesText)); + + try { + return RulesConfigurationLoader.loadConfiguration(rulesText.toString()); + } catch (GroovyConfigurationException e) { + throw new ValidationServiceException(ValidationServiceError.RULES_FILE_ERROR, e, + getConfigurationPathWildcards()); + } + } + + /** + * For logging and error reporting purposes, create a set of Strings each formatted to document the top-level + * folders for rules configuration files, and also the file suffix used to find the files. + * + * @return all the wildcard patterns used for matching rules files + */ + private List getConfigurationPathWildcards() { + return configurationPaths.stream() + .map(path -> path.toAbsolutePath() + File.separator + "*" + RULES_CONFIG_FILE_SUFFIX) + .collect(Collectors.toList()); + } + + /** + * Find all files matching the rules configuration file suffix that are immediate children of a rules configuration + * Path. If a subPath is specified then only find files in the resolved subPath. + * + * @param subPath + * an optional subPath (e.g. for an event type) + * @return all rules configuration files as Paths + * @throws ValidationServiceException + * if an I/O error occurs when accessing the file system + */ + private Stream getGroovyRulePaths(Optional subPath) throws ValidationServiceException { + List groovyRules = new ArrayList<>(); + for (Path configPath : configurationPaths) { + Path rulesPath = subPath.map(configPath::resolve).orElse(configPath); + if (rulesPath.toFile().exists()) { + try (Stream stream = Files.find(rulesPath, 1, (path, basicFileAttributes) -> path.toFile() + .getName().matches(".*\\" + RULES_CONFIG_FILE_SUFFIX));) { + groovyRules.addAll(stream.collect(Collectors.toList())); + } catch (IOException e) { + throw new ValidationServiceException(ValidationServiceError.RULES_FILE_ERROR, + configPath.toAbsolutePath(), e); + } + } + } + return groovyRules.stream(); + } + + private void validateRulesConfiguration() throws ValidationServiceException { + for (RuleManager ruleManager : ruleManagers.values()) { + for (EntitySection entity : ruleManager.getEntities()) { + if (ruleIndexingConfig.isPresent() && ruleIndexingConfig.get().skipOxmValidation(entity.getName())) { + continue; + } + if (oxmReader != null && oxmReader.getPrimaryKeys(entity.getName()).isEmpty()) { + throw new ValidationServiceException(ValidationServiceError.OXM_MISSING_KEY, + entity.getName() + " defined in " + getConfigurationPathWildcards()); + } + } + } + } + private Optional> getRulesToApply(Entity entity, Optional eventType) throws ValidationServiceException { Optional> rules = Optional.empty(); @@ -292,7 +341,17 @@ public class RuleDrivenValidator implements Validator { } private Collection getSupportedEventTypes() { - String[] list = configurationPath.toFile().list((current, name) -> new File(current, name).isDirectory()); - return list == null ? Collections.emptyList() : Arrays.asList(list); + Function> getDirectories = path -> { + try { + return Files.walk(path, 1).filter(Files::isDirectory); + } catch (IOException e) { + applicationLogger.error(ApplicationMsgs.READ_FILE_ERROR, e, "from the rules configuration path"); + return Stream.empty(); + } + }; + return configurationPaths.stream() // + .flatMap(getDirectories) // + .map(path -> path.getFileName().toString()) // + .collect(Collectors.toList()); } } diff --git a/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java b/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java index df15791..d8cd61e 100644 --- a/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java +++ b/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java @@ -1,19 +1,22 @@ -/* - * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs - * ============================================================================ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ * 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 + * 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. - * ============LICENSE_END===================================================== + * ============LICENSE_END========================================================= */ package org.onap.aai.validation.ruledriven.rule; @@ -65,7 +68,6 @@ public class GroovyRule implements Rule { private boolean ruleIsValid = true; private String name; - /** * @param ruleConfig * @throws InstantiationException diff --git a/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java b/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java index 60705ea..e4c2078 100644 --- a/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java +++ b/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java @@ -1,19 +1,22 @@ -/* - * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs - * ============================================================================ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ * 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 + * 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. - * ============LICENSE_END===================================================== + * ============LICENSE_END========================================================= */ package org.onap.aai.validation.ruledriven.rule; diff --git a/src/test/java/org/onap/aai/validation/ruledriven/mock/TestDefaultRules.java b/src/test/java/org/onap/aai/validation/ruledriven/mock/TestDefaultRules.java index c3b36ed..41721ba 100644 --- a/src/test/java/org/onap/aai/validation/ruledriven/mock/TestDefaultRules.java +++ b/src/test/java/org/onap/aai/validation/ruledriven/mock/TestDefaultRules.java @@ -1,20 +1,24 @@ -/* - * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs - * ============================================================================ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ * 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 + * 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. - * ============LICENSE_END===================================================== + * ============LICENSE_END========================================================= */ + package org.onap.aai.validation.ruledriven.mock; import static org.hamcrest.CoreMatchers.equalTo; @@ -61,8 +65,7 @@ public class TestDefaultRules { } enum TestCase { - NULL, - VSERVER; + NULL, VSERVER; } // Data returned by the mocked EventReader @@ -125,8 +128,8 @@ public class TestDefaultRules { @Before public void createRuleDrivenValidator() throws ValidationServiceException { - Path configurationPath = Paths.get("bundleconfig/etc/rules"); - ruleDrivenValidator = new RuleDrivenValidator(configurationPath, null, eventReader, null); + List configurationPaths = Collections.singletonList(Paths.get("bundleconfig/etc/rules")); + ruleDrivenValidator = new RuleDrivenValidator(configurationPaths, null, eventReader, null); } @Test diff --git a/src/test/java/org/onap/aai/validation/ruledriven/rule/TestConfigurationLoader.java b/src/test/java/org/onap/aai/validation/ruledriven/rule/TestConfigurationLoader.java index a70d908..e074bcd 100644 --- a/src/test/java/org/onap/aai/validation/ruledriven/rule/TestConfigurationLoader.java +++ b/src/test/java/org/onap/aai/validation/ruledriven/rule/TestConfigurationLoader.java @@ -1,20 +1,24 @@ -/* - * ============LICENSE_START=================================================== - * Copyright (c) 2018 Amdocs - * ============================================================================ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ * 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 + * 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. - * ============LICENSE_END===================================================== + * ============LICENSE_END========================================================= */ + package org.onap.aai.validation.ruledriven.rule; import com.google.gson.JsonArray; @@ -22,7 +26,9 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import javax.inject.Inject; import org.junit.Test; @@ -36,25 +42,24 @@ public class TestConfigurationLoader { System.setProperty("APP_HOME", "."); } - private enum AAIRelation { + private static final String RULES_PATH = "bundleconfig/etc/rules"; + + private enum AaiRelation { + // @formatter:off RELATED_TO("related-to"), PROPERTY_KEY("property-key"), PROPERTY_VALUE("property-value"); + // @formatter:on private final String text; /** * @param text */ - private AAIRelation(final String text) { + private AaiRelation(final String text) { this.text = text; } - /* - * (non-Javadoc) - * - * @see java.lang.Enum#toString() - */ @Override public String toString() { return text; @@ -69,9 +74,8 @@ public class TestConfigurationLoader { */ @Test public void testTrinityRule() throws Exception { - Path configurationPath = Paths.get("bundleconfig/etc/rules"); - - RuleDrivenValidator validator = new RuleDrivenValidator(configurationPath, oxmReader, null, null); + List configurationPaths = Collections.singletonList(Paths.get(RULES_PATH)); + RuleDrivenValidator validator = new RuleDrivenValidator(configurationPaths, oxmReader, null, null); validator.initialise(); // Find the trinity rule @@ -91,18 +95,18 @@ public class TestConfigurationLoader { RuleTester ruleTester = new RuleTester(trinityRule, attributeValues); ruleTester.test(true); - JsonObject genericVnfData = createRelationshipData(relationships, "generic-vnf"); + final JsonObject genericVnfData = createRelationshipData(relationships, "generic-vnf"); ruleTester.test(true); // Add a new object for the image relationship - JsonObject imageData = createRelationshipData(relationships, "image"); + final JsonObject imageData = createRelationshipData(relationships, "image"); ruleTester.test(true); createRelationshipData(relationships, "pserver"); ruleTester.test(true); // Add a new JSON object for the image name - JsonObject imageNameProperty = createRelatedToProperty(imageData); + final JsonObject imageNameProperty = createRelatedToProperty(imageData); ruleTester.test(true); setPropertyKey(imageNameProperty, "image.image-name"); @@ -174,16 +178,16 @@ public class TestConfigurationLoader { */ private JsonObject createRelationshipData(Set relationships, String relatedObject) { JsonObject relationData = new JsonObject(); - relationData.addProperty(AAIRelation.RELATED_TO.toString(), relatedObject); + relationData.addProperty(AaiRelation.RELATED_TO.toString(), relatedObject); relationships.add(relationData); return relationData; } private void setPropertyKey(JsonObject objectMap, String propertyKeyName) { - objectMap.addProperty(AAIRelation.PROPERTY_KEY.toString(), propertyKeyName); + objectMap.addProperty(AaiRelation.PROPERTY_KEY.toString(), propertyKeyName); } private void setPropertyValue(JsonObject objectMap, String propertyValue) { - objectMap.addProperty(AAIRelation.PROPERTY_VALUE.toString(), propertyValue); + objectMap.addProperty(AaiRelation.PROPERTY_VALUE.toString(), propertyValue); } } diff --git a/src/test/java/org/onap/aai/validation/ruledriven/validator/TestDataDictionary.java b/src/test/java/org/onap/aai/validation/ruledriven/validator/TestDataDictionary.java index c3bad43..7292dec 100644 --- a/src/test/java/org/onap/aai/validation/ruledriven/validator/TestDataDictionary.java +++ b/src/test/java/org/onap/aai/validation/ruledriven/validator/TestDataDictionary.java @@ -40,6 +40,11 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * Use Spring XML to create an instance of {@link RuleDrivenValidator} that is configured to use Data Dictionary based + * Validation Rules. + * + */ @RunWith(SpringJUnit4ClassRunner.class) @TestPropertySource(locations = {"classpath:oxm-reader/schemaIngest.properties"}) @ContextConfiguration(locations = {"classpath:data-dictionary/test-data-dictionary-beans.xml"}) diff --git a/src/test/java/org/onap/aai/validation/ruledriven/validator/TestRuleDrivenValidator.java b/src/test/java/org/onap/aai/validation/ruledriven/validator/TestRuleDrivenValidator.java index 643e2e3..27039a0 100644 --- a/src/test/java/org/onap/aai/validation/ruledriven/validator/TestRuleDrivenValidator.java +++ b/src/test/java/org/onap/aai/validation/ruledriven/validator/TestRuleDrivenValidator.java @@ -1,20 +1,24 @@ -/* - * ============LICENSE_START=================================================== - * Copyright (c) 2018-2019 Amdocs - * ============================================================================ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ * 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 + * 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. - * ============LICENSE_END===================================================== + * ============LICENSE_END========================================================= */ + package org.onap.aai.validation.ruledriven.validator; import static org.hamcrest.CoreMatchers.is; @@ -24,11 +28,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import com.google.gson.JsonSyntaxException; import java.io.IOException; import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.function.BiPredicate; import java.util.stream.Stream; @@ -36,6 +42,8 @@ import javax.inject.Inject; import org.junit.Test; import org.junit.runner.RunWith; import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.reader.EventReader; +import org.onap.aai.validation.reader.OxmReader; import org.onap.aai.validation.result.ValidationResult; import org.onap.aai.validation.ruledriven.RuleDrivenValidator; import org.onap.aai.validation.test.util.TestEntity; @@ -45,9 +53,9 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@TestPropertySource(locations = { "classpath:oxm-reader/schemaIngest.properties" }) -@ContextConfiguration(locations = { - "classpath:" + TestRuleDrivenValidator.UNIT_TEST_FOLDER + "/test-rule-driven-validator-beans.xml" }) +@TestPropertySource(locations = {"classpath:oxm-reader/schemaIngest.properties"}) +@ContextConfiguration( + locations = {"classpath:" + TestRuleDrivenValidator.UNIT_TEST_FOLDER + "/test-rule-driven-validator-beans.xml"}) public class TestRuleDrivenValidator { static { @@ -60,16 +68,12 @@ public class TestRuleDrivenValidator { @Inject private RuleDrivenValidator validator; - /** - * @param testEntitiesPath - * @param testEventsPath - * @param resultsPath - * @return all test entities - * @throws URISyntaxException - */ + @Inject + private OxmReader oxmReader; + public static List getEntities(String testEntitiesPath, String testEventsPath, String resultsPath) throws URISyntaxException { - Path testEvents = Paths.get(ClassLoader.getSystemResource(testEntitiesPath + testEventsPath).toURI()); + Path testEvents = findResource(testEntitiesPath, testEventsPath); BiPredicate jsonMatcher = (path, basicFileAttributes) -> path.toFile().getName().matches(".*\\.json"); @@ -84,26 +88,44 @@ public class TestRuleDrivenValidator { return entitiesList; } - /** - * @throws ValidationServiceException - * @throws JsonSyntaxException - * @throws URISyntaxException - * @throws IOException - */ + @Test + public void testInvalidRulesPath() throws ValidationServiceException, URISyntaxException { + validator = buildValidator(null, "/non-existent-folder"); + validator.initialise(); + } + + @Test + public void testNoRulesFilesExist() throws ValidationServiceException, URISyntaxException { + validator = buildValidator(null, "/test_events"); + validator.initialise(); + } + + @Test(expected = ValidationServiceException.class) + public void testEntityMissingFromOxm() throws ValidationServiceException, URISyntaxException { + validator = buildValidator(oxmReader, "/missing_oxm"); + validator.initialise(); + } + @Test public void testValidateUnitTestInstances() throws ValidationServiceException, JsonSyntaxException, URISyntaxException, IOException { validateEntities(UNIT_TEST_FOLDER, TEST_EVENTS_PATH, "/results/expected"); } - /** - * @param inputEventsFolder - * @param testEventsPath - * @param resultsPath - * @throws URISyntaxException - * @throws ValidationServiceException - * @throws IOException - */ + private static Path findResource(String path, String subPath) throws URISyntaxException { + URL resource = ClassLoader.getSystemResource(path + subPath); + if (resource == null) { + return Paths.get(path, subPath); + } else { + return Paths.get(resource.toURI()); + } + } + + private RuleDrivenValidator buildValidator(OxmReader oxmReader, String rulesFolder) throws URISyntaxException { + return new RuleDrivenValidator(Collections.singletonList(findResource(UNIT_TEST_FOLDER, rulesFolder)), + oxmReader, new EventReader(null, null, null), null); + } + private void validateEntities(String inputEventsFolder, String testEventsPath, String resultsPath) throws URISyntaxException, ValidationServiceException, IOException { for (TestEntity entity : getEntities(inputEventsFolder, testEventsPath, resultsPath)) { @@ -111,7 +133,7 @@ public class TestRuleDrivenValidator { assertThat(results.size(), is(1)); ValidationResult expectedResult = entity.getExpectedValidationResult(); if (expectedResult == null) { - Path testEvents = Paths.get(ClassLoader.getSystemResource(inputEventsFolder + resultsPath).toURI()); + Path testEvents = findResource(inputEventsFolder, resultsPath); StringBuilder sb = new StringBuilder(); Files.walk(testEvents).forEach((path) -> sb.append(path).append("\n")); assertThat("Expected results missing (" + entity.expectedResultsFile + ")\n" + sb.toString(), diff --git a/src/test/resources/rule-driven-validator/missing_oxm/dummy_event_type/oxm_missing.groovy b/src/test/resources/rule-driven-validator/missing_oxm/dummy_event_type/oxm_missing.groovy new file mode 100644 index 0000000..1ec2a01 --- /dev/null +++ b/src/test/resources/rule-driven-validator/missing_oxm/dummy_event_type/oxm_missing.groovy @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (c) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2018-2019 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +entity { + type 'unknown_type' + validation { + useRule { + name 'dummy' + attributes 'dummy' + } + } +} + +rule { + name 'dummy' + category 'INVALID_VALUE' + description 'for test purposes' + errorText '' + severity 'MINOR' + validate 'return false' +} -- cgit 1.2.3-korg