/** * ============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========================================================= */ package org.onap.aai.validation.modeldriven.validator; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.dom4j.Element; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.onap.aai.validation.controller.ValidationController; import org.onap.aai.validation.modeldriven.ModelCacheManager; import org.onap.aai.validation.modeldriven.ModelId; import org.onap.aai.validation.modeldriven.parser.XMLModelParser; import org.onap.aai.validation.result.ValidationResult; import org.onap.aai.validation.result.Violation; import org.onap.aai.validation.test.util.TestUtil; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @SpringBootTest @RunWith(SpringJUnit4ClassRunner.class) @TestPropertySource(locations = {"classpath:oxm-reader/schemaIngest.properties"}) @ContextConfiguration(locations = {"classpath:model-validation/instance-validator/test-validation-service-beans.xml"}) public class TestModelDrivenValidator { static { System.setProperty("APP_HOME", "."); } private static final String RESOURCE_VERSION = "1467975776"; private static final String MODEL_ID_ATTRIBUTE_MNV = "model-name-version-id"; private static final String MODEL_ID_ATTRIBUTE_MID = "model-id"; @MockBean private ModelCacheManager mockModelCacheManager; @Inject private ModelDrivenValidator modelDrivenValidator; private String objectInstance; private String connectorModel; static enum InstanceValidationFile { // @formatter:off CONNECTOR_MODEL ("connector-widget-id.xml"), NO_MODEL_ID ("connector-instance-no-model-id.json"), UNKNOWN_MODEL_ID ("connector-instance-unknown-model-id.json"), ERRORS ("connector-instance-errors.json"), MULTIPLE_MISSING_ATTRS ("connector-instance-multiple-missing-attrs.json"), MULTIPLE_UNEXPECTED_ATTRS ("connector-instance-multiple-unexpected-attrs.json"), SUCCESS ("connector-instance-success.json"); // @formatter:on private String filename; InstanceValidationFile(String filename) { this.filename = "model-validation/instance-validator/" + filename; } public String getFilename() { return this.filename; } } @Before public void initMocks() { MockitoAnnotations.initMocks(this); } @Before public void setUp() throws Exception { connectorModel = TestUtil.getFileAsString(InstanceValidationFile.CONNECTOR_MODEL.getFilename()); } @Test public void testValidateInstanceWithoutModelId() throws Exception { objectInstance = TestUtil.getFileAsString(InstanceValidationFile.NO_MODEL_ID.getFilename()); ValidationResult validationResult = modelDrivenValidator.validate(objectInstance).get(0); assertThatValidationResultIsValid(validationResult, "c7611ebe-c324-48f1-8085-94aef0c12fd", "connector", "1467975776"); Violation violation = validationResult.getViolations().get(0); Map details = new HashMap<>(); details.put("No model ID", null); assertThatViolationIsValid(violation, ValidationController.VALIDATION_ERROR_SEVERITY, details, "The model [null] could not be found", RESOURCE_VERSION); } @Test public void testValidateInstanceWithUnknownModelId() throws Exception { objectInstance = TestUtil.getFileAsString(InstanceValidationFile.UNKNOWN_MODEL_ID.getFilename()); Mockito.when(mockModelCacheManager.get(new ModelId(MODEL_ID_ATTRIBUTE_MID, "UNKNOWN-MODEL"))).thenReturn(null); ValidationResult validationResult = modelDrivenValidator.validate(objectInstance).get(0); assertThatValidationResultIsValid(validationResult, "c7611ebe-c324-48f1-8085-94aef0c12fd", "connector", "1467975776"); Violation violation = validationResult.getViolations().get(0); Map details = new HashMap<>(); details.put("No model ID", "UNKNOWN-MODEL"); assertThatViolationIsValid(violation, ValidationController.VALIDATION_ERROR_SEVERITY, details, "The model [UNKNOWN-MODEL] could not be found", RESOURCE_VERSION); } @Test public void testValidate() throws Exception { objectInstance = TestUtil.getFileAsString(InstanceValidationFile.ERRORS.getFilename()); Element modelElement = XMLModelParser.parse(connectorModel, true); Mockito.when(mockModelCacheManager.get(new ModelId(MODEL_ID_ATTRIBUTE_MID, "connector-widget-id"))) .thenReturn(modelElement); Mockito.when(mockModelCacheManager .get(new ModelId(MODEL_ID_ATTRIBUTE_MNV, "l2-bridge-for-wan-connector-resource-id"))).thenReturn(null); ValidationResult validationResult = modelDrivenValidator.validate(objectInstance).get(0); assertThatValidationResultIsValid(validationResult, "c7611ebe-c324-48f1-8085-94aef0c12fd", "connector", "1467975776"); List violations = validationResult.getViolations(); assertThat(violations, hasSize(3)); assertThat(getCategories(violations), containsInAnyOrder(Arrays.asList("MISSING_ATTR", "UNEXPECTED_ATTR", "UNEXPECTED_REL").toArray())); Violation violation = getValidationByCategory(violations, "MISSING_ATTR").get(0); Map details = new HashMap<>(); details.put("MISSING ATTR", "product"); assertThatViolationIsValid(violation, ValidationController.VALIDATION_ERROR_SEVERITY, details, "Attribute [product] is missing in the object instance", RESOURCE_VERSION); violation = getValidationByCategory(violations, "UNEXPECTED_ATTR").get(0); details = new HashMap<>(); details.put("UNEXPECTED ATTR", "unexpected"); assertThatViolationIsValid(violation, ValidationController.VALIDATION_ERROR_SEVERITY, details, "Attribute [unexpected] should not be present in the object instance", RESOURCE_VERSION); violation = getValidationByCategory(violations, "UNEXPECTED_REL").get(0); details = new HashMap<>(); Map entityIdmap = new HashMap<>(); entityIdmap.put("vdc-id", "vdc-01"); details.put("entityId", entityIdmap); details.put("modelName", null); details.put("entityType", "virtual-data-center"); details.put("UNEXPECTED REL", "logical-link"); assertThatViolationIsValid(violation, ValidationController.VALIDATION_ERROR_SEVERITY, details, "Entity [vdc-id=vdc-01] of type [virtual-data-center] must not be related to [logical-link]", RESOURCE_VERSION); } @Test public void testValidateMultipleMissingAttrs() throws Exception { objectInstance = TestUtil.getFileAsString(InstanceValidationFile.MULTIPLE_MISSING_ATTRS.getFilename()); Element modelElement = XMLModelParser.parse(connectorModel, true); Mockito.when(mockModelCacheManager.get(new ModelId(MODEL_ID_ATTRIBUTE_MID, "connector-widget-id"))) .thenReturn(modelElement); Mockito.when(mockModelCacheManager .get(new ModelId(MODEL_ID_ATTRIBUTE_MNV, "l2-bridge-for-wan-connector-resource-id"))).thenReturn(null); List violations = modelDrivenValidator.validate(objectInstance).get(0).getViolations(); assertThat(violations, hasSize(2)); assertThat(getCategories(violations), containsInAnyOrder(Arrays.asList("MISSING_ATTR", "MISSING_ATTR").toArray())); List missingAttrValidations = getValidationByCategory(violations, "MISSING_ATTR"); String detailsAsString = getDetails(missingAttrValidations).toString(); assertThat(detailsAsString, containsString("{MISSING ATTR=product}")); assertThat(detailsAsString, containsString("{MISSING ATTR=vpn-id}")); } @Test public void testValidateMultipleUnexpectedAttrs() throws Exception { objectInstance = TestUtil.getFileAsString(InstanceValidationFile.MULTIPLE_UNEXPECTED_ATTRS.getFilename()); Element modelElement = XMLModelParser.parse(connectorModel, true); Mockito.when(mockModelCacheManager.get(new ModelId(MODEL_ID_ATTRIBUTE_MID, "connector-widget-id"))) .thenReturn(modelElement); Mockito.when(mockModelCacheManager .get(new ModelId(MODEL_ID_ATTRIBUTE_MNV, "l2-bridge-for-wan-connector-resource-id"))).thenReturn(null); List violations = modelDrivenValidator.validate(objectInstance).get(0).getViolations(); assertThat(violations, hasSize(2)); assertThat(getCategories(violations), containsInAnyOrder(Arrays.asList("UNEXPECTED_ATTR", "UNEXPECTED_ATTR").toArray())); List missingAttrViolations = getValidationByCategory(violations, "UNEXPECTED_ATTR"); String detailsAsString = getDetails(missingAttrViolations).toString(); assertThat(detailsAsString, containsString("{UNEXPECTED ATTR=city}")); assertThat(detailsAsString, containsString("{UNEXPECTED ATTR=state}")); } @Test public void testValidateSuccess() throws Exception { objectInstance = TestUtil.getFileAsString(InstanceValidationFile.SUCCESS.getFilename()); Element modelElement = XMLModelParser.parse(connectorModel, true); Mockito.when(mockModelCacheManager.get(new ModelId(MODEL_ID_ATTRIBUTE_MID, "connector-widget-id"))) .thenReturn(modelElement); Mockito.when(mockModelCacheManager .get(new ModelId(MODEL_ID_ATTRIBUTE_MNV, "l2-bridge-for-wan-connector-resource-id"))).thenReturn(null); List violations = modelDrivenValidator.validate(objectInstance).get(0).getViolations(); assertThat(violations, is(empty())); } private void assertThatValidationResultIsValid(ValidationResult validationResult, String entityInstanceId, String entityType, String resourceVersion) { assertThat( validationResult.getEntityId().getAsJsonObject().entrySet().iterator().next().getValue().getAsString(), is(equalTo(entityInstanceId))); assertThat(validationResult.getEntityType(), is(equalTo(entityType))); assertThat(validationResult.getResourceVersion(), is(equalTo(resourceVersion))); } private void assertThatViolationIsValid(Violation violation, String severity, Map violationDetails, String errorMessage, String resourceVersion) { assertThat(violation.getSeverity(), is(equalTo(severity))); assertThat(violation.getViolationType(), is(equalTo("Model"))); assertThat(violation.getViolationDetails(), is(equalTo(violationDetails))); assertThat(violation.getErrorMessage(), is(equalTo(errorMessage))); } private List getCategories(List validations) { List categories = new ArrayList<>(); for (Violation validation : validations) { categories.add(validation.getCategory()); } return categories; } private List> getDetails(List validations) { List> details = new ArrayList<>(); for (Violation validation : validations) { details.add(validation.getViolationDetails()); } return details; } private List getValidationByCategory(List validations, String category) { List validationsByCategory = new ArrayList<>(); for (Violation validation : validations) { if (category.equals(validation.getCategory())) { validationsByCategory.add(validation); } } return validationsByCategory; } }