diff options
author | Prudence Au <prudence.au@amdocs.com> | 2018-08-13 17:06:59 -0400 |
---|---|---|
committer | Pierre Rioux <pierre.rioux@amdocs.com> | 2018-08-21 11:21:26 -0400 |
commit | c604f64b971491f8c9b953adce54b847d7946e26 (patch) | |
tree | 134f7fc91b4da9e04c564c92337d44df420c8df0 /src/test/java/org | |
parent | 3baa3ebd0000b15f1c54c736f4a307731b16b923 (diff) |
Initial submission for validation service
Change-Id: I9372430f1ae347373d5a9a0c7a427d7bd393d61e
Issue-ID: LOG-427
Signed-off-by: Prudence Au (prudence.au@amdocs.com)
Signed-off-by: Geora Barsky <georab@amdocs.com>
Signed-off-by: Pierre Rioux <pierre.rioux@amdocs.com>
Diffstat (limited to 'src/test/java/org')
43 files changed, 6444 insertions, 0 deletions
diff --git a/src/test/java/org/onap/aai/validation/auth/MicroServiceAuthTest.java b/src/test/java/org/onap/aai/validation/auth/MicroServiceAuthTest.java new file mode 100644 index 0000000..f9bd177 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/auth/MicroServiceAuthTest.java @@ -0,0 +1,227 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.auth; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Paths; +import java.security.cert.X509Certificate; +import javax.security.auth.x500.X500Principal; +import javax.ws.rs.core.Cookie; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.aai.auth.AAIAuthException; +import org.onap.aai.auth.AAIMicroServiceAuth; +import org.onap.aai.auth.AAIMicroServiceAuthCore; +import org.onap.aai.validation.config.ValidationServiceAuthConfig; +import org.springframework.mock.web.MockHttpServletRequest; + +/** + * Tests @{link AAIMicroServiceAuth} + */ + +public class MicroServiceAuthTest { + + static { + System.setProperty("APP_HOME", "."); + System.setProperty("CONFIG_HOME", Paths.get(System.getProperty("user.dir"), "src/test/resources").toString()); + } + + private static final String VALID_ADMIN_USER = "cn=common-name, ou=org-unit, o=org, l=location, st=state, c=us"; + private static final String authPolicyFile = "auth_policy.json"; + + /** + * Temporarily invalidate the default policy file and then try to initialise the authorisation class using the name + * of a policy file that does not exist. + * + * @throws AAIAuthException + * @throws IOException + */ + @Test(expected = AAIAuthException.class) + public void missingPolicyFile() throws AAIAuthException, IOException { + String defaultFile = AAIMicroServiceAuthCore.getDefaultAuthFileName(); + try { + AAIMicroServiceAuthCore.setDefaultAuthFileName("invalid.default.file"); + ValidationServiceAuthConfig authConfig = new ValidationServiceAuthConfig(); + authConfig.setAuthPolicyFile("invalid.file.name"); + new AAIMicroServiceAuth(authConfig); + } finally { + AAIMicroServiceAuthCore.setDefaultAuthFileName(defaultFile); + } + } + + /** + * Test loading of a temporary file created with the specified roles + * + * @throws AAIAuthException + * @throws IOException + * @throws JSONException + */ + @Test + public void createLocalAuthFile() throws AAIAuthException, IOException, JSONException { + JSONObject roles = createRoleObject("role", createUserObject("user"), createFunctionObject("func")); + AAIMicroServiceAuth auth = createAuthService(roles); + assertThat(auth.authUser("nosuchuser", "method:func"), is(equalTo("AAI_9101"))); + assertThat(auth.authUser("user", "method:func"), is(equalTo("OK"))); + } + + /** + * Test loading of the policy file relative to CONFIG_HOME + * + * @throws AAIAuthException + */ + @Test + public void createAuth() throws AAIAuthException { + AAIMicroServiceAuth auth = createStandardAuth(); + assertAdminUserAuthorisation(auth, VALID_ADMIN_USER); + } + + @Test + public void testAuthUser() throws AAIAuthException { + AAIMicroServiceAuth auth = createStandardAuth(); + assertThat(auth.authUser(VALID_ADMIN_USER, "GET:actions"), is(equalTo("OK"))); + assertThat(auth.authUser(VALID_ADMIN_USER, "WRONG:action"), is(equalTo("AAI_9101"))); + } + + @Test + public void testAuthCookie() throws AAIAuthException { + AAIMicroServiceAuth auth = createStandardAuth(); + Cookie mockCookie = new Cookie("name", null); + StringBuilder user = new StringBuilder(VALID_ADMIN_USER); + + assertThat(auth.authCookie(null, "GET:actions", user), is(false)); + assertThat(auth.authCookie(null, "WRONG:action", user), is(false)); + + assertThat(auth.authCookie(mockCookie, "GET:actions", user), is(true)); + assertThat(auth.authCookie(mockCookie, "WRONG:action", user), is(false)); + } + + @Test + public void testValidateRequests() throws AAIAuthException { + AAIMicroServiceAuth auth = createStandardAuth(); + assertThat(auth.validateRequest(new MockHttpServletRequest(), null, "app/v1/service"), is(false)); + assertThat(auth.validateRequest(createMockRequest(), "POST", "getAndPublish"), is(false)); + assertThat(auth.validateRequest(createMockRequest(), "POST", "validate"), is(true)); + } + + private MockHttpServletRequest createMockRequest() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + servletRequest.setSecure(true); + servletRequest.setScheme("https"); + servletRequest.setServerPort(9501); + servletRequest.setServerName("localhost"); + servletRequest.setRequestURI("/services/validation-service/v1/app/validate"); + + X509Certificate mockCertificate = Mockito.mock(X509Certificate.class); + Mockito.when(mockCertificate.getSubjectX500Principal()) + .thenReturn(new X500Principal("CN=test, OU=qa, O=Test Ltd, L=London, ST=London, C=GB")); + + servletRequest.setAttribute("javax.servlet.request.X509Certificate", new X509Certificate[] {mockCertificate}); + servletRequest.setAttribute("javax.servlet.request.cipher_suite", ""); + return servletRequest; + } + + private AAIMicroServiceAuth createStandardAuth() throws AAIAuthException { + ValidationServiceAuthConfig authConfig = new ValidationServiceAuthConfig(); + authConfig.setAuthPolicyFile(authPolicyFile); + return new AAIMicroServiceAuth(authConfig); + } + + /** + * @param rolesJson + * @return + * @throws IOException + * @throws AAIAuthException + */ + private AAIMicroServiceAuth createAuthService(JSONObject roles) throws IOException, AAIAuthException { + ValidationServiceAuthConfig authConfig = new ValidationServiceAuthConfig(); + File file = File.createTempFile("auth-policy", "json"); + file.deleteOnExit(); + FileWriter fileWriter = new FileWriter(file); + fileWriter.write(roles.toString()); + fileWriter.flush(); + fileWriter.close(); + + authConfig.setAuthPolicyFile(file.getAbsolutePath()); + return new AAIMicroServiceAuth(authConfig); + } + + /** + * Assert authorisation results for an admin user based on the test policy file + * + * @param auth + * @param adminUser + * @throws AAIAuthException + */ + private void assertAdminUserAuthorisation(AAIMicroServiceAuth auth, String adminUser) throws AAIAuthException { + assertThat(auth.authUser(adminUser, "GET:actions"), is(equalTo("OK"))); + assertThat(auth.authUser(adminUser, "POST:actions"), is(equalTo("OK"))); + assertThat(auth.authUser(adminUser, "PUT:actions"), is(equalTo("OK"))); + assertThat(auth.authUser(adminUser, "DELETE:actions"), is(equalTo("OK"))); + } + + private JSONArray createFunctionObject(String functionName) throws JSONException { + JSONArray functionsArray = new JSONArray(); + JSONObject func = new JSONObject(); + func.put("name", functionName); + func.put("methods", createMethodObject("method")); + functionsArray.put(func); + return functionsArray; + } + + private JSONArray createMethodObject(String methodName) throws JSONException { + JSONArray methodsArray = new JSONArray(); + JSONObject method = new JSONObject(); + method.put("name", methodName); + methodsArray.put(method); + return methodsArray; + } + + private JSONArray createUserObject(String username) throws JSONException { + JSONArray usersArray = new JSONArray(); + JSONObject user = new JSONObject(); + user.put("username", username); + usersArray.put(user); + return usersArray; + } + + private JSONObject createRoleObject(String roleName, JSONArray usersArray, JSONArray functionsArray) + throws JSONException { + JSONObject roles = new JSONObject(); + + JSONObject role = new JSONObject(); + role.put("name", roleName); + role.put("functions", functionsArray); + role.put("users", usersArray); + + JSONArray rolesArray = new JSONArray(); + rolesArray.put(role); + roles.put("roles", rolesArray); + + return roles; + } + +} diff --git a/src/test/java/org/onap/aai/validation/config/TestRestConfig.java b/src/test/java/org/onap/aai/validation/config/TestRestConfig.java new file mode 100644 index 0000000..313c847 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/config/TestRestConfig.java @@ -0,0 +1,79 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.config; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import javax.inject.Inject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.validation.config.RestConfig; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:/rest-config/test-validation-service-beans.xml"}) +public class TestRestConfig { + + static { + System.setProperty("APP_HOME", "."); + } + + @Inject + private RestConfig restConfig; + + @Test + public void testRestConfigPopulation() throws Exception { + RestConfig expectedRestConfig = new RestConfig(); + + expectedRestConfig.setHost("localhost"); + expectedRestConfig.setPort(8080); + expectedRestConfig.setProtocol("https"); + expectedRestConfig.setBaseModelURI("${baseModelURI}"); + expectedRestConfig.setTrustStorePath("/dir1/dir2/trustStorePath"); + expectedRestConfig.setTrustStorePassword("70c87528c88dcd9f9c2558d30e817868"); + expectedRestConfig.setKeyStorePath("/dir1/dir2/keyStorePath"); + expectedRestConfig.setKeyStorePassword("70c87528c88dcd9f9c2558d30e817868"); + expectedRestConfig.setKeyManagerFactoryAlgorithm("AES"); + expectedRestConfig.setKeyStoreType("jks"); + expectedRestConfig.setSecurityProtocol("TLS"); + expectedRestConfig.setConnectionTimeout(100); + expectedRestConfig.setReadTimeout(200); + + assertThat(expectedRestConfig, is(restConfig)); + assertThat(expectedRestConfig.getBaseModelURI(), is(restConfig.getBaseModelURI())); + assertThat(expectedRestConfig.getConnectionTimeout(), is(restConfig.getConnectionTimeout())); + assertThat(expectedRestConfig.getHost(), is(restConfig.getHost())); + assertThat(expectedRestConfig.getKeyManagerFactoryAlgorithm(), is(restConfig.getKeyManagerFactoryAlgorithm())); + assertThat(expectedRestConfig.getKeyStorePassword(), is(restConfig.getKeyStorePassword())); + assertThat(expectedRestConfig.getKeyStorePath(), is(restConfig.getKeyStorePath())); + assertThat(expectedRestConfig.getKeyStoreType(), is(restConfig.getKeyStoreType())); + assertThat(expectedRestConfig.getPort(), is(restConfig.getPort())); + assertThat(expectedRestConfig.getProtocol(), is(restConfig.getProtocol())); + assertThat(expectedRestConfig.getReadTimeout(), is(restConfig.getReadTimeout())); + assertThat(expectedRestConfig.getSecurityProtocol(), is(restConfig.getSecurityProtocol())); + assertThat(expectedRestConfig.getTrustStorePassword(), is(restConfig.getTrustStorePassword())); + assertThat(expectedRestConfig.getTrustStorePath(), is(restConfig.getTrustStorePath())); + assertThat(expectedRestConfig.hashCode(), is(restConfig.hashCode())); + assertThat(expectedRestConfig.toString(), is(restConfig.toString())); + assertTrue(expectedRestConfig.equals(restConfig)); + + } +} diff --git a/src/test/java/org/onap/aai/validation/config/TestTopicAdminConfig.java b/src/test/java/org/onap/aai/validation/config/TestTopicAdminConfig.java new file mode 100644 index 0000000..f6a6195 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/config/TestTopicAdminConfig.java @@ -0,0 +1,60 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.config; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import javax.inject.Inject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.validation.config.TopicAdminConfig; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:/topic-admin-config/test-validation-service-beans.xml"}) +public class TestTopicAdminConfig { + + static { + System.setProperty("APP_HOME", "."); + } + + @Inject + private TopicAdminConfig topicAdminConfig; + + @Test + public void testTopicAdminConfigPopulation() throws Exception { + TopicAdminConfig expectedTopicAdminConfig = new TopicAdminConfig(); + + expectedTopicAdminConfig.setPublishEnable(true); + expectedTopicAdminConfig.setPublishRetries(3l); + expectedTopicAdminConfig.setConsumeEnable(true); + expectedTopicAdminConfig.setConsumePollingIntervalSeconds(3l); + + assertThat(expectedTopicAdminConfig, is(topicAdminConfig)); + assertThat(expectedTopicAdminConfig.hashCode(), is(topicAdminConfig.hashCode())); + assertThat(expectedTopicAdminConfig.toString(), is(topicAdminConfig.toString())); + assertThat(expectedTopicAdminConfig.getConsumePollingIntervalSeconds(), + is(topicAdminConfig.getConsumePollingIntervalSeconds())); + assertThat(expectedTopicAdminConfig.getPublishRetries(), is(topicAdminConfig.getPublishRetries())); + assertTrue(expectedTopicAdminConfig.equals(topicAdminConfig)); + } + +} diff --git a/src/test/java/org/onap/aai/validation/config/TestTopicConfig.java b/src/test/java/org/onap/aai/validation/config/TestTopicConfig.java new file mode 100644 index 0000000..efe82b8 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/config/TestTopicConfig.java @@ -0,0 +1,107 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.config; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.util.List; +import java.util.Properties; +import javax.annotation.Resource; +import javax.inject.Inject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.validation.config.TopicConfig; +import org.onap.aai.validation.ValidationServiceApplication; +import org.onap.aai.validation.config.TopicConfig.Topic; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:/topic-config/test-validation-service-beans.xml"}) +public class TestTopicConfig { + + static { + System.setProperty("APP_HOME", "."); + } + + @Inject + private TopicConfig topicConfigurations; + + @Resource(name = "topicProperties") + private Properties topicProperties; + + + @Test + public void testGetTopicProperties() throws Exception { + assertThat(topicProperties.getProperty("aai-event.name"), is("aai-event")); + assertThat(topicProperties.getProperty("aai-data-export.name"), is("aai-data-export")); + } + + + + @Test + public void testGetConsumerTopicsFromTopicConfig() throws Exception { + assertThat(topicConfigurations.getConsumerTopicNames(), containsInAnyOrder("aai-event", "aai-data-export")); + } + + + @Test + public void testGetConsumerTopicConfigurationObjects() throws Exception { + Topic eventTopic = new TopicConfig("aai-event","aai-data-integrity").new Topic(); + eventTopic.setName("aai-event"); + eventTopic.setHost("event-dummy-host"); + eventTopic.setUsername("event-dummy-username"); + eventTopic.setPassword("event-dummy-password"); + eventTopic.setConsumerGroup("event-dummy-consumer-group"); + eventTopic.setConsumerId("event-dummy-consumer-id"); + eventTopic.setTransportType("event-dummy-transport-type"); + + Topic exportTopic = new TopicConfig("aai-data-export","aai-data-integrity").new Topic(); + exportTopic.setName("aai-data-export"); + exportTopic.setHost("export-dummy-host"); + exportTopic.setUsername("export-dummy-username"); + exportTopic.setPassword("export-dummy-password"); + exportTopic.setConsumerGroup("export-dummy-consumer-group"); + exportTopic.setConsumerId("export-dummy-consumer-id"); + exportTopic.setTransportType("export-dummy-transport-type"); + + List<Topic> consumerTopics = topicConfigurations.getConsumerTopics(); + + assertThat(consumerTopics, containsInAnyOrder(eventTopic, exportTopic)); + } + + @Test + public void testGetPublisherTopicConfigurationObjects() throws Exception { + Topic integrityTopic = new TopicConfig("aai-data-export","aai-data-integrity").new Topic(); + integrityTopic.setName("aai-data-integrity"); + integrityTopic.setHost("integrity-dummy-host"); + integrityTopic.setPartition("integrity-dummy-partition"); + integrityTopic.setUsername("integrity-dummy-username"); + integrityTopic.setPassword("integrity-dummy-password"); + integrityTopic.setTransportType("integrity-dummy-transport-type"); + + List<Topic> publisherTopics = topicConfigurations.getPublisherTopics(); + + assertThat(publisherTopics, containsInAnyOrder(integrityTopic)); + } + + +} diff --git a/src/test/java/org/onap/aai/validation/config/TestValidationControllerConfig.java b/src/test/java/org/onap/aai/validation/config/TestValidationControllerConfig.java new file mode 100644 index 0000000..a8e03eb --- /dev/null +++ b/src/test/java/org/onap/aai/validation/config/TestValidationControllerConfig.java @@ -0,0 +1,69 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.config; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.validation.config.ValidationControllerConfig; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:/validation-controller-config/test-validation-service-beans.xml"}) +public class TestValidationControllerConfig { + + static { + System.setProperty("APP_HOME", "."); + } + + @Inject + private ValidationControllerConfig validationControllerConfig; + + @Test + public void testValidationControllerConfig() { + ValidationControllerConfig expected = new ValidationControllerConfig(); + List<String> excludedEventActionList = new ArrayList<String>(); + excludedEventActionList.add("DELETE"); + + List<String> eventTypeRuleList = new ArrayList<String>(2); + eventTypeRuleList.add("AAI-EVENT"); + eventTypeRuleList.add("AAI-DATA-EXPORT-API"); + + List<String> eventTypeModelList = new ArrayList<String>(); + eventTypeModelList.add("AAI-DATA-EXPORT-NQ"); + + expected.setEventDomain("devINT1"); + expected.setExcludedEventActions(excludedEventActionList); + expected.setEventTypeRule(eventTypeRuleList); + expected.setEventTypeModel(eventTypeModelList); + expected.setEventTypeEnd("END-EVENT"); + + assertThat(expected.getEventDomain(), is(validationControllerConfig.getEventDomain())); + assertThat(expected.getExcludedEventActions(), is(validationControllerConfig.getExcludedEventActions())); + assertThat(expected.getEventTypeRule(), is(validationControllerConfig.getEventTypeRule())); + assertThat(expected.getEventTypeModel(), is(validationControllerConfig.getEventTypeModel())); + assertThat(expected.getEventTypeEnd(), is(validationControllerConfig.getEventTypeEnd())); + } + +} diff --git a/src/test/java/org/onap/aai/validation/controller/TestValidationController.java b/src/test/java/org/onap/aai/validation/controller/TestValidationController.java new file mode 100644 index 0000000..ff67181 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/controller/TestValidationController.java @@ -0,0 +1,391 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.controller; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aai.validation.Validator; +import org.onap.aai.validation.config.EventReaderConfig; +import org.onap.aai.validation.config.ValidationControllerConfig; +import org.onap.aai.validation.controller.ValidationController; +import org.onap.aai.validation.exception.ValidationServiceError; +import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.publisher.MessagePublisher; +import org.onap.aai.validation.reader.EventReader; +import org.onap.aai.validation.reader.data.Entity; +import org.onap.aai.validation.reader.data.EntityId; +import org.onap.aai.validation.result.ValidationResult; +import org.onap.aai.validation.result.Violation; + +@RunWith(MockitoJUnitRunner.class) +public class TestValidationController { + + private static final String AAI_EVENT = "AAI-EVENT"; + private static final String CREATE = "CREATE"; + private static final String DELETE = "DELETE"; + private static final String DEV_INT_1 = "devINT1"; + private static final String ENTITY_LINK = "entityLink"; + private static final String MODEL = "model"; + private static final String RULE = "rule"; + private static final String TEST = "test"; + private static final String TESTDATA_EVENTTYPE_NAMEDQUERY = "aai named query eventtype"; + private static final String TESTDATA_EVENTTYPE_API = "aai api eventtype"; + private static final String TESTDATA_EVENTTYPE_AAI = "aai event eventype"; + private static final String TESTDATA_EVENTTYPE_UNKNOWN = "unknown eventtype"; + private static final String TESTDATA_EVENTTYPE_NULL = "event with null eventtype"; + private static final String TESTDATA_EVENTTYPE_END_EVENT = "END-EVENT"; + private static final String TESTDATA_DOMAIN_INVALID = "event with invalid domain"; + private static final String TESTDATA_DOMAIN_NULL = "event with null domain"; + private static final String TESTDATA_EVENTACTION_DELETE = "event with delete event action"; + private static final String TESTDATA_EVENTACTION_NULL = "event with null event action"; + private static final String TESTDATA_EXCEPTION_EVENT = "event causing exception"; + private static final String TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT = + "event causing exception during handling of the original exception"; + private static final String TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR = + "event causing exception during publishing of validation result"; + private static final String VSERVER = "vserver"; + + @Mock + private ValidationControllerConfig validationControllerConfig; + + @Mock + private EventReader eventReader; + + @Mock + private Validator ruleDrivenValidator; + + @Mock + private Validator modelDrivenValidator; + + @Mock + private MessagePublisher messagePublisher; + + @InjectMocks + private ValidationController validationController = new ValidationController(validationControllerConfig, + eventReader, ruleDrivenValidator, modelDrivenValidator, messagePublisher); + + @Mock + private Entity entity; + + static { + System.setProperty("APP_HOME", "."); + } + + @Before + public void setupMocks() throws ValidationServiceException { + + Map<String, List<ValidationResult>> validationResultsMap = setupTestData(); + + when(ruleDrivenValidator.validate(TESTDATA_EVENTTYPE_AAI)) + .thenReturn(validationResultsMap.get(TESTDATA_EVENTTYPE_AAI)); + when(ruleDrivenValidator.validate(TESTDATA_EVENTTYPE_API)) + .thenReturn(validationResultsMap.get(TESTDATA_EVENTTYPE_API)); + when(modelDrivenValidator.validate(TESTDATA_EVENTTYPE_NAMEDQUERY)) + .thenReturn(validationResultsMap.get(TESTDATA_EVENTTYPE_NAMEDQUERY)); + when(ruleDrivenValidator.validate(TESTDATA_EXCEPTION_EVENT)) + .thenThrow(new RuntimeException("Failed to validate")); + when(ruleDrivenValidator.validate(TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT)) + .thenThrow(new RuntimeException("Failed to validate")); + when(ruleDrivenValidator.validate(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR)) + .thenReturn(validationResultsMap.get(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR)); + when(ruleDrivenValidator.validate(TESTDATA_EVENTACTION_NULL)) + .thenReturn(validationResultsMap.get(TESTDATA_EVENTTYPE_AAI)); + + Map<String, List<String>> eventTypeDataMap = setupEventTypeData(); + when(validationControllerConfig.getEventTypeRule()).thenReturn(eventTypeDataMap.get(RULE)); + when(validationControllerConfig.getEventTypeModel()).thenReturn(eventTypeDataMap.get(MODEL)); + when(validationControllerConfig.getEventTypeEnd()).thenReturn("END-EVENT"); + + when(eventReader.getEventType(TESTDATA_EVENTTYPE_AAI)).thenReturn(Optional.of(AAI_EVENT)); + when(eventReader.getEventType(TESTDATA_EVENTTYPE_API)).thenReturn(Optional.of("AAI-DATA-EXPORT-API")); + when(eventReader.getEventType(TESTDATA_EVENTTYPE_NAMEDQUERY)).thenReturn(Optional.of("AAI-DATA-EXPORT-NQ")); + when(eventReader.getEventType(TESTDATA_EVENTTYPE_UNKNOWN)).thenReturn(Optional.of("EVENTTYPE-UNKNOWN")); + when(eventReader.getEventType(TESTDATA_EVENTTYPE_NULL)).thenReturn(Optional.empty()); + when(eventReader.getEventType(TESTDATA_EXCEPTION_EVENT)).thenReturn(Optional.of(AAI_EVENT)); + when(eventReader.getEventType(TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT)).thenReturn(Optional.of(AAI_EVENT)); + when(eventReader.getEventType(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR)).thenReturn(Optional.of(AAI_EVENT)); + when(eventReader.getEventType(TESTDATA_EVENTACTION_NULL)).thenReturn(Optional.of(AAI_EVENT)); + + when(validationControllerConfig.getEventDomain()).thenReturn(DEV_INT_1); + when(eventReader.getEventDomain(TESTDATA_EVENTTYPE_AAI)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_EVENTTYPE_API)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_EVENTTYPE_NAMEDQUERY)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_EVENTTYPE_UNKNOWN)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_EVENTTYPE_NULL)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_DOMAIN_INVALID)).thenReturn(Optional.of("invalidDomain")); + when(eventReader.getEventDomain(TESTDATA_DOMAIN_NULL)).thenReturn(Optional.empty()); + when(eventReader.getEventDomain(TESTDATA_EXCEPTION_EVENT)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_EVENTACTION_DELETE)).thenReturn(Optional.of(DEV_INT_1)); + when(eventReader.getEventDomain(TESTDATA_EVENTACTION_NULL)).thenReturn(Optional.of(DEV_INT_1)); + + List<String> excludedActions = new ArrayList<>(); + excludedActions.add(DELETE); + when(validationControllerConfig.getExcludedEventActions()).thenReturn(excludedActions); + when(eventReader.getEventAction(TESTDATA_EVENTTYPE_AAI)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_EVENTTYPE_API)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_EVENTTYPE_NAMEDQUERY)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_EVENTTYPE_UNKNOWN)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_EVENTTYPE_NULL)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_EXCEPTION_EVENT)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR)).thenReturn(Optional.of(CREATE)); + when(eventReader.getEventAction(TESTDATA_EVENTACTION_DELETE)).thenReturn(Optional.of(DELETE)); + when(eventReader.getEventAction(TESTDATA_EVENTACTION_NULL)).thenReturn(Optional.empty()); + + when(eventReader.getEntityType(TESTDATA_EXCEPTION_EVENT)).thenReturn(Optional.of(VSERVER)); + when(eventReader.getEntity(TESTDATA_EXCEPTION_EVENT)).thenReturn(entity); + when(eventReader.getEntityType(TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT)).thenThrow( + new RuntimeException("Error during handling the exception for an event that couldn't be validated")); + //@formatter:off + Mockito.doThrow(new ValidationServiceException(ValidationServiceError.EVENT_CLIENT_PUBLISHER_INIT_ERROR)) + .when(messagePublisher) + .publishMessage( + Mockito.contains("\"entityId\":\"[vserver-id=instanceid1]\",\"entityType\":\"entitytype1\",\"resourceVersion\":\"resourceVersion1\"")); + //@formatter:on + } + + private Map<String, List<String>> setupEventTypeData() { + Map<String, List<String>> eventTypeDataMap = new HashMap<>(); + List<String> eventTypeRule = new ArrayList<>(); + + eventTypeRule.add(AAI_EVENT); + eventTypeRule.add("AAI-DATA-EXPORT-API"); + eventTypeDataMap.put(RULE, eventTypeRule); + + List<String> eventTypeModel = new ArrayList<>(); + eventTypeModel.add("AAI-DATA-EXPORT-NQ"); + eventTypeDataMap.put(MODEL, eventTypeModel); + + return eventTypeDataMap; + } + + private Map<String, List<ValidationResult>> setupTestData() throws ValidationServiceException { + + Map<String, List<ValidationResult>> validationResultsMap = new HashMap<>(); + + List<ValidationResult> aaiEventValidationResults = new ArrayList<>(); + + setUpEntityMock("20160525162737-61c49d41-5338-4755-af54-06cee9fe4aca", VSERVER, "1464193654"); + + aaiEventValidationResults.add(new ValidationResult(entity)); + aaiEventValidationResults.add(new ValidationResult(entity)); + validationResultsMap.put(TESTDATA_EVENTTYPE_AAI, aaiEventValidationResults); + + List<ValidationResult> apiEventValidationResults = new ArrayList<>(); + + setUpEntityMock("20160525162737-61c49d41-5338-4755-af54-06cee9fe4acb", VSERVER, "1464193655"); + + apiEventValidationResults.add(new ValidationResult(entity)); + validationResultsMap.put(TESTDATA_EVENTTYPE_API, apiEventValidationResults); + + List<ValidationResult> namedQueryEventValidationResults = new ArrayList<>(); + + setUpEntityMock("20160525162737-61c49d41-5338-4755-af54-06cee9fe4acc", VSERVER, "1464193656"); + + namedQueryEventValidationResults.add(new ValidationResult(entity)); + validationResultsMap.put(TESTDATA_EVENTTYPE_NAMEDQUERY, namedQueryEventValidationResults); + + List<ValidationResult> messagePublishExceptionValidationResults = new ArrayList<>(); + + setUpEntityMock("instanceid1", "entitytype1", "resourceVersion1"); + + messagePublishExceptionValidationResults.add(new ValidationResult(entity)); + validationResultsMap.put(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR, messagePublishExceptionValidationResults); + + return validationResultsMap; + } + + @Test + public void testExecuteForAAIEvent() throws Exception { + // Test for AAI-EVENT + validationController.execute(TESTDATA_EVENTTYPE_AAI, TEST); + verify(ruleDrivenValidator, times(1)).validate(TESTDATA_EVENTTYPE_AAI); + verify(messagePublisher, times(2)).publishMessage(Mockito.contains( + "\"entityId\":{\"vserver-id\":\"20160525162737-61c49d41-5338-4755-af54-06cee9fe4aca\"},\"entityType\":\"vserver\",\"entityLink\":\"entityLink\",\"resourceVersion\":\"1464193654\",\"entity\":{},\"violations\":[]}")); + } + + @Test + public void testExecuteForAPIEvent() throws Exception { + // Test for AAI-DATA-EXPORT-API + validationController.execute(TESTDATA_EVENTTYPE_API, TEST); + verify(ruleDrivenValidator, times(1)).validate(TESTDATA_EVENTTYPE_API); + verify(messagePublisher, times(1)).publishMessage(Mockito.contains( + "\"entityId\":{\"vserver-id\":\"20160525162737-61c49d41-5338-4755-af54-06cee9fe4acb\"},\"entityType\":\"vserver\",\"entityLink\":\"entityLink\",\"resourceVersion\":\"1464193655\",\"entity\":{},\"violations\":[]}")); + } + + @Test + public void testExecuteForNQEvent() throws Exception { + // Test for AAI-DATA-EXPORT-NQ + validationController.execute(TESTDATA_EVENTTYPE_NAMEDQUERY, TEST); + verify(modelDrivenValidator, times(1)).validate(TESTDATA_EVENTTYPE_NAMEDQUERY); + verify(messagePublisher, times(1)).publishMessage(Mockito.contains( + "\"entityId\":{\"vserver-id\":\"20160525162737-61c49d41-5338-4755-af54-06cee9fe4acc\"},\"entityType\":\"vserver\",\"entityLink\":\"entityLink\",\"resourceVersion\":\"1464193656\",\"entity\":{},\"violations\":[]}")); + } + + @Test + public void testExecuteForNullDomain() throws Exception { + doVerifyMockInteractionsTest(TESTDATA_DOMAIN_NULL, TEST); + } + + private void doVerifyMockInteractionsTest(String event, String eventSource) throws Exception { + validationController.execute(event, eventSource); + verify(eventReader, times(1)).getEventType(Mockito.anyString()); + verify(ruleDrivenValidator, times(0)).validate(Mockito.anyString()); + verify(modelDrivenValidator, times(0)).validate(Mockito.anyString()); + verify(messagePublisher, times(0)).publishMessage(Mockito.anyString()); + + } + + @Test + public void testExecuteForInvalidDomain() throws Exception { + doVerifyMockInteractionsTest(TESTDATA_DOMAIN_INVALID, TEST); + } + + @Test + public void testExecuteForExcludedAction() throws Exception { + doVerifyMockInteractionsTest(TESTDATA_EVENTACTION_DELETE, TEST); + } + + @Test + public void testExecuteForNullAction() throws Exception { + validationController.execute(TESTDATA_EVENTACTION_NULL, TEST); + verify(eventReader, times(2)).getEventType(Mockito.anyString()); + verify(ruleDrivenValidator, times(1)).validate(Mockito.anyString()); + verify(modelDrivenValidator, times(0)).validate(Mockito.anyString()); + verify(messagePublisher, times(2)).publishMessage(Mockito.anyString()); + } + + + + private void doEventTypeTest(String event, String eventSource, int numEventReaderInvocations) throws Exception { + validationController.execute(event, eventSource); + verify(eventReader, times(numEventReaderInvocations)).getEventType(event); + verify(ruleDrivenValidator, times(0)).validate(Mockito.anyString()); + verify(modelDrivenValidator, times(0)).validate(Mockito.anyString()); + verify(messagePublisher, times(0)).publishMessage(Mockito.anyString()); + } + + @Test + public void testExecuteForNullEventType() throws Exception { + // The implementation checks whether this is an end event + // Given that it is not, the event is then examined to see if it is a validation candidate + doEventTypeTest(TESTDATA_EVENTTYPE_NULL, TEST, 2); + } + + @Test + public void testExecuteForUnknownEventType() throws Exception { + doEventTypeTest(TESTDATA_EVENTTYPE_UNKNOWN, TEST, 2); + } + + @Test + public void testExecuteForEndEventType() throws Exception { + doVerifyMockInteractionsTest(TESTDATA_EVENTTYPE_END_EVENT, TEST); + } + + @Test + public void testExceptionDuringValidation() throws Exception { + String primaryKey = "vserver-id"; + String value = "example-vserver-id-val-34666"; + String resourceVersion = "123456789"; + + EntityId entityId = new EntityId(primaryKey, value); + + when(entity.getResourceVersion()).thenReturn(Optional.of(resourceVersion)); + when(entity.getIds()).thenReturn(Collections.singletonList(entityId)); + validationController.execute(TESTDATA_EXCEPTION_EVENT, TEST); + verify(ruleDrivenValidator, times(1)).validate(TESTDATA_EXCEPTION_EVENT); + + // @formatter:off + Violation violation = new Violation.Builder(entity) + .category("CANNOT_VALIDATE") + .severity("CRITICAL") + .violationType("NONE") + .errorMessage("Failed to validate") + .build(); + // @formatter:on + + JsonObject violationObject = new JsonParser().parse(violation.toString()).getAsJsonObject(); + violationObject.remove("validationRule"); // Not set + + JsonObject validationResult = new JsonObject(); + JsonObject entityIdObject = new JsonObject(); + JsonElement entity = new JsonObject(); + entityIdObject.addProperty(primaryKey, value); + validationResult.add(Violation.ENTITY_ID_PROPERTY, entityIdObject); + validationResult.addProperty(Violation.ENTITY_TYPE_PROPERTY, "entitytype1"); + validationResult.addProperty(ENTITY_LINK, ENTITY_LINK); + validationResult.addProperty("resourceVersion", resourceVersion); + validationResult.add("entity", entity); + JsonArray violations = new JsonArray(); + violations.add(violationObject); + validationResult.add("violations", violations); + + String json = validationResult.toString(); + String messageContent = json.substring(1, json.length() - 1); // Remove the { } from the JSON string + verify(messagePublisher).publishMessage(Mockito.contains(messageContent)); + } + + @Test + public void testExceptionDuringHandlingValidationException() throws Exception { + // Test for exception during handling of an exception scenario + validationController.execute(TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT, TEST); + verify(ruleDrivenValidator, times(1)).validate(TESTDATA_HANDLE_EXCEPTION_EXCEPTION_EVENT); + verify(messagePublisher, times(0)).publishMessage(Mockito.anyString()); + } + + @Test + public void testExceptionDuringMessagePublish() throws Exception { + // Test for exception during publishing message. + // Cant verify if the static application logger has been called. + // This test is here for code coverage. + validationController.execute(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR, TEST); + verify(ruleDrivenValidator, times(1)).validate(TESTDATA_VALIDATION_RESULT_PUBLISH_ERROR); + verify(messagePublisher, times(1)).publishMessage(Mockito.contains( + "\"entityId\":{\"vserver-id\":\"instanceid1\"},\"entityType\":\"entitytype1\",\"entityLink\":\"entityLink\",\"resourceVersion\":\"resourceVersion1\",\"entity\":{},\"violations\":[]}")); + } + + private void setUpEntityMock(String id, String type, String resourceVersion) throws ValidationServiceException { + when(eventReader.getEventReaderConfig()).thenReturn(new EventReaderConfig()); + when(entity.getType()).thenReturn(type); + EntityId entityId = new EntityId("vserver-id", id); + when(entity.getIds()).thenReturn(Collections.singletonList(entityId)); + when(entity.getEntityLink()).thenReturn(ENTITY_LINK); + when(entity.getResourceVersion()).thenReturn(Optional.of(resourceVersion)); + } +} diff --git a/src/test/java/org/onap/aai/validation/data/client/TestRestClient.java b/src/test/java/org/onap/aai/validation/data/client/TestRestClient.java new file mode 100644 index 0000000..9f2807b --- /dev/null +++ b/src/test/java/org/onap/aai/validation/data/client/TestRestClient.java @@ -0,0 +1,74 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.data.client; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import javax.ws.rs.core.MediaType; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.aai.validation.config.RestConfig; +import org.onap.aai.validation.data.client.RestClient; +import org.onap.aai.validation.exception.ValidationServiceException; + +/** + * Simple tests for GET and POST failures so as to increase code coverage. + * + * Note that the REST client is not properly initialised. + * + */ +public class TestRestClient { + + static { + System.setProperty("APP_HOME", "."); + } + + private static final String TEST_URL = "/aai/v11"; + private RestConfig mockRestConfig; + + @Before + public void setUp() { + mockRestConfig = Mockito.mock(RestConfig.class); + Mockito.when(mockRestConfig.getProtocol()).thenReturn("http"); + Mockito.when(mockRestConfig.getHost()).thenReturn("localhost"); + Mockito.when(mockRestConfig.getPort()).thenReturn(8080); + } + + @Test + public void validateConstructor() { + RestClient restClient = new RestClient(mockRestConfig); + assertNotNull(restClient); + assertThat(restClient.toString(), is(notNullValue())); + } + + @Test(expected = ValidationServiceException.class) + public void getOperationFailure() throws ValidationServiceException { + RestClient restClient = new RestClient(mockRestConfig); + restClient.get(TEST_URL, MediaType.TEXT_PLAIN); + } + + @Test(expected = ValidationServiceException.class) + public void postOperationFailure() throws ValidationServiceException { + RestClient restClient = new RestClient(mockRestConfig); + restClient.post(TEST_URL, MediaType.TEXT_PLAIN); + } +} diff --git a/src/test/java/org/onap/aai/validation/logging/LogReader.java b/src/test/java/org/onap/aai/validation/logging/LogReader.java new file mode 100644 index 0000000..096221d --- /dev/null +++ b/src/test/java/org/onap/aai/validation/logging/LogReader.java @@ -0,0 +1,101 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.logging; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import org.apache.commons.lang.time.StopWatch; +import org.junit.Assert; + +public class LogReader { + + private Map<String, Path> cachedLogMap = new HashMap<>(); + private Map<String, BufferedReader> readersMap = new HashMap<>(); + private BufferedReader cachedReader; + + public LogReader(String logDirectory, String logFilePrefix) throws IOException { + cachedReader = getReader(logDirectory, logFilePrefix); + } + + private BufferedReader getReader(String logDirectory, String logFilePrefix) throws IOException { + BufferedReader reader = readersMap.get(logFilePrefix); + if (reader == null) { + reader = new BufferedReader(new FileReader(getLogFile(logDirectory, logFilePrefix))); + while (reader.readLine() != null) { + // Consume all lines + } + readersMap.put(logFilePrefix, reader); + } + return reader; + } + + /** + * @param logDirectory + * @return the most recently created log file. + * @throws IOException + */ + public File getLogFile(String logDirectory, String filenamePrefix) throws IOException { + Path cachedLog = cachedLogMap.get(filenamePrefix); + + if (cachedLog == null) { + Optional<Path> latestFilePath = Files.list(Paths.get(logDirectory)) + .filter(f -> Files.isDirectory(f) == false && f.getFileName().toString().startsWith(filenamePrefix)) + .max(Comparator.comparingLong(f -> f.toFile().lastModified())); + if (latestFilePath.isPresent()) { + cachedLog = latestFilePath.get(); + } else { + throw new IOException("No validation log files were found!"); + } + } + + return cachedLog.toFile(); + } + + /** + * @return new lines appended to the log file + * @throws IOException + */ + public String getNewLines() throws IOException { + StopWatch stopwatch = new StopWatch(); + stopwatch.start(); + + while (!cachedReader.ready()) { + if (stopwatch.getTime() > TimeUnit.SECONDS.toMillis(30)) { + Assert.fail("Test took too long"); + } + // else keep waiting + } + + StringBuilder lines = new StringBuilder(); + String line; + while ((line = cachedReader.readLine()) != null) { + lines.append(line).append(System.lineSeparator()); + } + return lines.toString(); + } +} diff --git a/src/test/java/org/onap/aai/validation/logging/TestApplicationLogger.java b/src/test/java/org/onap/aai/validation/logging/TestApplicationLogger.java new file mode 100644 index 0000000..d19d43d --- /dev/null +++ b/src/test/java/org/onap/aai/validation/logging/TestApplicationLogger.java @@ -0,0 +1,245 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.logging; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Arrays; +import org.apache.commons.lang.time.StopWatch; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.mdc.MdcOverride; +import org.onap.aai.validation.logging.ApplicationMsgs; +import org.onap.aai.validation.logging.LogHelper; +import org.onap.aai.validation.logging.LogHelper.TriConsumer; +import org.springframework.http.HttpHeaders; + +/** + * Simple test to log each of the validation messages in turn. + * + * This version tests only the error logger at INFO level. + * + */ +public class TestApplicationLogger { + + @BeforeClass + public static void setupClass() { + System.setProperty("APP_HOME", "."); + } + + /** + * Check that each message can be logged and that (by implication of successful logging) there is a corresponding + * resource (message format). + * + * @throws IOException + */ + @Test + public void logAllMessages() throws IOException { + Logger logger = LogHelper.INSTANCE; + String logDirectory = getLogDirectory(); + LogReader errorReader = new LogReader(logDirectory, "error"); + LogReader debugReader = new LogReader(logDirectory, "debug"); + String[] args = {"1", "2", "3", "4"}; + for (ApplicationMsgs msg : Arrays.asList(ApplicationMsgs.values())) { + if (msg.name().endsWith("ERROR")) { + logger.error(msg, args); + validateLoggedMessage(msg, errorReader, "ERROR"); + + logger.error(msg, new RuntimeException("fred"), args); + validateLoggedMessage(msg, errorReader, "fred"); + } else { + logger.info(msg, args); + validateLoggedMessage(msg, errorReader, "INFO"); + + logger.warn(msg, args); + validateLoggedMessage(msg, errorReader, "WARN"); + } + + logger.debug(msg, args); + validateLoggedMessage(msg, debugReader, "DEBUG"); + + // The trace level is not enabled + logger.trace(msg, args); + } + } + + /** + * Check that each message can be logged and that (by implication of successful logging) there is a corresponding + * resource (message format). + * + * @throws IOException + */ + @Test + public void logDebugMessages() throws IOException { + LogReader reader = new LogReader(getLogDirectory(), "debug"); + LogHelper.INSTANCE.debug("a message"); + String s = reader.getNewLines(); + assertThat(s, is(notNullValue())); + } + + + /** + * Check logAudit with HTTP headers + * + * @throws IOException + */ + @Test + public void logAuditMessage() throws IOException { + LogHelper logger = LogHelper.INSTANCE; + LogReader reader = new LogReader(getLogDirectory(), "audit"); + + HttpHeaders headers = Mockito.mock(HttpHeaders.class); + Mockito.when(headers.getFirst("X-ECOMP-RequestID")).thenReturn("ecomp-request-id"); + Mockito.when(headers.getFirst("X-FromAppId")).thenReturn("app-id"); + + // Call logAudit without first calling startAudit + logger.logAuditSuccess("first call: bob"); + String s = reader.getNewLines(); + assertThat(s, is(notNullValue())); + assertThat("audit message log level", s, containsString("INFO")); + assertThat("audit message content", s, containsString("bob")); + + // This time call the start method + logger.startAudit(headers, null); + logger.logAuditSuccess("second call: foo"); + s = reader.getNewLines(); + assertThat(s, is(notNullValue())); + assertThat("audit message log level", s, containsString("INFO")); + assertThat("audit message content", s, containsString("foo")); + assertThat("audit message content", s, containsString("ecomp-request-id")); + assertThat("audit message content", s, containsString("app-id")); + } + + /** + * Check logAudit with no HTTP headers + * + * @throws IOException + */ + @Test + public void logAuditMessageWithoutHeaders() throws IOException { + LogHelper logger = LogHelper.INSTANCE; + LogReader reader = new LogReader(getLogDirectory(), "audit"); + logger.startAudit(null, null); + logger.logAuditSuccess("foo"); + String s = reader.getNewLines(); + assertThat(s, is(notNullValue())); + assertThat("audit message log level", s, containsString("INFO")); + assertThat("audit message content", s, containsString("foo")); + } + + /** + * Check logMetrics + * + * @throws IOException + */ + @Test + public void logMetricsMessage() throws IOException { + LogReader reader = new LogReader(getLogDirectory(), "metrics"); + LogHelper logger = LogHelper.INSTANCE; + logger.logMetrics("metrics: fred"); + String s = reader.getNewLines(); + assertThat(s, is(notNullValue())); + assertThat("metrics message log level", s, containsString("INFO")); + assertThat("metrics message content", s, containsString("fred")); + } + + @Test + public void logMetricsMessageWithStopwatch() throws IOException { + LogReader reader = new LogReader(getLogDirectory(), "metrics"); + LogHelper logger = LogHelper.INSTANCE; + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + logger.logMetrics(stopWatch, "joe", "bloggs"); + String logLine = reader.getNewLines(); + assertThat(logLine, is(notNullValue())); + assertThat("metrics message log level", logLine, containsString("INFO")); + assertThat("metrics message content", logLine, containsString("joe")); + } + + @Test + public void callUnsupportedMethods() throws IOException { + LogHelper logger = LogHelper.INSTANCE; + ApplicationMsgs dummyMsg = ApplicationMsgs.LOAD_PROPERTIES; + callUnsupportedOperationMethod(logger::error, dummyMsg); + callUnsupportedOperationMethod(logger::info, dummyMsg); + callUnsupportedOperationMethod(logger::warn, dummyMsg); + callUnsupportedOperationMethod(logger::debug, dummyMsg); + callUnsupportedOperationMethod(logger::trace, dummyMsg); + try { + logger.error(dummyMsg, new LogFields(), new RuntimeException("test"), ""); + } catch (UnsupportedOperationException e) { + // Expected to reach here + } + try { + logger.info(dummyMsg, new LogFields(), new MdcOverride(), ""); + } catch (UnsupportedOperationException e) { + // Expected to reach here + } + try { + logger.formatMsg(dummyMsg, ""); + } catch (UnsupportedOperationException e) { + // Expected to reach here + } + } + + private String getLogDirectory() { + String logDirectory = LogHelper.getLogDirectory(); + assertThat(Paths.get(logDirectory).toAbsolutePath().toString(), + startsWith(Paths.get(System.getProperty("APP_HOME")).toAbsolutePath().toString())); + return logDirectory; + } + + /** + * Call a logger method which is expected to throw an UnsupportedOperationException + * + * @param logMethod + * @param dummyMsg + */ + private void callUnsupportedOperationMethod(TriConsumer<Enum<?>, LogFields, String[]> logMethod, + ApplicationMsgs dummyMsg) { + try { + logMethod.accept(dummyMsg, new LogFields(), new String[] {""}); + org.junit.Assert.fail("method should have thrown execption"); // NOSONAR as code not reached + } catch (UnsupportedOperationException e) { + // Expected to reach here + } + } + + /** + * Assert that a log message was logged to the expected log file at the expected severity + * + * @param msg + * @param reader + * @param severity + * @throws IOException + */ + private void validateLoggedMessage(ApplicationMsgs msg, LogReader reader, String severity) throws IOException { + String s = reader.getNewLines(); + assertThat(s, is(notNullValue())); + assertThat(msg.toString() + " log level", s, containsString(severity)); + } +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/TestModelId.java b/src/test/java/org/onap/aai/validation/modeldriven/TestModelId.java new file mode 100644 index 0000000..7cefede --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/TestModelId.java @@ -0,0 +1,95 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.modeldriven; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; + +import org.junit.Test; +import org.onap.aai.validation.modeldriven.ModelId; + +public class TestModelId { + + static { + System.setProperty("APP_HOME", "."); + } + + @Test + public void testGettersAndSetters() { + String attr = null; + String id = null; + ModelId modelId = new ModelId(attr, id); + assertThat(modelId.getModelIdAttribute(), is(equalTo(attr))); + assertThat(modelId.getModelId(), is(equalTo(id))); + assertThat(modelId.isEmpty(), is(true)); + + attr = ""; + modelId.setModelIdAttribute(attr); + assertThat(modelId.getModelIdAttribute(), is(equalTo(attr))); + assertThat(modelId.getModelId(), is(equalTo(id))); + assertThat(modelId.isEmpty(), is(true)); + + attr = "new_attr_value"; + modelId.setModelIdAttribute(attr); + assertThat(modelId.getModelIdAttribute(), is(equalTo(attr))); + assertThat(modelId.getModelId(), is(equalTo(id))); + assertThat(modelId.isEmpty(), is(true)); + + id = "new_id"; + modelId.setModelId(id); + assertThat(modelId.getModelIdAttribute(), is(equalTo(attr))); + assertThat(modelId.getModelId(), is(equalTo(id))); + assertThat(modelId.isEmpty(), is(false)); + + id = ""; + modelId.setModelId(id); + assertThat(modelId.getModelIdAttribute(), is(equalTo(attr))); + assertThat(modelId.getModelId(), is(equalTo(id))); + assertThat(modelId.isEmpty(), is(true)); + + attr = null; + modelId.setModelIdAttribute(attr); + assertThat(modelId.getModelIdAttribute(), is(equalTo(attr))); + assertThat(modelId.getModelId(), is(equalTo(id))); + assertThat(modelId.isEmpty(), is(true)); + } + + @Test + public void testIsEmpty() { + assertThat(new ModelId(null, null).isEmpty(), is(true)); + assertThat(new ModelId("", null).isEmpty(), is(true)); + assertThat(new ModelId(null, "").isEmpty(), is(true)); + assertThat(new ModelId("", "").isEmpty(), is(true)); + assertThat(new ModelId("A", null).isEmpty(), is(true)); + assertThat(new ModelId(null, "B").isEmpty(), is(true)); + assertThat(new ModelId("A", "B").isEmpty(), is(false)); + } + + @Test + public void testEqualsMethod() { + ModelId id1 = new ModelId("a", "b"); + ModelId id2 = new ModelId("a", "b"); + assertThat(id1, is(equalTo(id1))); + assertThat(id1, is(equalTo(id2))); + assertThat(id1, is(not(equalTo(null)))); + assertThat(id1.hashCode(), is(equalTo(id2.hashCode()))); + } + +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestFilter.java b/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestFilter.java new file mode 100644 index 0000000..c9d2688 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestFilter.java @@ -0,0 +1,55 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.modeldriven.configuration.mapping; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; +import org.onap.aai.validation.modeldriven.configuration.mapping.Filter; + +public class TestFilter { + + static { + System.setProperty("APP_HOME", "."); + } + + @Test + public void testAllMethodsInFilterClassToImproveCodeCoverage() { + Filter filter1 = new Filter(); + List<String> valid = new ArrayList<>(); + valid.add("String 1"); + filter1.setPath("path"); + filter1.setValid(valid); + + Filter filter2 = new Filter(); + filter2.setPath("path"); + filter2.setValid(valid); + + assertThat(filter1, is(filter2)); + assertThat(filter1.hashCode(), is(filter2.hashCode())); + assertThat(filter1.getPath(), is(filter2.getPath())); + assertThat(filter1.getValid(), is(filter2.getValid())); + assertThat(filter1.toString(), is(filter2.toString())); + assertTrue(filter1.equals(filter2)); + } + +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestModelInstanceMapper.java b/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestModelInstanceMapper.java new file mode 100644 index 0000000..7c820bb --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestModelInstanceMapper.java @@ -0,0 +1,71 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.modeldriven.configuration.mapping; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; +import org.onap.aai.validation.modeldriven.configuration.mapping.Filter; +import org.onap.aai.validation.modeldriven.configuration.mapping.ModelInstanceMapper; +import org.onap.aai.validation.modeldriven.configuration.mapping.ValueConfiguration; +import org.onap.aai.validation.modeldriven.configuration.mapping.ModelInstanceMapper.MappingType; + +public class TestModelInstanceMapper { + + static { + System.setProperty("APP_HOME", "."); + } + + @Test + public void testAllMethodsToImproveCodeCoverage() { + List<String> valid = new ArrayList<>(); + valid.add("string1"); + Filter filter = new Filter(); + filter.setPath("testPath"); + filter.setValid(valid); + + ValueConfiguration valueConf1 = new ValueConfiguration(); + valueConf1.setFilter(filter); + valueConf1.setId("id"); + valueConf1.setOrigin("testOrigin"); + valueConf1.setRoot("testRoot"); + valueConf1.setValue("testValue"); + + ModelInstanceMapper mapper1 = new ModelInstanceMapper(); + mapper1.setInstance(valueConf1); + mapper1.setMappingType(MappingType.ATTRIBUTE.toString()); + mapper1.setModel(valueConf1); + + ModelInstanceMapper mapper2 = new ModelInstanceMapper(); + mapper2.setInstance(valueConf1); + mapper2.setMappingType(MappingType.ATTRIBUTE.toString()); + mapper2.setModel(valueConf1); + + assertThat(mapper1.hashCode(), is(mapper2.hashCode())); + assertThat(mapper1.getInstance(), is(mapper2.getInstance())); + assertThat(mapper1.getMappingType(), is(mapper2.getMappingType())); + assertThat(mapper1.getModel(), is(mapper2.getModel())); + assertThat(mapper1.toString(), is(mapper2.toString())); + assertTrue(mapper1.equals(mapper2)); + } + +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestValueConfiguration.java b/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestValueConfiguration.java new file mode 100644 index 0000000..80c1ab8 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/configuration/mapping/TestValueConfiguration.java @@ -0,0 +1,70 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.modeldriven.configuration.mapping; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; +import org.onap.aai.validation.modeldriven.configuration.mapping.Filter; +import org.onap.aai.validation.modeldriven.configuration.mapping.ValueConfiguration; + +public class TestValueConfiguration { + + static { + System.setProperty("APP_HOME", "."); + } + + @Test + public void testAllMethodsToImproveCodeCoverage() { + + List<String> valid = new ArrayList<>(); + valid.add("string1"); + Filter filter = new Filter(); + filter.setPath("testPath"); + filter.setValid(valid); + + ValueConfiguration valueConf1 = new ValueConfiguration(); + valueConf1.setFilter(filter); + valueConf1.setId("id"); + valueConf1.setOrigin("testOrigin"); + valueConf1.setRoot("testRoot"); + valueConf1.setValue("testValue"); + + ValueConfiguration valueConf2 = new ValueConfiguration(); + valueConf2.setFilter(filter); + valueConf2.setId("id"); + valueConf2.setOrigin("testOrigin"); + valueConf2.setRoot("testRoot"); + valueConf2.setValue("testValue"); + + assertThat(valueConf1, is(valueConf2)); + assertThat(valueConf1.hashCode(), is(valueConf2.hashCode())); + assertThat(valueConf1.getFilter(), is(valueConf2.getFilter())); + assertThat(valueConf1.getId(), is(valueConf2.getId())); + assertThat(valueConf1.getOrigin(), is(valueConf2.getOrigin())); + assertThat(valueConf1.getRoot(), is(valueConf2.getRoot())); + assertThat(valueConf1.getValue(), is(valueConf2.getValue())); + assertThat(valueConf1.toString(), is(valueConf2.toString())); + assertTrue(valueConf1.equals(valueConf2)); + } + +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/parser/TestXMLModelParser.java b/src/test/java/org/onap/aai/validation/modeldriven/parser/TestXMLModelParser.java new file mode 100644 index 0000000..3344193 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/parser/TestXMLModelParser.java @@ -0,0 +1,96 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.modeldriven.parser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.dom4j.Element; +import org.dom4j.Node; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.validation.modeldriven.parser.XMLModelParser; + +public class TestXMLModelParser { + + static { + System.setProperty("APP_HOME", "."); + } + + private static final String CONNECTOR_MODEL_ID = "460c6de2-a92b-4e3b-9ba3-538ce782b2fa"; + private static final String MODEL_ID_ATTRIBUTE = "model-name-version-id"; + + private Element modelElement; + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Before + public void setUp() throws Exception { + File modelFile = new File("src/test/resources/model-validation/model-parser/all-models.xml"); + Element modelsElement = XMLModelParser.parse(modelFile, false); + modelElement = XMLModelParser.getModelElementWithId(modelsElement, MODEL_ID_ATTRIBUTE, CONNECTOR_MODEL_ID); + } + + @Test + public void testParseXMLModelFile() throws Exception { + assertEquals("Invalid model element name.", "model", modelElement.getName()); + } + + @Test + public void testGetAttributes() throws Exception { + String attrsXPath = "metadata/metadatum/metaname"; + List<Node> attrNodes = XMLModelParser.getObjectsFromXPath(modelElement, attrsXPath); + assertEquals("Unexpected number of attributes.", 2, attrNodes.size()); + + List<String> validAttrs = new ArrayList<>(); + validAttrs.add("a"); + validAttrs.add("b"); + + List<String> actualAttrs = new ArrayList<>(); + for (Node node : attrNodes) { + actualAttrs.add(node.getText()); + } + + assertTrue("Unexpected attribute names.", validAttrs.containsAll(actualAttrs)); + } + + @Test + public void testGetRelatedObjects() throws Exception { + String relObjsXPath = "model-elements/model-element"; + List<Node> relatedNodes = XMLModelParser.getObjectsFromXPath(modelElement, relObjsXPath); + assertEquals("Unexpected number of related objects.", 1, relatedNodes.size()); + + Node relatedObjUUIDNode = relatedNodes.get(0).selectSingleNode("model-element-uuid"); + assertEquals("Unexpected related object UUID.", "71b825be-febf-45f7-b86a-ca0e3de19c90", + relatedObjUUIDNode.getText()); + } + + @Test + public void testModelValidationFailure() throws Exception { + File modelFile = new File("src/test/resources/model-validation/model-parser/all-models.xml"); + + assertNull("Validation failure should result in null being returned.", XMLModelParser.parse(modelFile, true)); + } +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/validator/TestInstanceReader.java b/src/test/java/org/onap/aai/validation/modeldriven/validator/TestInstanceReader.java new file mode 100644 index 0000000..60588bb --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/validator/TestInstanceReader.java @@ -0,0 +1,236 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.modeldriven.validator; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; + +import com.google.common.collect.Multimap; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import javax.inject.Inject; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.modeldriven.configuration.mapping.ModelInstanceMapper; +import org.onap.aai.validation.modeldriven.validator.InstanceReader; +import org.onap.aai.validation.test.util.TestUtil; +import org.onap.aai.validation.util.JsonUtil; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@TestPropertySource(properties = {"schemaIngestPropLoc = src/test/resources/oxm-reader/schemaIngest.properties"}) +@ContextConfiguration(locations = {"classpath:model-validation/instance-reader/test-validation-service-beans.xml"}) +public class TestInstanceReader { + + static { + System.setProperty("APP_HOME", "."); + } + + private static ModelInstanceMapper mapping; + private static ModelInstanceMapper mappingRootUnknown; + private static ModelInstanceMapper mappingRootMissing; + private static String connector; + private static String connectorSibling; + private static String expectedVirtualDataCenter; + private static String expectedVirtualDataCenterModelName; + private static String connectorModelName; + private static String expectedLogicalLink; + private static String expectedGenericVnf; + private static String expectedPserver; + + @Inject + private InstanceReader instanceReader; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + mapping = TestInstanceReader.getMapping(TestData.MAPPING.getFilename()); + mappingRootUnknown = TestInstanceReader.getMapping(TestData.MAPPING_ROOT_UNKNOWN.getFilename()); + mappingRootMissing = TestInstanceReader.getMapping(TestData.MAPPING_ROOT_MISSING.getFilename()); + connector = TestUtil.getFileAsString(TestData.CONNECTOR.getFilename()); + connectorModelName = TestUtil.getFileAsString(TestData.CONNECTOR_MODEL_NAME.getFilename()); + connectorSibling = TestUtil.getFileAsString(TestData.CONNECTOR_SIBLING.getFilename()); + expectedVirtualDataCenter = TestUtil.getFileAsString(TestData.EXPECTED_VDC.getFilename()); + expectedVirtualDataCenterModelName = TestUtil.getFileAsString(TestData.EXPECTED_VDC_MODEL_NAME.getFilename()); + expectedLogicalLink = TestUtil.getFileAsString(TestData.EXPECTED_LOGICAL_LINK.getFilename()); + expectedGenericVnf = TestUtil.getFileAsString(TestData.EXPECTED_GENERIC_VNF.getFilename()); + expectedPserver = TestUtil.getFileAsString(TestData.EXPECTED_PSERVER.getFilename()); + + } + + enum TestData { + // @formatter:off + MAPPING ("model-validation/instance-reader/model-instance-mapping.json_conf"), + MAPPING_ROOT_UNKNOWN ("model-validation/instance-reader/model-instance-mapping-root-unknown.json_conf"), + MAPPING_ROOT_MISSING ("model-validation/instance-reader/model-instance-mapping-root-missing.json_conf"), + CONNECTOR ("model-validation/instance-reader/connector.json"), + CONNECTOR_MODEL_NAME ("model-validation/instance-reader/connector-model-name.json"), + CONNECTOR_SIBLING ("model-validation/instance-reader/connector-sibling-inventory-items.json"), + EXPECTED_VDC ("model-validation/instance-reader/expected-virtual-data-center.json"), + EXPECTED_VDC_MODEL_NAME ("model-validation/instance-reader/expected-virtual-data-center-model-name.json"), + EXPECTED_LOGICAL_LINK ("model-validation/instance-reader/expected-logical-link.json"), + EXPECTED_GENERIC_VNF ("model-validation/instance-reader/expected-generic-vnf.json"), + EXPECTED_PSERVER ("model-validation/instance-reader/expected-pserver.json"); + + private String filename; + TestData(String filename) {this.filename = filename;} + public String getFilename() {return this.filename;} + // @formatter:on + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testGetValuesNoModelName() throws Exception { + // Set expectation + JsonParser jsonParser = new JsonParser(); + JsonElement jsonElement = jsonParser.parse(expectedVirtualDataCenter); + String expectedValue = jsonElement.toString(); + + // Method under test + Multimap<String, String> values = instanceReader.getValues(connector, mapping); + + assertFalse(values.isEmpty()); + assertThat(values.keys().iterator().next(), is(equalTo("virtual-data-center"))); + assertThat(values.get("virtual-data-center").iterator().next(), is(equalTo(expectedValue))); + } + + @Test + public void testGetValuesWithModelName() throws Exception { + // Set expectation + JsonParser jsonParser = new JsonParser(); + JsonElement jsonElement = jsonParser.parse(expectedVirtualDataCenterModelName); + String expectedValue = jsonElement.toString(); + + // Method under test + Multimap<String, String> values = instanceReader.getValues(connectorModelName, mapping); + + assertFalse(values.isEmpty()); + assertThat(values.keys().iterator().next(), is(equalTo("Test VC Model Name"))); + assertThat(values.get("Test VC Model Name").iterator().next(), is(equalTo(expectedValue))); + } + + @Test + public void testNavigateInstance() throws Exception { + // Set expectation + JsonParser jsonParser = new JsonParser(); + JsonElement jsonElement = jsonParser.parse(expectedLogicalLink); + String expectedValue = jsonElement.toString(); + + // Method under test + Multimap<String, String> values = instanceReader.getValues(connector, mapping); + + String virtualDataCenterInstance = values.get("virtual-data-center").iterator().next(); + + // Method under test + values = instanceReader.getValues(virtualDataCenterInstance, mapping); + + assertThat(values.keys().iterator().next(), is(equalTo("Test LL Model Name"))); + assertThat(values.get("Test LL Model Name").iterator().next(), is(equalTo(expectedValue))); + } + + @Test + public void testNavigateInstanceWithSiblingInventoryItems() throws Exception { + // Set expectations + JsonParser jsonParser = new JsonParser(); + JsonElement genericVnfJsonElement = jsonParser.parse(expectedGenericVnf); + String expectedGenericVnf = genericVnfJsonElement.toString(); + + JsonElement pserverJsonElement = jsonParser.parse(expectedPserver); + String expectedPserver = pserverJsonElement.toString(); + + // Method under test + Multimap<String, String> values = instanceReader.getValues(connectorSibling, mapping); + + String virtualDataCenterInstance = values.get("virtual-data-center").iterator().next(); + + // Method under test + values = instanceReader.getValues(virtualDataCenterInstance, mapping); + + String logicalLinkInstance = values.get("Test LL Model Name").iterator().next(); + + // Method under test + values = instanceReader.getValues(logicalLinkInstance, mapping); + + assertThat(values.get("generic-vnf").iterator().next(), is(equalTo(expectedGenericVnf))); + assertThat(values.get("pserver").iterator().next(), is(equalTo(expectedPserver))); + } + + @Test + public void testGetValuesRootUnknown() throws Exception { + Multimap<String, String> values = instanceReader.getValues(connector, mappingRootUnknown); + + assertThat(values.isEmpty(), is(true)); + } + + @Test + public void testGetValuesRootMissing() throws Exception { + thrown.expect(ValidationServiceException.class); + thrown.expectMessage("VS-604"); + + instanceReader.getValues(connector, mappingRootMissing); + } + + @Test + public void testGetInstanceTypeNoModelName() throws Exception { + String instanceType = instanceReader.getInstanceType(connector); + assertThat(instanceType, is("connector")); + } + + @Test + public void testGetModelName() throws Exception { + String instanceType = instanceReader.getModelName(connectorModelName); + assertThat(instanceType, is("Test Connector Model Name")); + } + + @Test + public void testGetInstanceIdNoModelName() throws Exception { + String instanceId = instanceReader.getInstanceId(connector); + assertThat(instanceId, is("c7611ebe-c324-48f1-8085-94aef0c12fd")); + } + + @Test + public void testGetInstanceIdModelName() throws Exception { + String instanceId = instanceReader.getInstanceId(connectorModelName); + assertThat(instanceId, is("c7611ebe-c324-48f1-8085-94aef0c12fd")); + } + + @Test + public void testGetResourceVersion() throws Exception { + String resourceVersion = instanceReader.getResourceVersion(connector); + + assertThat(resourceVersion, is("1467975776")); + } + + private static ModelInstanceMapper getMapping(String mappingFileName) throws Exception { + JSONArray jsonArray = new JSONArray(TestUtil.getFileAsString(mappingFileName)); + JSONObject jsonObject = jsonArray.getJSONObject(0); + + return JsonUtil.fromJson(jsonObject.toString(), ModelInstanceMapper.class); + } +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/validator/TestModelDrivenValidator.java b/src/test/java/org/onap/aai/validation/modeldriven/validator/TestModelDrivenValidator.java new file mode 100644 index 0000000..cb9de43 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/validator/TestModelDrivenValidator.java @@ -0,0 +1,291 @@ +/* + * ============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===================================================== + */ +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.InjectMocks; +import org.mockito.Mock; +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.modeldriven.validator.ModelDrivenValidator; +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.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@TestPropertySource(properties = {"schemaIngestPropLoc = src/test/resources/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"; + + @Mock + private ModelCacheManager mockModelCacheManager; + + @InjectMocks + @Inject + private ModelDrivenValidator modelDrivenValidator; + + private String objectInstance; + private String connectorModel; + + enum INSTANCE_VALIDATION_FILE { + // @formatter:off + CONNECTOR_MODEL ("model-validation/instance-validator/connector-widget-id.xml"), + NO_MODEL_ID ("model-validation/instance-validator/connector-instance-no-model-id.json"), + UNKNOWN_MODEL_ID ("model-validation/instance-validator/connector-instance-unknown-model-id.json"), + ERRORS ("model-validation/instance-validator/connector-instance-errors.json"), + MULTIPLE_MISSING_ATTRS ("model-validation/instance-validator/connector-instance-multiple-missing-attrs.json"), + MULTIPLE_UNEXPECTED_ATTRS ("model-validation/instance-validator/connector-instance-multiple-unexpected-attrs.json"), + SUCCESS ("model-validation/instance-validator/connector-instance-success.json"); + // @formatter:on + + private String filename; + + INSTANCE_VALIDATION_FILE(String filename) { + this.filename = filename; + } + + public String getFilename() { + return this.filename; + } + } + + @Before + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @Before + public void setUp() throws Exception { + connectorModel = TestUtil.getFileAsString(INSTANCE_VALIDATION_FILE.CONNECTOR_MODEL.getFilename()); + } + + @Test + public void testValidateInstanceWithoutModelId() throws Exception { + objectInstance = TestUtil.getFileAsString(INSTANCE_VALIDATION_FILE.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<String, Object> 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(INSTANCE_VALIDATION_FILE.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<String, Object> 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(INSTANCE_VALIDATION_FILE.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<Violation> 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<String, Object> 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<String, Object> 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(INSTANCE_VALIDATION_FILE.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<Violation> violations = modelDrivenValidator.validate(objectInstance).get(0).getViolations(); + + assertThat(violations, hasSize(2)); + assertThat(getCategories(violations), + containsInAnyOrder(Arrays.asList("MISSING_ATTR", "MISSING_ATTR").toArray())); + + List<Violation> 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(INSTANCE_VALIDATION_FILE.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<Violation> violations = modelDrivenValidator.validate(objectInstance).get(0).getViolations(); + + assertThat(violations, hasSize(2)); + assertThat(getCategories(violations), + containsInAnyOrder(Arrays.asList("UNEXPECTED_ATTR", "UNEXPECTED_ATTR").toArray())); + + List<Violation> 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(INSTANCE_VALIDATION_FILE.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<Violation> 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<String, Object> 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<String> getCategories(List<Violation> validations) { + List<String> categories = new ArrayList<>(); + for (Violation validation : validations) { + categories.add(validation.getCategory()); + } + return categories; + } + + private List<Map<String, Object>> getDetails(List<Violation> validations) { + List<Map<String, Object>> details = new ArrayList<>(); + for (Violation validation : validations) { + details.add(validation.getViolationDetails()); + } + return details; + } + + private List<Violation> getValidationByCategory(List<Violation> validations, String category) { + List<Violation> validationsByCategory = new ArrayList<>(); + for (Violation validation : validations) { + if (category.equals(validation.getCategory())) { + validationsByCategory.add(validation); + } + } + return validationsByCategory; + } +} diff --git a/src/test/java/org/onap/aai/validation/modeldriven/validator/TestModelReader.java b/src/test/java/org/onap/aai/validation/modeldriven/validator/TestModelReader.java new file mode 100644 index 0000000..d974ca2 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/modeldriven/validator/TestModelReader.java @@ -0,0 +1,261 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.modeldriven.validator; + +import static org.hamcrest.Matchers.arrayContainingInAnyOrder; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import com.google.common.collect.Multimap; +import java.io.File; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import javax.inject.Inject; +import org.dom4j.Element; +import org.dom4j.Node; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.modeldriven.ModelCacheManager; +import org.onap.aai.validation.modeldriven.configuration.mapping.ModelInstanceMapper; +import org.onap.aai.validation.modeldriven.parser.XMLModelParser; +import org.onap.aai.validation.modeldriven.validator.ModelReader; +import org.onap.aai.validation.test.util.TestUtil; +import org.onap.aai.validation.util.JsonUtil; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:model-validation/model-reader/test-validation-service-beans.xml"}) +public class TestModelReader { + + static { + System.setProperty("APP_HOME", "."); + } + + private Element modelElement; + private ModelInstanceMapper mapping; + + @Inject + private ModelCacheManager cache; + + @Test + public void testGetValues() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-attributes-1.json"); + modelElement = XMLModelParser + .parse(new File("src/test/resources/model-validation/model-reader/connector-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries().size(), is(2)); + assertThat(values.containsEntry("product", null), is(true)); + assertThat(values.containsEntry("vpn-id", null), is(true)); + } + + /** + * @throws Exception + */ + @Test(expected = ValidationServiceException.class) + public void testGetValuesWithUnknownPath() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-attributes-2.json"); + modelElement = XMLModelParser + .parse(new File("src/test/resources/model-validation/model-reader/connector-widget-id.xml"), false); + + ModelReader.getValues(modelElement, mapping, cache); + } + + @Test + public void testGetValuesSingleModel() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships.json"); + modelElement = XMLModelParser + .parse(new File("src/test/resources/model-validation/model-reader/connector-widget-id.xml"), false); + + List<Node> expectedModels = XMLModelParser.getObjectsFromXPath(modelElement, mapping.getModel().getRoot()); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + Collection<Entry<String, Node>> entries = values.entries(); + assertThat(entries.size(), is(1)); + assertThat(values.containsEntry("virtual-data-center", expectedModels.get(0)), is(true)); + } + + @Test + public void testGetValuesMultipleModels() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships.json"); + modelElement = XMLModelParser + .parse(new File("src/test/resources/model-validation/model-reader/logical-link-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.keys().toArray(new String[] {}), arrayContainingInAnyOrder(new String[] {"logical-link",})); + + values = ModelReader.getValues(values.values().iterator().next(), mapping, cache); + + assertThat(values.keys().toArray(new String[] {}), + arrayContainingInAnyOrder(new String[] {"pBgf", "vDbe", "ipe", "vSbg",})); + } + + @Test + public void testGetValuesCurrentModelNoChildrenNoValues() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/connector-widget-id-no-children-1.xml"), + false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.isEmpty(), is(true)); + } + + @Test + public void testGetValuesCurrentModelNoChildrenWithValues() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/connector-widget-id-no-children-2.xml"), + false); + + Multimap<String, Node> parentValues = ModelReader.getValues(modelElement, mapping, cache); + + Multimap<String, Node> childValues = + ModelReader.getValues(parentValues.entries().iterator().next().getValue(), mapping, cache); + + assertThat(childValues.isEmpty(), is(true)); + } + + @Test + public void testResourceModelType() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.keys().toArray(new String[] {}), + arrayContainingInAnyOrder(new String[] {"l2-bridge-for-wan-connector",})); + } + + @Test + public void testRootWithInvalidPath() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-root-1.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries(), is(empty())); + } + + @Test + public void testRootMissing() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-root-2.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + assertThat(values.entries(), is(empty())); + } + + @Test + public void testFilterWithInvalidType() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-filter-1.json"); + modelElement = XMLModelParser + .parse(new File("src/test/resources/model-validation/model-reader/connector-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries(), is(empty())); + } + + @Test + public void testFilterWithEmptyArray() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-filter-2.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries(), is(empty())); + } + + @Test + public void testFilterWithMissingValidProperty() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-filter-3.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries(), is(empty())); + } + + @Test + public void testFilterWithInvalidPath() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-filter-4.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries(), is(empty())); + } + + @Test + public void testFilterWithMissingPath() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-filter-5.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries(), is(empty())); + } + + @Test + public void testFilterMissing() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-filter-6.json"); + modelElement = XMLModelParser.parse( + new File("src/test/resources/model-validation/model-reader/virtual-data-center-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.keys().toArray(new String[] {}), + arrayContainingInAnyOrder(new String[] {"l2-bridge-for-wan-connector"})); + } + + @Test + public void testGetValuesWithMultipleModelFetch() throws Exception { + mapping = getMapping("model-validation/model-reader/model-instance-mapping-relationships-with-id.json"); + modelElement = XMLModelParser + .parse(new File("src/test/resources/model-validation/model-reader/connector-widget-id.xml"), false); + + Multimap<String, Node> values = ModelReader.getValues(modelElement, mapping, cache); + + assertThat(values.entries(), is(empty())); + } + + private ModelInstanceMapper getMapping(String mappingFileName) throws Exception { + JSONArray jsonArray = new JSONArray(TestUtil.getFileAsString(mappingFileName)); + JSONObject jsonObject = jsonArray.getJSONObject(0); + + return JsonUtil.fromJson(jsonObject.toString(), ModelInstanceMapper.class); + } +} diff --git a/src/test/java/org/onap/aai/validation/publisher/MockEventPublisher.java b/src/test/java/org/onap/aai/validation/publisher/MockEventPublisher.java new file mode 100644 index 0000000..d1cfae0 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/publisher/MockEventPublisher.java @@ -0,0 +1,72 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.publisher; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collection; +import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.publisher.MessagePublisher; +import org.onap.aai.validation.result.ValidationResult; +import org.onap.aai.validation.test.util.TestEntity; +import org.onap.aai.validation.test.util.ValidationResultIsEqual; + +/** + * Will be injected by Spring + * + */ +public class MockEventPublisher implements MessagePublisher { + + private ValidationResult expectedValidationResult; + private String testDescription; + private boolean publishedMessage; + + public MockEventPublisher() { + // Deliberately empty - no configuration needed + } + + public void setTestEntity(TestEntity entity) throws URISyntaxException, IOException { + this.expectedValidationResult = entity.getExpectedValidationResult(); + this.publishedMessage = false; + } + + public void setTestDescription(String testDescription) { + this.testDescription = testDescription; + } + + @Override + public void publishMessage(String message) throws ValidationServiceException { + ValidationResult validationResult = ValidationResult.fromJson(message); + assertThat(testDescription, validationResult, is(ValidationResultIsEqual.equalTo(expectedValidationResult))); + publishedMessage = true; + } + + @Override + public void publishMessages(Collection<String> messages) throws ValidationServiceException { + for (String message : messages) { + publishMessage(message); + } + } + + public boolean processedSuccessfully() { + return publishedMessage || expectedValidationResult == null; + } +} diff --git a/src/test/java/org/onap/aai/validation/publisher/TestValidationEventPublisher.java b/src/test/java/org/onap/aai/validation/publisher/TestValidationEventPublisher.java new file mode 100644 index 0000000..8950e63 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/publisher/TestValidationEventPublisher.java @@ -0,0 +1,102 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.publisher; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.onap.aai.event.client.DMaaPEventPublisher; +import org.onap.aai.validation.config.TopicAdminConfig; +import org.onap.aai.validation.config.TopicConfig; +import org.onap.aai.validation.config.TopicConfig.Topic; +import org.onap.aai.validation.factory.DMaaPEventPublisherFactory; +import org.onap.aai.validation.publisher.ValidationEventPublisher; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class TestValidationEventPublisher { + + static { + System.setProperty("APP_HOME", "."); + System.setProperty("consumer.topic.names", "poa-rule-validation"); + System.setProperty("publisher.topic.names", "poa-audit-result"); + } + + private DMaaPEventPublisher mockEventPublisher; + private ValidationEventPublisher validationEventPublisher; + private List<Topic> topicList = new ArrayList<>(); + + @Before + public void setUp() throws Exception { + TopicConfig mockTopicConfig = Mockito.mock(TopicConfig.class); + TopicAdminConfig mockTopicAdminConfig = Mockito.mock(TopicAdminConfig.class); + when(mockTopicAdminConfig.isPublishEnable()).thenReturn(true); + + Topic topic1 = new TopicConfig("poa-rule-validation","poa-audit-result").new Topic(); + topic1.setName("aai-data-integrity"); + topic1.setHost("integrity-dummy-host"); + topic1.setPartition("integrity-dummy-partition"); + topic1.setUsername("integrity-dummy-username"); + topic1.setPassword("integrity-dummy-password"); + topic1.setTransportType("integrity-dummy-transport-type"); + topicList.add(topic1); + + when(mockTopicConfig.getPublisherTopics()).thenReturn(topicList); + validationEventPublisher = new ValidationEventPublisher(mockTopicConfig, mockTopicAdminConfig); + + mockEventPublisher = Mockito.mock(DMaaPEventPublisher.class); + when(mockEventPublisher.closeWithUnsent()).thenReturn(new ArrayList<>()); + + DMaaPEventPublisherFactory mockEventPublisherFactory = Mockito.mock(DMaaPEventPublisherFactory.class); + when(mockEventPublisherFactory.createEventPublisher(any(), any(), any(), any(), any())) + .thenReturn(mockEventPublisher); + + validationEventPublisher.setEventPublisherFactory(mockEventPublisherFactory); + } + + @Test + public void testPublishMessages() throws Exception { + Collection<String> messages = new ArrayList<>(); + messages.add("first test message"); + messages.add("second test message"); + when(mockEventPublisher.sendSync(any(String.class), Mockito.<Collection<String>>any())).thenReturn(2); + + validationEventPublisher.publishMessages(messages); + verify(mockEventPublisher, times(1)).sendSync(topicList.get(0).getPartition(), messages); + } + + @Test + public void testPublishMessage() throws Exception { + Collection<String> messages = new ArrayList<>(); + messages.add("first test message"); + when(mockEventPublisher.sendSync(any(String.class), Mockito.<Collection<String>>any())).thenReturn(1); + + validationEventPublisher.publishMessage(messages.iterator().next()); + verify(mockEventPublisher, times(1)).sendSync(topicList.get(0).getPartition(), messages); + } + +} diff --git a/src/test/java/org/onap/aai/validation/reader/TestEventReader.java b/src/test/java/org/onap/aai/validation/reader/TestEventReader.java new file mode 100644 index 0000000..a41eb76 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/reader/TestEventReader.java @@ -0,0 +1,270 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.reader; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import javax.inject.Inject; +import org.junit.BeforeClass; +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.data.Entity; +import org.onap.aai.validation.reader.data.EntityId; +import org.onap.aai.validation.test.util.TestUtil; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@TestPropertySource(properties = {"schemaIngestPropLoc = src/test/resources/oxm-reader/schemaIngest.properties"}) +@ContextConfiguration(locations = {"classpath:event-reader/test-validation-service-beans.xml"}) +public class TestEventReader { + + static { + System.setProperty("APP_HOME", "."); + } + + @Inject + private EventReader eventReader; + + private static String vserverEvent; + private static String genericVnfEvent; + private static String invalidEvent1; + private static String invalidEvent2; + private static String invalidEvent3; + private static String invalidEvent4; + private static String invalidEvent5; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + vserverEvent = TestUtil.getFileAsString(TestData.VSERVER.getFilename()); + genericVnfEvent = TestUtil.getFileAsString(TestData.GENERIC_VNF.getFilename()); + invalidEvent1 = TestUtil.getFileAsString(TestData.INVALID_1.getFilename()); + invalidEvent2 = TestUtil.getFileAsString(TestData.INVALID_2.getFilename()); + invalidEvent3 = TestUtil.getFileAsString(TestData.INVALID_3.getFilename()); + invalidEvent4 = TestUtil.getFileAsString(TestData.INVALID_4.getFilename()); + invalidEvent5 = TestUtil.getFileAsString(TestData.INVALID_5.getFilename()); + } + + enum TestData { + // @formatter:off + VSERVER ("event-reader/vserver-create-event.json"), + GENERIC_VNF ("event-reader/generic-vnf-create-event.json"), + INVALID_1 ("event-reader/invalid-event-1.json"), + INVALID_2 ("event-reader/invalid-event-2.json"), + INVALID_3 ("event-reader/invalid-event-3.json"), + INVALID_4 ("event-reader/invalid-event-4.json"), + INVALID_5 ("event-reader/invalid-event-5.json"); + + private String filename; + TestData(String filename) {this.filename = filename;} + public String getFilename() {return this.filename;} + // @formatter:on + } + + @Test + public void testGetEventDomain() throws Exception { + Optional<String> eventType = eventReader.getEventDomain(vserverEvent); + + assertThat(eventType.get(), is("devINT1")); + } + + @Test + public void testGetEventAction() throws Exception { + Optional<String> action = eventReader.getEventAction(vserverEvent); + + assertThat(action.get(), is("CREATE")); + } + + @Test + public void testGetEventType() throws Exception { + Optional<String> eventType = eventReader.getEventType(vserverEvent); + + assertThat(eventType.isPresent(), is(true)); + assertThat(eventType.get(), is("AAI-EVENT")); + } + + @Test(expected = ValidationServiceException.class) + public void testGetEventTypeMalformedJson() throws Exception { + eventReader.getEventType("this is malformed"); + } + + @Test + public void testGetEventTypeFromUnrecognisableEvent() throws Exception { + Optional<String> eventType = eventReader.getEventType("this-is-not-an-event-but-is-valid-json"); + + assertThat(eventType.isPresent(), is(false)); + } + + @Test + public void testGetEventTypeThatIsMissing() throws Exception { + Optional<String> eventType = eventReader.getEventType(invalidEvent1); + + assertThat(eventType.isPresent(), is(false)); + } + + @Test + public void testGetEntityType() throws Exception { + Optional<String> entityType = eventReader.getEntityType(vserverEvent); + + assertThat(entityType.get(), is("vserver")); + } + + @Test + public void testGetEntity() throws Exception { + Entity entity = eventReader.getEntity(genericVnfEvent); + + assertThat(entity.getType(), is("generic-vnf")); + + // Dig deeper to check we have the object we want + JsonParser parser = new JsonParser(); + JsonElement jsonElement = parser.parse(entity.getJson()); + String id = jsonElement.getAsJsonObject().get("vnf-id").getAsString(); + + assertThat(id, is("VAPP-1581")); + } + + @Test + public void testEntityLink() throws Exception { + Entity entity = eventReader.getEntity(vserverEvent); + + assertThat(entity.getEntityLink(), is( + "cloud-infrastructure/cloud-regions/cloud-region/region1/AAIregion1/tenants/tenant/example-tenant-id-val-88551/vservers/vserver/example-vserver-id-val-34666")); + } + + @Test(expected = ValidationServiceException.class) + public void testGetEntityWithMissingEntityType() throws Exception { + eventReader.getEntity(invalidEvent1); + } + + @Test(expected = ValidationServiceException.class) + public void testGetEntityWithUnknownEntityType() throws Exception { + eventReader.getEntity(invalidEvent2); + } + + @Test + public void testGetNestedEntity() throws Exception { + Entity entity = eventReader.getEntity(vserverEvent); + + assertThat(entity.getType(), is("vserver")); + + // Dig deeper to check we have the object we want + JsonParser parser = new JsonParser(); + JsonElement jsonElement = parser.parse(entity.getJson()); + String id = jsonElement.getAsJsonObject().get("vserver-id").getAsString(); + + assertThat(id, is("example-vserver-id-val-34666")); + } + + @Test(expected = ValidationServiceException.class) + public void testTooManyNestedEntitiesThrowsException() throws Exception { + eventReader.getEntity(invalidEvent4); + } + + @Test + public void testGetEntityIds() throws Exception { + Entity entity = eventReader.getEntity(vserverEvent); + + List<EntityId> ids = entity.getIds(); + + assertThat(ids, hasSize(1)); + EntityId entityId = ids.get(0); + + assertThat(entityId.getPrimaryKey(), is("vserver-id")); + assertThat(entityId.getValue(), is("example-vserver-id-val-34666")); + } + + @Test + public void testCompareEntityIds() throws Exception { + EntityId entityId = new EntityId(); + assertThat(entityId, is(not(equalTo(null)))); + + entityId.setPrimaryKey("key"); + assertThat(entityId, is(not(equalTo(null)))); + entityId.setValue("value"); + assertThat(entityId, is(not(equalTo(null)))); + + EntityId other = new EntityId(); + assertThat(entityId, is(not(equalTo(other)))); + + other.setPrimaryKey("key"); + assertThat(entityId, is(not(equalTo(other)))); + + other.setValue("value"); + assertThat(entityId, is(equalTo(other))); + + // Force call to hashCode() + assertThat(entityId.hashCode(), is(equalTo(other.hashCode()))); + } + + @Test + public void testGetEntityIdsForUnknownEntityType() throws Exception { + Entity entity = eventReader.getEntity(invalidEvent3); + + List<EntityId> ids = entity.getIds(); + + assertThat(ids, is(empty())); + } + + @Test + public void testGetResourceVersion() throws Exception { + Entity entity = eventReader.getEntity(vserverEvent); + + Optional<String> resourceVersion = entity.getResourceVersion(); + + assertThat(resourceVersion.isPresent(), is(true)); + assertThat(resourceVersion.get(), is("1464193654")); + } + + @Test + public void testGetResourceVersionMissing() throws Exception { + Entity entity = eventReader.getEntity(invalidEvent5); + + Optional<String> resourceVersion = entity.getResourceVersion(); + assertThat(resourceVersion.isPresent(), is(false)); + } + + @Test + public void testGetProperty() throws Exception { + Entity entity = eventReader.getEntity(vserverEvent); + + String resourceVersion = (String) entity.getAttributeValues(Arrays.asList("prov-status")).get("prov-status"); + + assertThat(resourceVersion, is("PREPROV")); + } + + @Test + public void testEntityLinkIsStripped() throws Exception { + Entity entity = eventReader.getEntity(vserverEvent); + String entityLink = entity.getEntityLink(); + assertThat(entityLink, is( + "cloud-infrastructure/cloud-regions/cloud-region/region1/AAIregion1/tenants/tenant/example-tenant-id-val-88551/vservers/vserver/example-vserver-id-val-34666")); + } +} diff --git a/src/test/java/org/onap/aai/validation/reader/TestJsonReader.java b/src/test/java/org/onap/aai/validation/reader/TestJsonReader.java new file mode 100644 index 0000000..e7a906a --- /dev/null +++ b/src/test/java/org/onap/aai/validation/reader/TestJsonReader.java @@ -0,0 +1,95 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.reader; + +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.onap.aai.validation.reader.JsonReader; +import org.onap.aai.validation.test.util.TestUtil; + +public class TestJsonReader { + + static { + System.setProperty("APP_HOME", "."); + } + + enum TestData { + // @formatter:off + SAMPLE_JSON ("json-reader/sample.json"); + + private String filename; + TestData(String filename) {this.filename = filename;} + public String getFilename() {return this.filename;} + // @formatter:on + } + + @Test + public void testGetString() throws Exception { + String json = TestUtil.getFileAsString(TestData.SAMPLE_JSON.getFilename()); + JsonReader jsonReader = new JsonReader(); + List<String> result = jsonReader.get(json, "$.event-header.entity-type"); + assertThat(result.get(0), is("vserver")); + } + + @Test + public void testGetInteger() throws Exception { + String json = TestUtil.getFileAsString(TestData.SAMPLE_JSON.getFilename()); + JsonReader jsonReader = new JsonReader(); + List<String> result = jsonReader.get(json, "$.event-header.sample-integer"); + assertThat(result.get(0), is("1")); + } + + @Test + public void testGetBoolean() throws Exception { + String json = TestUtil.getFileAsString(TestData.SAMPLE_JSON.getFilename()); + JsonReader jsonReader = new JsonReader(); + List<String> result = jsonReader.get(json, "$.event-header.sample-boolean"); + assertThat(result.get(0), is("true")); + } + + @Test + public void testGetObjectAsString() throws Exception { + String json = TestUtil.getFileAsString(TestData.SAMPLE_JSON.getFilename()); + JsonReader jsonReader = new JsonReader(); + List<String> result = jsonReader.get(json, "$.event-header.sample-object"); + + assertThat(result.get(0), is("{\"property\":\"value\"}")); + } + + @Test + public void testGetArrayAsString() throws Exception { + String json = TestUtil.getFileAsString(TestData.SAMPLE_JSON.getFilename()); + JsonReader jsonReader = new JsonReader(); + List<String> result = jsonReader.get(json, "$.event-header.sample-array"); + + assertThat(result, is(Arrays.asList("one"))); + } + + @Test + public void testGetWithInvalidPath() throws Exception { + String json = TestUtil.getFileAsString(TestData.SAMPLE_JSON.getFilename()); + JsonReader jsonReader = new JsonReader(); + List<String> result = jsonReader.get(json, "$.unknown"); + assertThat(result, empty()); + } +} diff --git a/src/test/java/org/onap/aai/validation/reader/TestOxmConfigTranslator.java b/src/test/java/org/onap/aai/validation/reader/TestOxmConfigTranslator.java new file mode 100644 index 0000000..73e76db --- /dev/null +++ b/src/test/java/org/onap/aai/validation/reader/TestOxmConfigTranslator.java @@ -0,0 +1,111 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.reader; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; + +import java.nio.file.InvalidPathException; +import java.util.List; +import java.util.Map; +import java.util.ServiceConfigurationError; +import org.junit.Test; +import org.onap.aai.setup.SchemaLocationsBean; +import org.onap.aai.setup.Version; +import org.onap.aai.validation.reader.OxmConfigTranslator; +import org.springframework.test.util.ReflectionTestUtils; + +public class TestOxmConfigTranslator { + + static { + System.setProperty("APP_HOME", "."); + } + + @Test + public void testOxmFiles() { + OxmConfigTranslator translator = buildConfigTranslator("src/test/resources/oxm-reader/single/"); + Map<Version, List<String>> latestVersion = translator.getNodeFiles(); + assertThat(latestVersion.size(), is(3)); + assertThat(latestVersion.values().iterator().next().size(), is(1)); + assertThat(latestVersion.values().iterator().next().get(0), not(isEmptyString())); + Map<Version, List<String>> latestVersion1 = translator.getEdgeFiles(); + assertThat(latestVersion1.size(), is(1)); + assertThat(latestVersion1.values().iterator().next().size(), is(1)); + assertThat(latestVersion1.values().iterator().next().get(0), not(isEmptyString())); + } + + @Test + public void testMultipleOxmFilesPerVersion() { + OxmConfigTranslator translator = buildConfigTranslator("src/test/resources/oxm-reader/multiple"); + Map<Version, List<String>> latestVersion = translator.getNodeFiles(); + assertThat(latestVersion.size(), is(2)); + assertThat(latestVersion.values().iterator().next().size(), is(2)); + assertThat(latestVersion.values().iterator().next().get(0), not(isEmptyString())); + Map<Version, List<String>> latestVersion1 = translator.getEdgeFiles(); + assertThat(latestVersion1.size(), is(0)); + } + + @Test + public void testZeroMatchingFiles() { + OxmConfigTranslator translator = buildConfigTranslator("src/test/resources/oxm-reader/"); + Map<Version, List<String>> versionsMap = translator.getNodeFiles(); + assertThat(versionsMap.size(), is(0)); + } + + @Test(expected = ServiceConfigurationError.class) + public void testNullNodesPath() { + buildConfigTranslator(null).getNodeFiles(); + } + + @Test(expected = ServiceConfigurationError.class) + public void testNullEdgesPath() { + buildConfigTranslator(null).getEdgeFiles(); + } + + @Test(expected = ServiceConfigurationError.class) + public void testNonExistentNodesPath() { + buildConfigTranslator("no-such-folder-exists/").getNodeFiles(); + } + + @Test(expected = ServiceConfigurationError.class) + public void testNonExistentEdgesPath() { + SchemaLocationsBean bean = new SchemaLocationsBean(); + ReflectionTestUtils.setField(bean, "nodeDirectory", "src/test/resources/oxm-reader/"); + ReflectionTestUtils.setField(bean, "edgeDirectory", "no-such-folder-exists/"); + new OxmConfigTranslator(bean).getEdgeFiles(); + } + + @Test(expected = InvalidPathException.class) + public void testInvalidPath() { + buildConfigTranslator("\0").getEdgeFiles(); + } + + private OxmConfigTranslator buildConfigTranslator(String path) { + return new OxmConfigTranslator(createSchemaLocationsBean(path)); + } + + private SchemaLocationsBean createSchemaLocationsBean(String path) { + SchemaLocationsBean bean = new SchemaLocationsBean(); + ReflectionTestUtils.setField(bean, "nodeDirectory", path); + ReflectionTestUtils.setField(bean, "edgeDirectory", path); + return bean; + } + +} diff --git a/src/test/java/org/onap/aai/validation/reader/TestOxmReader.java b/src/test/java/org/onap/aai/validation/reader/TestOxmReader.java new file mode 100644 index 0000000..f7f2643 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/reader/TestOxmReader.java @@ -0,0 +1,63 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.reader; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.util.List; +import javax.inject.Inject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.validation.reader.OxmReader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@TestPropertySource(properties = {"schemaIngestPropLoc = src/test/resources/oxm-reader/schemaIngest.properties"}) +@ContextConfiguration(locations = {"classpath:oxm-reader/oxm-reader-beans.xml"}) +public class TestOxmReader { + + static { + System.setProperty("APP_HOME", "."); + } + + @Inject + private OxmReader oxmReader; + + @Test + public void testGetPrimaryKeysSingleKey() throws Exception { + List<String> primaryKeys = oxmReader.getPrimaryKeys("connector"); + assertThat(primaryKeys.get(0), is("resource-instance-id")); + } + + @Test + public void testGetPrimaryKeysMultipleKeys() throws Exception { + List<String> primaryKeys = oxmReader.getPrimaryKeys("cloud-region"); + assertThat(primaryKeys, contains("cloud-owner", "cloud-region-id")); + } + + @Test + public void testGetPrimaryKeysUnknownObject() throws Exception { + List<String> primaryKeys = oxmReader.getPrimaryKeys("most-surely-does-not-exist"); + assertThat(primaryKeys, empty()); + } +} diff --git a/src/test/java/org/onap/aai/validation/request/TestRequestHeaders.java b/src/test/java/org/onap/aai/validation/request/TestRequestHeaders.java new file mode 100644 index 0000000..b9ff07c --- /dev/null +++ b/src/test/java/org/onap/aai/validation/request/TestRequestHeaders.java @@ -0,0 +1,143 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.request; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; +import javax.ws.rs.core.MultivaluedHashMap; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.aai.validation.services.RequestHeaders; +import org.springframework.http.HttpHeaders; + +/** + * Test the RequestHeaders class. + * + */ +public class TestRequestHeaders { + + static { + System.setProperty("APP_HOME", "."); + } + + @Test + public void testONAPHeaders() { + String transactionId = "transaction-id"; + String serviceInstanceId = "service-instance-id"; + + MultivaluedHashMap<String, String> headersMap = new MultivaluedHashMap<>(); + headersMap.put(RequestHeaders.HEADER_REQUEST_ID, createSingletonList(transactionId)); + headersMap.put(RequestHeaders.HEADER_SERVICE_INSTANCE_ID, createSingletonList(serviceInstanceId)); + headersMap.put("X-FromAppId", createSingletonList("app-id")); + headersMap.put("Host", createSingletonList("hostname")); + + HttpHeaders headers = createMockedHeaders(headersMap); + RequestHeaders requestHeaders = new RequestHeaders(headers); + assertThat(requestHeaders.getRequestId(), is(equalTo(transactionId))); + assertThat(requestHeaders.getInstanceId(), is(equalTo(serviceInstanceId))); + } + + @Test + public void testMultipleHeaderValues() { + String transactionId = "transaction-id"; + String serviceInstanceId = "service-instance-id"; + + MultivaluedHashMap<String, String> headersMap = new MultivaluedHashMap<>(); + headersMap.put(RequestHeaders.HEADER_REQUEST_ID, Arrays.asList(transactionId, "fred")); + headersMap.put(RequestHeaders.HEADER_SERVICE_INSTANCE_ID, Arrays.asList(serviceInstanceId, "bob")); + + HttpHeaders headers = createMockedHeaders(headersMap); + RequestHeaders requestHeaders = new RequestHeaders(headers); + assertThat(requestHeaders.getRequestId(), is(equalTo(transactionId))); + assertThat(requestHeaders.getInstanceId(), is(equalTo(serviceInstanceId))); + } + + @Test + public void testStandardHeaders() { + MultivaluedHashMap<String, String> headersMap = new MultivaluedHashMap<>(); + headersMap.put("X-TransactionId", createSingletonList("transaction-id")); + headersMap.put("X-FromAppId", createSingletonList("app-id")); + headersMap.put("Host", createSingletonList("hostname")); + + HttpHeaders headers = createMockedHeaders(headersMap); + RequestHeaders requestHeaders = new RequestHeaders(headers); + assertThat(requestHeaders.getRequestId(), is(nullValue())); + assertThat(requestHeaders.getInstanceId(), is(nullValue())); + } + + @Test + public void testEmptyHeaders() { + MultivaluedHashMap<String, String> headersMap = new MultivaluedHashMap<>(); + headersMap.put(RequestHeaders.HEADER_REQUEST_ID, Collections.emptyList()); + headersMap.put(RequestHeaders.HEADER_SERVICE_INSTANCE_ID, Collections.emptyList()); + + HttpHeaders headers = createMockedHeaders(headersMap); + RequestHeaders requestHeaders = new RequestHeaders(headers); + assertThat(requestHeaders.getRequestId(), is(nullValue())); + assertThat(requestHeaders.getInstanceId(), is(nullValue())); + } + + @Test + public void testNullHeaders() { + MultivaluedHashMap<String, String> headersMap = new MultivaluedHashMap<>(); + headersMap.put(RequestHeaders.HEADER_REQUEST_ID, Collections.emptyList()); + + HttpHeaders headers = createMockedHeaders(headersMap); + Mockito.when(headers.getFirst(RequestHeaders.HEADER_SERVICE_INSTANCE_ID)).thenReturn(null); + + RequestHeaders requestHeaders = new RequestHeaders(headers); + assertThat(requestHeaders.getRequestId(), is(nullValue())); + assertThat(requestHeaders.getInstanceId(), is(nullValue())); + } + + @Test + public void testToString() { + String transactionId = "transaction-id"; + String serviceInstanceId = "service-instance-id"; + + MultivaluedHashMap<String, String> headersMap = new MultivaluedHashMap<>(); + headersMap.put(RequestHeaders.HEADER_REQUEST_ID, createSingletonList(transactionId)); + headersMap.put(RequestHeaders.HEADER_SERVICE_INSTANCE_ID, createSingletonList(serviceInstanceId)); + + HttpHeaders headers = createMockedHeaders(headersMap); + RequestHeaders requestHeaders = new RequestHeaders(headers); + assertThat(requestHeaders.toString(), + is(equalTo("RequestHeaders [requestId=transaction-id, instanceId=service-instance-id]"))); + } + + private HttpHeaders createMockedHeaders(MultivaluedHashMap<String, String> headersMap) { + HttpHeaders headers = Mockito.mock(HttpHeaders.class); + for (Entry<String, List<String>> entry : headersMap.entrySet()) { + List<String> valuesList = entry.getValue(); + String value = valuesList == null || valuesList.isEmpty() ? null : valuesList.get(0); + Mockito.when(headers.getFirst(entry.getKey())).thenReturn(value); + } + return headers; + } + + private List<String> createSingletonList(String listItem) { + return Collections.<String>singletonList(listItem); + } +} diff --git a/src/test/java/org/onap/aai/validation/result/TestValidationResult.java b/src/test/java/org/onap/aai/validation/result/TestValidationResult.java new file mode 100644 index 0000000..5d02101 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/result/TestValidationResult.java @@ -0,0 +1,444 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.result; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import javax.inject.Inject; +import org.junit.Before; +import org.junit.BeforeClass; +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.data.Entity; +import org.onap.aai.validation.result.ValidationResult; +import org.onap.aai.validation.result.Violation; +import org.onap.aai.validation.result.Violation.Builder; +import org.onap.aai.validation.result.Violation.ViolationType; +import org.onap.aai.validation.test.util.TestUtil; +import org.onap.aai.validation.util.JsonUtil; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@TestPropertySource(properties = {"schemaIngestPropLoc = src/test/resources/oxm-reader/schemaIngest.properties"}) +@ContextConfiguration(locations = {"classpath:validation-result/test-validation-service-beans.xml"}) +public class TestValidationResult { + + static { + System.setProperty("APP_HOME", "."); + } + + @Inject + private EventReader eventReader; + + private static String vserverEvent; + private static Entity entity; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + vserverEvent = TestUtil.getFileAsString(TestData.VSERVER.getFilename()); + } + + @Before + public void setUp() throws Exception { + entity = eventReader.getEntity(vserverEvent); + } + + enum TestData { + // @formatter:off + VSERVER ("validation-result/vserver-create-event.json"); + + private String filename; + TestData(String filename) {this.filename = filename;} + public String getFilename() {return this.filename;} + // @formatter:on + } + + @Test + public void testValidationResultWithViolationDetailsAsString() throws Exception { + // Violation details + Map<String, Object> violationDetails = new HashMap<>(); + violationDetails.put("attr1", "val1"); + violationDetails.put("attr2", "val2"); + + ValidationResult validationResult = getValidationResult(violationDetails); + ValidationResult transformedVr = toAndFromJson(validationResult); + + assertThatValidationResultIsValid(transformedVr); + Violation v = assertThatViolationIsValid(transformedVr, validationResult.getViolations().get(0)); + assertThat(v.getViolationDetails(), is(violationDetails)); + } + + @Test + public void testValidationResultWithViolationDetailsIncludingNull() throws Exception { + // Violation details + Map<String, Object> violationDetails = new HashMap<>(); + violationDetails.put("attr1", "val1"); + violationDetails.put("attr2", null); + + ValidationResult validationResult = getValidationResult(violationDetails); + ValidationResult transformedVr = toAndFromJson(validationResult); + + // Check + assertThatValidationResultIsValid(transformedVr); + Violation v = assertThatViolationIsValid(transformedVr, validationResult.getViolations().get(0)); + assertThat(v.getViolationDetails(), is(violationDetails)); + } + + @Test + public void testValidationResultWithViolationDetailsAsList() throws Exception { + // Violation details + Map<String, Object> violationDetails = new HashMap<>(); + violationDetails.put("attr1", Arrays.asList("val1", "val2")); + violationDetails.put("attr2", Arrays.asList("val3", "val4")); + + ValidationResult validationResult = getValidationResult(violationDetails); + ValidationResult transformedVr = toAndFromJson(validationResult); + + // Check + assertThatValidationResultIsValid(transformedVr); + Violation v = assertThatViolationIsValid(transformedVr, validationResult.getViolations().get(0)); + assertThat(v.getViolationDetails(), is(violationDetails)); + } + + @Test + public void testValidationResultWithViolationDetailsAsInt() throws Exception { + // Violation details + Map<String, Object> violationDetails = new HashMap<>(); + violationDetails.put("attr1", 1); + violationDetails.put("attr2", 2); + + ValidationResult validationResult = getValidationResult(violationDetails); + ValidationResult vr = toAndFromJson(validationResult); + + // Check + assertThatValidationResultIsValid(vr); + Violation v = assertThatViolationIsValid(vr, validationResult.getViolations().get(0)); + assertThat(v.getViolationDetails().get("attr1"), is(1.0)); + assertThat(v.getViolationDetails().get("attr2"), is(2.0)); + } + + @Test + public void testValidationResultWithViolationDetailsAsObject() throws Exception { + // Violation details + JsonArray jsonArray = new JsonArray(); + jsonArray.add("v1"); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("p1", jsonArray); + jsonObject.add("p2", jsonArray); + Map<String, Object> violationDetails = new HashMap<>(); + violationDetails.put("attr1", jsonObject); + + ValidationResult validationResult = getValidationResult(violationDetails); + ValidationResult transformedVr = toAndFromJson(validationResult); + + // Check + assertThatValidationResultIsValid(transformedVr); + Violation v = assertThatViolationIsValid(transformedVr, validationResult.getViolations().get(0)); + String jsonDetails = v.getViolationDetails().get("attr1").toString(); + JsonParser jsonParser = new JsonParser(); + JsonElement jsonElement = jsonParser.parse(jsonDetails); + assertThat(jsonObject, is(jsonElement)); + } + + @Test + public void testCompareObjects() throws Exception { + ValidationResult validationResult = new ValidationResult(entity); + assertThat(validationResult, is(not(equalTo(null)))); + + validationResult.setEntityId(new JsonObject()); + assertThat(validationResult, is(not(equalTo(null)))); + + ValidationResult other = new ValidationResult(entity); + assertThat(validationResult, is(not(equalTo(other)))); + + validationResult.setEntityType("type"); + assertThat(validationResult, is(not(equalTo(other)))); + + Map<String, Object> violationDetails = new HashMap<>(); + + //@formatter:off + Violation violation = new Violation.Builder(entity) + .category("category") + .severity("severity") + .violationType("violationType") + .violationDetails(violationDetails) + .errorMessage("errorMessage") + .build(); + //@formatter:on + + validationResult.addViolation(violation); + assertThat(validationResult, is(not(equalTo(other)))); + + // Force call to hashCode() + assertThat(validationResult.hashCode(), is(not(equalTo(other.hashCode())))); + + } + + /** + * Tests for comparing two Violation objects. The generated Violation ID must be deterministic. + * + * @throws Exception + */ + @Test + public void testCompareViolationObjects() throws Exception { + // Use the standard vserver event + Builder builder = new Violation.Builder(entity); + + // Force call to toString() for coverage only + assertThat(builder.toString(), is(equalTo(new Violation.Builder(entity).toString()))); + + // Build a blank violation + Violation violation = builder.build(); + + // Identity tests + assertThat(violation, is(not(equalTo(null)))); + assertThat(violation, is(not(equalTo(1)))); + assertThat(violation, is(equalTo(violation))); + + // Ensure that any violations we build are identical + testViolationIdsForEquality(builder, builder, true); + + // Create a copy of the vserver event and vary the resourceVersion + Entity entity2 = eventReader + .getEntity(vserverEvent.replaceFirst("resource-version\": \"1464193654", "resource-version\": \"123")); + + // The violationId produced for identically built violations is the same for each builder (although the vserver + // events differ). + testViolationIdsForEquality(new Violation.Builder(entity), new Violation.Builder(entity2), true); + + // The violationId produced must differ whenever the violation values differ. + testViolationIdsForInequality(new Violation.Builder(entity), new Violation.Builder(entity2)); + + // Make a new variant of the vserver event using a different entity Id + Entity entity3 = eventReader.getEntity( + vserverEvent.replaceFirst("vserver-id\": \"example-vserver-id-val-34666", "vserver-id\": \"123")); + + // The violationId produced for identically built violations is now different for each builder (because the + // entity Ids differ). + testViolationIdsForEquality(new Violation.Builder(entity), new Violation.Builder(entity3), false); + } + + /** + * Generate various violations using the supplied builders and assert the expected equality of the generated + * Violation IDs whenever the values supplied to the builders are the same. + * + * @param b1 a builder + * @param b2 another builder + * @param expectedResult whether or not the two builders should produce identical violations + * @throws ValidationServiceException + */ + private void testViolationIdsForEquality(Builder b1, Builder b2, Boolean expectedResult) + throws ValidationServiceException { + Violation v1 = b1.build(); + Violation v2 = b2.build(); + assertThatViolationsAreEqual(v1, v2, expectedResult); + + // Use the same category + String category = "INVALID OBJ"; + v1 = b1.category(category).build(); + v2 = b2.category(category).build(); + assertThatViolationsAreEqual(v1, v2, expectedResult); + + // Use the same severity + String severity = "CRITICAL"; + v1 = b1.severity(severity).build(); + v2 = b2.severity(severity).build(); + assertThatViolationsAreEqual(v1, v2, expectedResult); + + // Use the same violation type + v1 = b1.violationType(ViolationType.RULE).build(); + v2 = b2.violationType(ViolationType.RULE).build(); + assertThatViolationsAreEqual(v1, v2, expectedResult); + + // Use the same validation rule + String rule = "prov-status"; + v1 = b1.validationRule(rule).build(); + v2 = b2.validationRule(rule).build(); + assertThatViolationsAreEqual(v1, v2, expectedResult); + + // Use the same error message + String errorMessage = "Invalid prov-status value. Must have a value not equal to ACTIVE/active."; + v1 = b1.errorMessage(errorMessage).build(); + v2 = b2.errorMessage(errorMessage).build(); + assertThatViolationsAreEqual(v1, v2, expectedResult); + + // Use the same violation details + Map<String, Object> details = new HashMap<>(); + details.put(rule, "ACTIVE"); + v1 = b1.violationDetails(details).build(); + v2 = b2.violationDetails(details).build(); + assertThatViolationsAreEqual(v1, v2, expectedResult); + } + + /** + * Generate violations using the supplied builders and assert that the generated Violation IDs differ whenever the + * values supplied to the builders differ. + * + * @param builder + * @param builder2 + * @throws ValidationServiceException + */ + private void testViolationIdsForInequality(Builder builder, Builder builder2) throws ValidationServiceException { + Violation violation; + Violation other; + + // Vary the violation type + violation = builder.violationType("").build(); + other = builder2.violationType(ViolationType.RULE).build(); + assertThatViolationIdsDiffer(violation, other); + + violation = builder.violationType(ViolationType.NONE).build(); + other = builder2.violationType(ViolationType.RULE).build(); + assertThatViolationIdsDiffer(violation, other); + + // Vary the validation rule + violation = builder.validationRule(null).build(); + other = builder2.validationRule("rule").build(); + assertThatViolationIdsDiffer(violation, other); + + violation = builder.validationRule("rule1").build(); + other = builder2.validationRule(null).build(); + assertThatViolationIdsDiffer(violation, other); + + violation = builder.validationRule("rule1").build(); + other = builder2.validationRule("rule2").build(); + assertThatViolationIdsDiffer(violation, other); + + // Vary the category + violation = builder.category(null).build(); + other = builder2.category("category").build(); + assertThatViolationIdsDiffer(violation, other); + + violation = builder.category("category").build(); + other = builder2.category(null).build(); + assertThatViolationIdsDiffer(violation, other); + + violation = builder.category("category1").build(); + other = builder2.category("category2").build(); + assertThatViolationIdsDiffer(violation, other); + + // Vary the error message + violation = builder.validationRule("rule").build(); + other = builder2.validationRule("rule").errorMessage("message2").build(); + assertThatViolationIdsDiffer(violation, other); + + violation = builder.validationRule("rule").errorMessage("message1").build(); + other = builder2.validationRule("rule").errorMessage("message2").build(); + assertThatViolationIdsDiffer(violation, other); + + // Vary the severity + violation = builder.errorMessage("msg").build(); + other = builder2.errorMessage("msg").severity("sev2").build(); + assertThatViolationIdsDiffer(violation, other); + + violation = builder.errorMessage("msg").severity("sev1").build(); + other = builder2.errorMessage("msg").severity("sev2").build(); + assertThatViolationIdsDiffer(violation, other); + } + + private ValidationResult getValidationResult(Map<String, Object> violationDetails) + throws ValidationServiceException { + ValidationResult validationResult = new ValidationResult(entity); + + //@formatter:off + Violation violation = new Violation.Builder(entity) + .category("category") + .severity("severity") + .violationType("violationType") + .violationDetails(violationDetails) + .errorMessage("errorMessage") + .build(); + //@formatter:on + + validationResult.addViolation(violation); + + return validationResult; + } + + private ValidationResult toAndFromJson(ValidationResult validationResult) { + return JsonUtil.toAnnotatedClassfromJson(validationResult.toJson(), ValidationResult.class); + } + + private void assertThatValidationResultIsValid(ValidationResult vr) { + assertTrue("Expected valid UUID", isValidEventId(vr.getValidationId())); + assertIsValidTimestamp(vr.getValidationTimestamp()); + JsonObject expectedEntityId = new JsonObject(); + expectedEntityId.addProperty("vserver-id", "example-vserver-id-val-34666"); + assertThat(vr.getEntityId(), is(expectedEntityId)); + assertThat(vr.getEntityType(), is("vserver")); + assertThat(vr.getResourceVersion(), is("1464193654")); + assertThat(vr.getEntityLink(), is( + "cloud-infrastructure/cloud-regions/cloud-region/region1/AAIregion1/tenants/tenant/example-tenant-id-val-88551/vservers/vserver/example-vserver-id-val-34666")); + } + + private Violation assertThatViolationIsValid(ValidationResult vr, Violation expectedViolation) { + Violation v = vr.getViolations().get(0); + assertThat(v.getViolationId(), is(expectedViolation.getViolationId())); + assertThat(v.getCategory(), is("category")); + assertThat(v.getSeverity(), is("severity")); + assertThat(v.getViolationType(), is("violationType")); + assertThat(v.getErrorMessage(), is("errorMessage")); + return v; + } + + private void assertThatViolationsAreEqual(Violation v1, Violation v2, Boolean expectedResult) { + assertThat("Violation equality in error:\n" + v1 + " equals " + v2, v1.equals(v2), is(expectedResult)); + assertThat("Violation ID equality in error:\n" + v1.getViolationId() + " equals " + v2.getViolationId(), + v1.getViolationId().equals(v2.getViolationId()), is(expectedResult)); + // Force a call to toString() for code coverage only + assertThat(v1.toString().equals(v2.toString()), is(equalTo(expectedResult))); + } + + private void assertThatViolationIdsDiffer(Violation violation, Violation other) { + assertThat(violation.getViolationId(), is(not(equalTo(other.getViolationId())))); + assertThat(violation, is(not(equalTo(other)))); + } + + private boolean isValidEventId(String eventId) { + try { + UUID.fromString(eventId); + } catch (IllegalArgumentException exception) { + return false; + } + return true; + } + + private void assertIsValidTimestamp(String date) { + DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmssX").withZone(ZoneOffset.UTC); + Instant.from(f.parse(date)); + } +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/configuration/ConfigFileBuilder.java b/src/test/java/org/onap/aai/validation/ruledriven/configuration/ConfigFileBuilder.java new file mode 100644 index 0000000..1f87ca0 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/configuration/ConfigFileBuilder.java @@ -0,0 +1,104 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.configuration; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; +import java.util.Properties; +import org.junit.rules.TemporaryFolder; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.validation.logging.LogHelper; +import org.onap.aai.validation.ruledriven.configuration.EntitySection; +import org.onap.aai.validation.ruledriven.configuration.RulesConfigurationLoader; +import org.onap.aai.validation.ruledriven.configuration.build.ContentBuilder; +import org.onap.aai.validation.ruledriven.configuration.build.EntityBuilder; +import org.onap.aai.validation.ruledriven.configuration.build.RuleBuilder; + +public class ConfigFileBuilder extends ContentBuilder { + + private static final Logger logger = LogHelper.INSTANCE; + + private static final String TMP_CONFIG_FILE = "config.txt"; + private TemporaryFolder testFolder; + private File tempFile; + + public ConfigFileBuilder(TemporaryFolder testFolder) { + super(); + this.testFolder = testFolder; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("ConfigBuilder [").append(testFolder.getRoot().getAbsolutePath()).append(System.lineSeparator()); + for (ContentBuilder item : items) { + sb.append(item).append(System.lineSeparator()); + } + sb.append(System.lineSeparator()).append("]"); + return sb.toString(); + } + + public EntityBuilder entity() { + EntityBuilder item = new EntityBuilder(); + addContent(item); + return item; + } + + public RuleBuilder rule() { + RuleBuilder item = new RuleBuilder(); + addContent(item); + return item; + } + + public void entity(Properties props) { + EntityBuilder entity = entity(); + entity.appendProperties(props); + } + + public RuleBuilder rule(String name) { + RuleBuilder rule = rule(); + rule.appendValue("name", name); + return rule; + } + + public List<EntitySection> loadConfiguration() throws IOException { + logger.debug("Configuration file: " + build()); + return buildConfiguration(build()); + } + + private List<EntitySection> buildConfiguration(String text) throws IOException { + tempFile = createConfigFile(text); + return RulesConfigurationLoader.loadConfiguration(tempFile).getEntities(); + } + + private File createConfigFile(String configText) throws IOException { + tempFile = testFolder.newFile(TMP_CONFIG_FILE); + BufferedWriter bw = new BufferedWriter(new FileWriter(tempFile)); + bw.write(configText); + bw.close(); + return tempFile; + } + + public void freeResources() { + tempFile.delete(); + } + +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/configuration/ConfigurationExceptionMatcher.java b/src/test/java/org/onap/aai/validation/ruledriven/configuration/ConfigurationExceptionMatcher.java new file mode 100644 index 0000000..f32c5d3 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/configuration/ConfigurationExceptionMatcher.java @@ -0,0 +1,73 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.configuration; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.onap.aai.validation.ruledriven.configuration.GroovyConfigurationException; + +public class ConfigurationExceptionMatcher { + public static Matcher<GroovyConfigurationException> hasInvalidToken(final String expectedToken) { + return new TypeSafeMatcher<GroovyConfigurationException>() { + private String foundToken; + + @Override + public void describeTo(Description description) { + description.appendText("result from getInvalidToken() equals \"").appendText(expectedToken) + .appendText("\""); + } + + @Override + public void describeMismatchSafely(final GroovyConfigurationException exception, + final Description mismatchDescription) { + mismatchDescription.appendText("was ").appendValue(foundToken); + } + + @Override + protected boolean matchesSafely(GroovyConfigurationException exception) { + foundToken = exception.getInvalidToken(); + return foundToken != null && foundToken.equalsIgnoreCase(expectedToken); + } + }; + } + + public static Matcher<GroovyConfigurationException> configTextContains(final String expectedConfigText) { + return new TypeSafeMatcher<GroovyConfigurationException>() { + private String foundConfigText; + + @Override + public void describeTo(Description description) { + description.appendText("result from getConfigText() containing \"").appendText(expectedConfigText) + .appendText("\""); + } + + @Override + public void describeMismatchSafely(final GroovyConfigurationException exception, + final Description mismatchDescription) { + mismatchDescription.appendText("was ").appendValue(foundConfigText); + } + + @Override + protected boolean matchesSafely(GroovyConfigurationException exception) { + foundConfigText = exception.getConfigText(); + return foundConfigText != null && foundConfigText.contains(expectedConfigText); + } + }; + } +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/configuration/TestConfigFileBuilder.java b/src/test/java/org/onap/aai/validation/ruledriven/configuration/TestConfigFileBuilder.java new file mode 100644 index 0000000..6d56fa8 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/configuration/TestConfigFileBuilder.java @@ -0,0 +1,59 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.configuration; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.onap.aai.validation.ruledriven.configuration.build.EntityBuilder; + +/** + * These tests are required to ensure code coverage by unit testing + * + */ +public class TestConfigFileBuilder { + + static { + System.setProperty("APP_HOME", "."); + } + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + /** + * Validate that a content builder accepts a numeric value + * + * @throws Exception + */ + @Test + public void testNumberItem() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + EntityBuilder ab = new EntityBuilder(); + ab.appendValue("dummy", 3); + ab.appendValue("dummy2", 5L); + builder.addContent(ab); + builder.toString(); + } + + @Test + public void testToString() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + builder.addContent(new EntityBuilder()); + builder.toString(); + } +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/configuration/TestRulesConfigurationReader.java b/src/test/java/org/onap/aai/validation/ruledriven/configuration/TestRulesConfigurationReader.java new file mode 100644 index 0000000..c0f9f48 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/configuration/TestRulesConfigurationReader.java @@ -0,0 +1,448 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.configuration; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.onap.aai.validation.ruledriven.configuration.EntitySection; +import org.onap.aai.validation.ruledriven.configuration.GroovyConfigurationException; +import org.onap.aai.validation.ruledriven.configuration.RuleSection; +import org.onap.aai.validation.ruledriven.configuration.SettingsSection; +import org.onap.aai.validation.ruledriven.configuration.build.EntityBuilder; +import org.onap.aai.validation.ruledriven.configuration.build.RuleBuilder; +import org.onap.aai.validation.ruledriven.configuration.build.ValidationBuilder; +import org.onap.aai.validation.test.util.RandomString; + +/** + * Tests for the Groovy classes that read and parse the rules configuration + * + */ +public class TestRulesConfigurationReader { + + static { + System.setProperty("APP_HOME", "."); + } + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + /** + * Exception expected by Junit. This is modified per test. + */ + @Rule + public final ExpectedException exception = ExpectedException.none(); + + private static final String INVALID_TOKEN = "audif"; + + @Test + public void testEmptyConfiguration() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + Collection<EntitySection> entitys = builder.loadConfiguration(); + assertThat(entitys.size(), is(0)); + } + + /** + * Test for reporting of an unknown token with various syntax formatting + * + * @throws Exception + */ + @Test + public void testInvalidTopLevelItem() throws Exception { + testInvalidToken(INVALID_TOKEN); + testInvalidToken(INVALID_TOKEN + " { }"); + testInvalidToken("{ " + INVALID_TOKEN + " }"); + testInvalidToken(INVALID_TOKEN + " { "); + testInvalidToken(INVALID_TOKEN + " } "); + testInvalidToken("{} " + INVALID_TOKEN); + testInvalidToken("\"" + INVALID_TOKEN); + } + + @Test + public void testInvalidentityItem1() throws Exception { + testInvalidToken("entity { invalid }", "invalid"); + } + + @Test + public void testInvalidentityItem2() throws Exception { + testInvalidToken("entity { invalid item }", "item"); + } + + @Test + public void testInvalidentityItem3() throws Exception { + testInvalidToken("entity { name name\n fred fred}", "name"); + } + + @Test + public void testInvalidQuery() throws Exception { + testInvalidToken("entity { name 'name'\n joe}", "joe"); + } + + @Test + public void testGenericRuleWithZeroAttributes() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + EntityBuilder entity = builder.entity(); + entity.appendValue("name", "entity"); + ValidationBuilder validation = entity.validation(buildProperties("type")); + validation.useRule("ruleZ"); + builder.rule("ruleZ"); + + exception.expect(GroovyConfigurationException.class); + exception.expectMessage(containsString("attributes")); + builder.loadConfiguration(); + } + + @Test + public void testInvalidUseRule() throws Exception { + testInvalidToken("entity { validation { useRule { foo } } }", "foo"); + } + + @Test + public void testMissingRule() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + builder.entity().validation().useRule("missingRule"); + exception.expect(GroovyConfigurationException.class); + exception.expectMessage(containsString("missingRule")); + builder.loadConfiguration(); + } + + @Test + public void testDuplicateRule() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + builder.rule("duplicateRule"); + builder.rule("duplicateRule"); + exception.expect(GroovyConfigurationException.class); + exception.expectMessage(containsString("duplicateRule")); + builder.loadConfiguration(); + } + + @Test + public void testSimpleentity() throws Exception { + String name = RandomString.generate(); + + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + Properties entity = new Properties(); + entity.put("name", name); + builder.entity(entity); + + List<EntitySection> entities = builder.loadConfiguration(); + + assertThat(entities.size(), is(1)); + EntitySection entityConf = entities.get(0); + assertThat(entityConf.getName(), is(equalTo(name))); + } + + /** + * The Settings section is not tested elsewhere + * + * @throws Exception + */ + @Test + public void testGlobalSettings() throws Exception { + SettingsSection settings = new SettingsSection(); + settings.toString(); + } + + @Test + public void testentityWithRuleUsingStrings() throws Exception { + String name = RandomString.generate(); + String description = RandomString.generate(); + String severity = RandomString.generate(); + List<String> attributes = Arrays.asList(RandomString.generate()); + String validate = randomValidationExpression(); + + Properties rule = new Properties(); + rule.put("name", name); + rule.put("description", description); + rule.put("severity", severity); + rule.put("attributes", attributes); + rule.put("validate", validate); + + String type = RandomString.generate(); + + Properties validation = new Properties(); + validation.put("type", type); + validation.put("rule", rule); + + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + Properties entity = new Properties(); + entity.put("validation", validation); + builder.entity(entity); + + List<EntitySection> entities = builder.loadConfiguration(); + + assertThat(entities.size(), is(1)); + EntitySection entityConf = entities.get(0); + Collection<RuleSection> rules = entityConf.getRules(); + assertThat(rules.size(), is(1)); + + RuleSection ruleConfig = rules.iterator().next(); + assertThat(ruleConfig.getName(), is(equalTo(name))); + assertThat(ruleConfig.getDescription(), is(equalTo(description))); + assertThat(ruleConfig.getSeverity(), is(equalTo(severity))); + assertThat(ruleConfig.getAttributes(), is(equalTo(attributes))); + assertThat(ruleConfig.getExpression(), is(equalTo(validate))); + assertThat(ruleConfig.getType(), is(equalTo(type))); + } + + @Test + public void testentityWithRuleUsingBuilder() throws Exception { + String name = RandomString.generate(); + String description = RandomString.generate(); + String severity = RandomString.generate(); + List<String> attributes = Arrays.asList(RandomString.generate()); + String validate = randomValidationExpression(); + String type = RandomString.generate(); + + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + ValidationBuilder validation = builder.entity().validation(); + validation.appendValue("type", type); + + RuleBuilder rule = validation.rule(name); + rule.appendValue("description", description); + rule.appendValue("severity", severity); + rule.appendValue("attributes", attributes); + rule.appendValue("validate", validate); + + List<EntitySection> entitys = builder.loadConfiguration(); + + assertThat(entitys.size(), is(1)); + EntitySection entityConf = entitys.get(0); + Collection<RuleSection> rules = entityConf.getRules(); + assertThat(rules.size(), is(1)); + + RuleSection ruleConfig = rules.iterator().next(); + assertThat(ruleConfig.getName(), is(equalTo(name))); + assertThat(ruleConfig.getDescription(), is(equalTo(description))); + assertThat(ruleConfig.getSeverity(), is(equalTo(severity))); + assertThat(ruleConfig.getAttributes(), is(equalTo(attributes))); + assertThat(ruleConfig.getExpression(), is(equalTo(validate))); + assertThat(ruleConfig.getType(), is(equalTo(type))); + } + + @Test + public void testentityWithEmbeddedRule() throws Exception { + Properties rule = buildProperties("name", "description", "severity", "validate"); + rule.put("attributes", Arrays.asList(RandomString.generate())); + + Properties validation = buildProperties("type"); + validation.put("rule", rule); + + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + Properties entity = new Properties(); + entity.put("validation", validation); + builder.entity(entity); + + List<EntitySection> entitys = builder.loadConfiguration(); + + assertThat(entitys.size(), is(1)); + EntitySection entityConf = entitys.get(0); + Collection<RuleSection> rules = entityConf.getRules(); + assertThat(rules.size(), is(1)); + + RuleSection ruleConfig = rules.iterator().next(); + assertThatConfigMatchesProperties(ruleConfig, rule, validation); + } + + @Test + public void testEmbeddedRuleUsingString() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + builder.appendLine("entity {"); + builder.appendLine(" type 'newvce'"); + builder.appendLine(" validation {"); + builder.appendLine(" rule {"); + builder.appendLine(" name 'vnfName'"); + builder.appendLine( + " description 'Validate that the vnf-name attribute matches the expected string format'"); + builder.appendLine(" severity 'MAJOR'"); + builder.appendLine(" attributes 'vnf-name'"); + builder.appendLine(" validate 'vnf-name.matchesPattern(xxxxnnnvbc)'"); + builder.appendLine(" }"); + builder.appendLine(" }"); + builder.appendLine("}"); + List<EntitySection> entitys = builder.loadConfiguration(); + + assertThat(entitys.size(), is(1)); + EntitySection entityConf = entitys.get(0); + assertThat(entityConf.getName(), is(equalTo("newvce"))); + + Collection<RuleSection> rules = entityConf.getRules(); + assertThat(rules.size(), is(1)); + RuleSection ruleConfig = rules.iterator().next(); + + assertThat(ruleConfig.getType(), is(equalTo("newvce"))); + assertThat(ruleConfig.getName(), is(equalTo("vnfName"))); + assertThat(ruleConfig.getDescription(), + is(equalTo("Validate that the vnf-name attribute matches the expected string format"))); + assertThat(ruleConfig.getSeverity(), is(equalTo("MAJOR"))); + List<String> expectedList = new ArrayList<String>(); + expectedList.add("vnf-name"); + assertThat(ruleConfig.getAttributes(), is(equalTo(expectedList))); + assertThat(ruleConfig.getExpression(), is(equalTo("vnf-name.matchesPattern(xxxxnnnvbc)"))); + } + + @Test + public void testGenericRuleUsingStrings() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + builder.appendLine("entity {"); + builder.appendLine(" type 'newvce'"); + builder.appendLine(" validation {"); + builder.appendLine(" useRule {"); + builder.appendLine(" name 'genericRule'"); + builder.appendLine(" attributes 'clli'"); + builder.appendLine(" }"); + builder.appendLine(" }"); + builder.appendLine("}"); + builder.appendLine("rule {"); + builder.appendLine(" name 'genericRule'"); + builder.appendLine(" description 'The field (attribute) must be less than 50 characters in length'"); + builder.appendLine(" severity 'MINOR'"); + builder.appendLine(" validate 'attribute.size() < 50'"); + builder.appendLine("}"); + + List<EntitySection> entitys = builder.loadConfiguration(); + assertThat(entitys.size(), is(1)); + EntitySection entityConf = entitys.get(0); + assertThat(entityConf.getName(), is(equalTo("newvce"))); + + Collection<RuleSection> rules = entityConf.getRules(); + assertThat("Number of rules", rules.size(), is(1)); + RuleSection ruleConfig = rules.iterator().next(); + + assertThat(ruleConfig.getType(), is(equalTo("newvce"))); + assertThat(ruleConfig.getName(), is(equalTo("genericRule"))); + assertThat(ruleConfig.getDescription(), + is(equalTo("The field (attribute) must be less than 50 characters in length"))); + assertThat(ruleConfig.getSeverity(), is(equalTo("MINOR"))); + List<String> expectedList = new ArrayList<String>(); + expectedList.add("clli"); + assertThat(ruleConfig.getAttributes(), is(equalTo(expectedList))); + assertThat(ruleConfig.getExpression(), is(equalTo("attribute.size() < 50"))); + } + + @Test + public void testMultipleGenericRules() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + EntityBuilder entity = builder.entity(); + ValidationBuilder validation = entity.validation(buildProperties("type")); + validation.useRule("rule1"); + validation.useRule("rule2").appendValue("attributes", "attr"); + builder.rule("rule1").appendValue("attributes", "field").appendValue("validate", "true"); + builder.rule("rule2").appendValue("validate", "true"); + + List<EntitySection> entitys = builder.loadConfiguration(); + + assertThat(entitys.size(), is(1)); + EntitySection entityConf = entitys.get(0); + Collection<RuleSection> rules = entityConf.getRules(); + assertThat(rules.size(), is(2)); + + Iterator<RuleSection> iterator = rules.iterator(); + RuleSection ruleConfig = iterator.next(); + assertThat(ruleConfig.getName(), is(equalTo("rule1"))); + assertThat(ruleConfig.getAttributes(), is(Collections.singletonList("field"))); + + ruleConfig = iterator.next(); + assertThat(ruleConfig.getName(), is(equalTo("rule2"))); + assertThat(ruleConfig.getAttributes(), is(Collections.singletonList("attr"))); + } + + @Test + public void testGenericRuleWithMultipleAttributes() throws Exception { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + EntityBuilder entity = builder.entity(); + ValidationBuilder validation = entity.validation(buildProperties("type")); + validation.useRule("rule").appendValue("attributes", Arrays.asList("attr1", "attr2")); + builder.rule("rule").appendValue("attributes", Arrays.asList("field1", "field2")).appendValue("validate", + "true"); + + List<EntitySection> entities = builder.loadConfiguration(); + + assertThat(entities.size(), is(1)); + EntitySection entityConf = entities.get(0); + Collection<RuleSection> rules = entityConf.getRules(); + assertThat(rules.size(), is(1)); + + Iterator<RuleSection> iterator = rules.iterator(); + RuleSection ruleConfig = iterator.next(); + assertThat(ruleConfig.getName(), is(equalTo("rule"))); + assertThat(ruleConfig.getAttributes(), is(Arrays.asList("attr1", "attr2"))); + } + + private String randomValidationExpression() { + String validate = RandomString.generate(); + while (validate.matches("^\\d+[a-fA-F]+\\D+.*") || validate.matches("0x\\D+.*")) { + validate = RandomString.generate(); + } + return validate; + } + + private void testInvalidToken(String configText) throws IOException { + testInvalidToken(configText, INVALID_TOKEN); + } + + private void testInvalidToken(String configText, String invalidToken) throws IOException { + ConfigFileBuilder builder = new ConfigFileBuilder(testFolder); + builder.addContent(configText); + assertConfigurationException(invalidToken); + builder.loadConfiguration(); + } + + private void assertConfigurationException(String invalidToken) { + exception.expect(GroovyConfigurationException.class); + exception.expectMessage(containsString(invalidToken)); + exception.expect(ConfigurationExceptionMatcher.hasInvalidToken(invalidToken)); + exception.expect(ConfigurationExceptionMatcher.configTextContains(invalidToken)); + } + + private Properties buildProperties(String... strings) { + Properties props = new Properties(); + for (String str : strings) { + props.put(str, randomValidationExpression()); + } + return props; + } + + private void assertThatConfigMatchesProperties(RuleSection ruleConfig, Properties rule, Properties validation) { + assertMatch(ruleConfig.getName(), rule, "name"); + assertMatch(ruleConfig.getDescription(), rule, "description"); + assertMatch(ruleConfig.getSeverity(), rule, "severity"); + assertThat(ruleConfig.getAttributes(), is(equalTo(rule.get("attributes")))); + assertMatch(ruleConfig.getExpression(), rule, "validate"); + assertMatch(ruleConfig.getType(), validation, "type"); + assertMatch(ruleConfig.getObjectId(), validation, "objectId"); + } + + private void assertMatch(String value, Properties props, String key) { + assertThat(value, is(equalTo(props.getProperty(key)))); + } +} 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 new file mode 100644 index 0000000..c3b36ed --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/mock/TestDefaultRules.java @@ -0,0 +1,148 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.mock; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +import com.google.gson.JsonObject; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; +import org.onap.aai.validation.Validator; +import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.reader.EventReader; +import org.onap.aai.validation.reader.data.AttributeValues; +import org.onap.aai.validation.reader.data.Entity; +import org.onap.aai.validation.reader.data.EntityId; +import org.onap.aai.validation.result.ValidationResult; +import org.onap.aai.validation.result.Violation; +import org.onap.aai.validation.ruledriven.RuleDrivenValidator; + +/** + * Test that the rules present under bundleconfig/etc/rules/ can be loaded and evaluated (using a mocked event). + * + */ +@RunWith(MockitoJUnitRunner.class) +public class TestDefaultRules { + + static { + System.setProperty("APP_HOME", "."); + } + + enum TestCase { + NULL, + VSERVER; + } + + // Data returned by the mocked EventReader + enum TestData { + // @formatter:off + ENTITTY_DATA ("vserver dummy json data"), + ENTITTY_TYPE ("vserver"), + RESOURCE_VERSION_VALUE("1476735182"), + VSERVER_ID_KEY ("vserver-id"), + VSERVER_ID_VALUE ("13b629a4-87ae-492d-943f-acb8f3d9c3d9"); + // @formatter:on + + private String value; + + TestData(String value) { + this.value = value; + } + } + + @Mock + private EventReader eventReader; + + @Mock + private Entity entity; + + private Validator ruleDrivenValidator; + + @Before + public void createMockEventReader() throws ValidationServiceException { + when(eventReader.getEventType(TestCase.VSERVER.name())).thenReturn(Optional.of("aai-event")); + when(eventReader.getEventType(TestCase.NULL.name())).thenReturn(null); + + when(eventReader.getEntityType(anyString())).thenReturn(Optional.of(TestData.ENTITTY_TYPE.value)); + when(eventReader.getEntity(anyString())).thenReturn(entity); + + // Mocked entity returned by the event reader + when(entity.getType()).thenReturn(TestData.ENTITTY_TYPE.value); + when(entity.getResourceVersion()).thenReturn(Optional.of(TestData.RESOURCE_VERSION_VALUE.value)); + + EntityId entityId = new EntityId(TestData.VSERVER_ID_KEY.value, TestData.VSERVER_ID_VALUE.value); + when(entity.getIds()).thenReturn(new ArrayList<>(Arrays.asList(entityId))); + + // Return dummy values for any requested attributes + when(entity.getAttributeValues(anyListOf(String.class))).thenAnswer(new Answer<AttributeValues>() { + @SuppressWarnings("unchecked") + @Override + public AttributeValues answer(InvocationOnMock invocation) { + AttributeValues attributeValues = new AttributeValues(); + for (String attribute : (List<String>) invocation.getArguments()[0]) { + if (attribute.contains("[*]")) { + attributeValues.put(attribute, Collections.emptyList()); + } else { + attributeValues.put(attribute, ""); + } + } + return attributeValues; + } + }); + } + + @Before + public void createRuleDrivenValidator() throws ValidationServiceException { + Path configurationPath = Paths.get("bundleconfig/etc/rules"); + ruleDrivenValidator = new RuleDrivenValidator(configurationPath, null, eventReader, null); + } + + @Test + public void testExecuteRulesForVserver() throws Exception { + List<ValidationResult> results = ruleDrivenValidator.validate(TestCase.VSERVER.name()); + assertThat(results.size(), is(1)); + + ValidationResult validationResult = results.get(0); + assertThat(validationResult.getEntityType(), is(equalTo(TestData.ENTITTY_TYPE.value))); + JsonObject expectedEntityId = new JsonObject(); + expectedEntityId.addProperty(TestData.VSERVER_ID_KEY.value, TestData.VSERVER_ID_VALUE.value); + assertThat(validationResult.getEntityId(), is(equalTo(expectedEntityId))); + assertThat(validationResult.getViolations().size(), is(2)); + + Violation violation = validationResult.getViolations().get(0); + assertThat(violation.getCategory(), is(equalTo("MISSING_REL"))); + } + +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/rule/RuleHelper.java b/src/test/java/org/onap/aai/validation/ruledriven/rule/RuleHelper.java new file mode 100644 index 0000000..456d011 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/rule/RuleHelper.java @@ -0,0 +1,36 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.rule; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.onap.aai.validation.reader.data.AttributeValues; +import org.onap.aai.validation.ruledriven.rule.Rule; + +public class RuleHelper { + + static void assertRuleResult(Rule rule, AttributeValues values, Boolean expectedResult) { + assertThat(rule + " failed for values [" + values + "]", rule.execute(values), is(equalTo(expectedResult))); + } + + static void assertRuleResult(Rule rule, Object value, Boolean expectedResult) { + assertThat(rule + " failed for value [" + value + "]", rule.execute(value), is(equalTo(expectedResult))); + } +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/rule/RuleTester.java b/src/test/java/org/onap/aai/validation/ruledriven/rule/RuleTester.java new file mode 100644 index 0000000..8593f93 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/rule/RuleTester.java @@ -0,0 +1,47 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.rule; + +import org.onap.aai.validation.reader.data.AttributeValues; +import org.onap.aai.validation.ruledriven.rule.Rule; + +/** + * Helper class for testing rules + * + */ +public class RuleTester { + + private Rule rule; + private AttributeValues attributeValues; + + /** + * @param trinityRule + * @param attributeValues + */ + public RuleTester(Rule trinityRule, AttributeValues attributeValues) { + this.rule = trinityRule; + this.attributeValues = attributeValues; + } + + /** + * @param expectedResult + */ + public void test(boolean expectedResult) { + RuleHelper.assertRuleResult(rule, attributeValues, expectedResult); + } +} 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 new file mode 100644 index 0000000..f226252 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/rule/TestConfigurationLoader.java @@ -0,0 +1,190 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.rule; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.LinkedHashSet; +import java.util.Set; +import javax.inject.Inject; +import org.junit.Test; +import org.onap.aai.validation.reader.OxmReader; +import org.onap.aai.validation.reader.data.AttributeValues; +import org.onap.aai.validation.ruledriven.RuleDrivenValidator; +import org.onap.aai.validation.ruledriven.rule.Rule; + +public class TestConfigurationLoader { + + static { + System.setProperty("APP_HOME", "."); + } + + private enum AAIRelation { + RELATED_TO("related-to"), + PROPERTY_KEY("property-key"), + PROPERTY_VALUE("property-value"); + + private final String text; + + /** + * @param text + */ + private AAIRelation(final String text) { + this.text = text; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Enum#toString() + */ + @Override + public String toString() { + return text; + } + } + + @Inject + private OxmReader oxmReader; + + /** + * If vserver is related to an image with image-name = 'TRINITY' then generic-vnf.vnf-name must match xxxxnnnnv + */ + @Test + public void testTrinityRule() throws Exception { + Path configurationPath = Paths.get("bundleconfig/etc/rules"); + + RuleDrivenValidator validator = new RuleDrivenValidator(configurationPath, oxmReader, null, null); + validator.initialise(); + + // Find the trinity rule + Rule trinityRule = null; + for (Rule rule : validator.getRulesForEntity("vserver", "aai-event")) { + if (rule.getName().contains("TRINITY") && rule.getName().contains("generic-vnf")) { + trinityRule = rule; + } + } + + // Create a set of relationship objects to be passed to the rule + Set<JsonObject> relationships = new LinkedHashSet<>(); + AttributeValues attributeValues = new AttributeValues(); + attributeValues.put("relationship-list.relationship[*]", relationships); + + // Test the rule against the relationships + RuleTester ruleTester = new RuleTester(trinityRule, attributeValues); + ruleTester.test(true); + + JsonObject genericVnfData = createRelationshipData(relationships, "generic-vnf"); + ruleTester.test(true); + + // Add a new object for the image relationship + 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); + ruleTester.test(true); + + setPropertyKey(imageNameProperty, "image.image-name"); + ruleTester.test(true); + + setPropertyValue(imageNameProperty, "not TRINITY"); + ruleTester.test(true); + + setPropertyValue(imageNameProperty, "TRINITY"); + ruleTester.test(false); + + JsonObject vnfNameProperty = createRelatedToProperty(genericVnfData); + ruleTester.test(false); + + setPropertyKey(vnfNameProperty, "generic-vnf.vnf-name"); + ruleTester.test(false); + + setPropertyValue(vnfNameProperty, "invalid"); + ruleTester.test(false); + + setPropertyValue(vnfNameProperty, ""); + ruleTester.test(false); + + setPropertyValue(vnfNameProperty, "bmsx0001v"); + ruleTester.test(true); + + // Add another new object for a different image relationship + JsonObject image2Data = createRelationshipData(relationships, "image"); + ruleTester.test(true); + + JsonObject image2NameProperty = createRelatedToProperty(image2Data); + ruleTester.test(true); + + setPropertyKey(image2NameProperty, "image.image-name"); + ruleTester.test(true); + + setPropertyValue(image2NameProperty, "not TRINITY"); + ruleTester.test(true); + + setPropertyValue(vnfNameProperty, "invalid"); + ruleTester.test(false); + + setPropertyValue(imageNameProperty, "not TRINITY"); + ruleTester.test(true); + + setPropertyValue(image2NameProperty, "TRINITY"); + ruleTester.test(false); + + setPropertyValue(image2NameProperty, "also not TRINITY"); + ruleTester.test(true); + } + + /** + * @param relationshipData + * @return + */ + private JsonObject createRelatedToProperty(JsonObject relationshipData) { + JsonObject imageNameProperty = new JsonObject(); + JsonElement jsonArray = new JsonArray(); + jsonArray.getAsJsonArray().add(imageNameProperty); + relationshipData.add("related-to-property", jsonArray); + return imageNameProperty; + } + + /** + * @param relationships + * @param relatedObject + * @return + */ + private JsonObject createRelationshipData(Set<JsonObject> relationships, String relatedObject) { + JsonObject relationData = new JsonObject(); + 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); + } + + private void setPropertyValue(JsonObject objectMap, String propertyValue) { + objectMap.addProperty(AAIRelation.PROPERTY_VALUE.toString(), propertyValue); + } +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/rule/TestRuleExecution.java b/src/test/java/org/onap/aai/validation/ruledriven/rule/TestRuleExecution.java new file mode 100644 index 0000000..15e958d --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/rule/TestRuleExecution.java @@ -0,0 +1,494 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.rule; + +import static org.hamcrest.CoreMatchers.containsString; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.validation.reader.data.AttributeValues; +import org.onap.aai.validation.ruledriven.configuration.GroovyConfigurationException; +import org.onap.aai.validation.ruledriven.configuration.RuleSection; +import org.onap.aai.validation.ruledriven.rule.GroovyRule; + +/** + * Tests for creating an AuditRule object and then executing the rule expression against fixed attribute values + * + * @see GroovyRule + * + */ +public class TestRuleExecution { + + static { + System.setProperty("APP_HOME", "."); + } + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + /** + * Simple example of a rule using a boolean expression, acting on a single attribute + * + * @throws Exception + */ + @Test + public void testRuleCreation() throws Exception { + // This object represents a rule + GroovyRule rule = buildRule("i", "i == 44"); + + // Success + assertRuleResult(rule, 44, true); + + // Failure + assertRuleResult(rule, 5, false); + } + + @Test + public void testRuleWithMultipleAttributes() throws Exception { + GroovyRule rule = buildRule(Arrays.asList("i", "j"), "i == 22 && j == 44"); + + // Success + assertRuleResult(rule, Arrays.asList(22, 44), true); + + // Failure + assertRuleResult(rule, Arrays.asList(5, 5), false); + assertRuleResult(rule, Arrays.asList(22, 5), false); + assertRuleResult(rule, Arrays.asList(5, 44), false); + } + + /** + * vserver is related to vpe and vserver-name contains me6 + */ + @Test + public void testConditionalRegExp() throws Exception { + // !related-to.contains("vpe") || vserver-name =~ "me6" + String expression = "!related-to.contains(\"vpe\") || vserver-name =~ \"me6\""; + List<String> attributes = Arrays.asList("related-to", "vserver-name"); + GroovyRule rule = buildRule(attributes, expression); + + // Create some tests, varying the values for each attribute + Collection<Collection<String>> relatedToTests = new ArrayList<>(); + Collection<Collection<String>> vserverNameTests = new ArrayList<>(); + + // These are the related-to values to test + relatedToTests.add(Collections.<String>emptyList()); + relatedToTests.add(Arrays.asList("vpe")); + relatedToTests.add(Arrays.asList("vpe", "vces")); + relatedToTests.add(Arrays.asList("vces")); + relatedToTests.add(Arrays.asList("other", "vces")); + + // These are the vserver-name values to test + Collection<String> testNames = new ArrayList<>(); + testNames.add("fred"); + testNames.add("me"); + testNames.add("me7"); + testNames.add("me6"); + testNames.add("123me6"); + testNames.add("me6789"); + testNames.add("123me6789"); + + // Additional test for no vserver-name values present + vserverNameTests.add(Collections.<String>emptyList()); + + for (String name : testNames) { + // Build single element lists containing the test vserver names + vserverNameTests.add(Arrays.asList(name)); + + // Also build multi-element lists containing the test vserver names + vserverNameTests.add(Arrays.asList(name, "6dummy")); + } + + // Now run the tests, computing the expected Boolean result each time + for (Collection<String> relatedToList : relatedToTests) { + // If no vpe is related, then the result will always be true + boolean expectedResult = !relatedToList.contains("vpe"); + + Map<String, Object> map = new HashMap<>(); + map.put("related-to", relatedToList); + + for (Collection<String> vserverNames : vserverNameTests) { + // Assign the strings to the attribute vserver-name + map.put("vserver-name", vserverNames); + + if (expectedResult == false) { + for (String name : vserverNames) { + if (name.contains("me6")) { + expectedResult = true; + break; + } + } + } + + testWithAttributeValue(rule, map, expectedResult); + } + } + } + + /** + * generic-vnf.vnf-type should be "BW NFM" and not "bnfm" + */ + @Test + public void testStringComparison() throws Exception { + String attribute = "generic-vnf.vnf-type"; + String expression = "vnf-type == 'BW NFM'"; + GroovyRule rule = buildRule(attribute, expression); + assertRuleResult(rule, "BW NFM", true); + assertRuleResult(rule, "bnfm", false); + assertRuleResult(rule, null, false); + assertRuleResult(rule, "", false); + assertRuleResult(rule, "fred", false); + assertRuleResult(rule, "bob", false); + assertRuleResult(rule, 5, false); + assertRuleResult(rule, 1000L, false); + } + + @Test + public void testNotEquals() throws Exception { + GroovyRule rule = buildRule("x", "x != 'foo'"); + assertRuleResult(rule, "", true); + assertRuleResult(rule, "bar", true); + assertRuleResult(rule, "foo", false); + assertRuleResult(rule, "foo\n", true); + assertRuleResult(rule, 5, true); + assertRuleResult(rule, 1000L, true); + assertRuleResult(rule, null, true); + } + + @Test + public void testGreaterThan() throws Exception { + Map<Object, Boolean> tests = new HashMap<>(); + tests.put(-1, false); + tests.put(0, false); + tests.put(1, false); + tests.put(4, false); + tests.put(5, true); + tests.put(55, true); + tests.put(null, false); + testRuleExpression("i", "i > 4", tests); + } + + @Test + public void testValidStringLength() throws Exception { + String attribute = "clli"; + String expression = "clli.size() == 8 || clli.size() == 11"; + Map<Object, Boolean> tests = new HashMap<>(); + tests.put("", false); + tests.put("X", false); + tests.put("1", false); + tests.put("1234", false); + tests.put("123456", false); + tests.put("1234567", false); + tests.put("12345678", true); + tests.put("123456789", false); + tests.put("1234567890", false); + tests.put("12345678901", true); + tests.put("1234567890ABC", false); + tests.put("1234567890123456789012345678901234567890", false); + testRuleExpression(attribute, expression, tests); + } + + /** + * location_clli is 8 or 11 characters and must be characters only + */ + @Test + public void testStringLengthAndChars() throws Exception { + String attribute = "location_clli"; + String expression = "location_clli != null && location_clli.matches('[a-zA-Z]{8,11}')"; + Map<Object, Boolean> tests = new HashMap<>(); + tests.put(null, false); + tests.put("", false); + tests.put("X", false); + tests.put("1234567", false); + tests.put("12345678", false); // 8 digits + tests.put("ABCDEFGH", true); // 8 chars + tests.put("1234567890A", false); // 11 mixed + tests.put("abcdefghijk", true); // 11 chars + tests.put("AbCdEfGhIjK", true); // 11 chars + tests.put("AbCdEfGhIj?", false); // special char + testRuleExpression(attribute, expression, tests); + } + + /** + * incorrect naming, e.g. expecting ae0.x (where x is unit/subinterface number), but receiving ae0.353.3303 + */ + @Test + public void testRegularExpression() throws Exception { + String attribute = "unit"; + String expression = "unit.matches('^ae0\\\\.(\\\\d)+')"; + Map<Object, Boolean> tests = new HashMap<>(); + tests.put("", false); + tests.put("X", false); + tests.put("ae0", false); + tests.put("ae0.", false); + tests.put("ae01", false); + tests.put("ae012", false); + tests.put("ae0.1", true); + tests.put("ae0.354", true); + tests.put("ae0.354.", false); + tests.put("ae0.353.3303", false); + tests.put("ae0.353.3303.1", false); + testRuleExpression(attribute, expression, tests); + } + + @Test + public void testNullStringLength() throws Exception { + String attribute = "clli"; + String expression = "clli.size() == 8 || clli.size() == 11"; + exception.expect(IllegalArgumentException.class); + exception.expectMessage(containsString("Argument")); + exception.expectMessage(containsString("null")); + GroovyRule rule = buildRule(attribute, expression); + rule.execute((Object[]) null); + } + + @Test + public void testStringLengthWithNull() throws Exception { + String attribute = "a"; + String expression = "a == null || a.size() > 4"; + Map<Object, Boolean> tests = new HashMap<>(); + tests.put("", false); + tests.put("X", false); + tests.put("1", false); + tests.put("1234", false); + tests.put("123456", true); + tests.put("1234567", true); + tests.put("12345678", true); + tests.put("123456789", true); + tests.put("1234567890", true); + tests.put("12345678901", true); + tests.put("1234567890ABC", true); + tests.put("1234567890123456789012345678901234567890", true); + testRuleExpression(attribute, expression, tests); + } + + /** + * Prov-status cannot be ACTIVE or NULL (empty) + */ + @Test + public void testStringTextWithNull() throws Exception { + String attribute = "prov-status"; + String expression = "prov-status != null && prov-status != 'ACTIVE'"; + Map<Object, Boolean> tests = new HashMap<>(); + tests.put(null, false); + tests.put("ACTIVE", false); + tests.put("", true); + tests.put("X", true); + tests.put("1", true); + tests.put("1234", true); + tests.put("123456", true); + tests.put("1234567", true); + tests.put("12345678", true); + tests.put("123456789", true); + tests.put("1234567890", true); + tests.put("12345678901", true); + tests.put("1234567890ABC", true); + tests.put("1234567890123456789012345678901234567890", true); + testRuleExpression(attribute, expression, tests); + } + + /** + * Prov-status cannot be ACTIVE/active or NULL/null or empty or missing + */ + @Test + public void testCaseInsensitveStringMatch() throws Exception { + String attribute = "prov-status"; + String expression = + "prov-status != null && prov-status.size() > 0 && !prov-status.equalsIgnoreCase('NULL') && !prov-status.equalsIgnoreCase('ACTIVE')"; + Map<Object, Boolean> tests = new HashMap<>(); + tests.put(null, false); + tests.put("", false); + tests.put("active", false); + tests.put("ACTIVE", false); + tests.put("null", false); + tests.put("NULL", false); + tests.put("NVTPROV", true); + tests.put("1", true); + tests.put("1234", true); + testRuleExpression(attribute, expression, tests); + } + + @Test + public void testUsingAttributeValuesObject() throws Exception { + List<String> attributes = Arrays.asList("attr1", "attr2"); + String expression = "attr1.size() == 8 || attr2.size() == 11"; + GroovyRule rule = buildRule(attributes, expression); + AttributeValues attributeValues = new AttributeValues("attr1", "other"); + attributeValues.put("attr2", "other"); + rule.execute(attributeValues); + } + + @Test + public void testMissingMethod() throws Exception { + String attribute = "clli"; + String expression = "clli.size() == 8 || clli.size() == 11"; + exception.expect(IllegalArgumentException.class); + exception.expectMessage(containsString("Integer")); + exception.expectMessage(containsString("size()")); + GroovyRule rule = buildRule(attribute, expression); + rule.execute(1); + } + + @Test + public void testMultipleAttributes() throws Exception { + List<String> attributes = Arrays.asList("clli", "other"); + String expression = "clli.size() == 8 || other.size() == 11"; + exception.expect(IllegalArgumentException.class); + exception.expectMessage(containsString("Integer")); + exception.expectMessage(containsString("size()")); + GroovyRule rule = buildRule(attributes, expression); + rule.execute(new Integer(1), new Integer(2)); + } + + /** + * Compare two attributes (using a sub-string match) + */ + @Test + public void testAttributeComparison() throws Exception { + String attribute1 = "heat-stack-id"; + String attribute2 = "vnf-name"; + + // Alternative forms of the expression + Collection<String> expressionsToTest = new ArrayList<>(); + expressionsToTest.add("heat-stack-id?.size() > 10 && heat-stack-id[0..10] == vnf-name"); + expressionsToTest.add("heat-stack-id?.size() > 10 && heat-stack-id.substring(0,11) == vnf-name"); + expressionsToTest.add("heat-stack-id?.size() > 10 && heat-stack-id.take(11) == vnf-name"); + + // Create some tests, varying the values for each attribute + Collection<String> heatStackIds = new ArrayList<>(); + Collection<String> vnfNames = new ArrayList<>(); + + heatStackIds.add("123me67890abcdef"); + heatStackIds.add("123me67890a"); + heatStackIds.add("fred"); + heatStackIds.add(""); + heatStackIds.add(null); + + vnfNames.add("123me67890abcdef"); + vnfNames.add("123me67890a"); + vnfNames.add("123me6789"); + vnfNames.add("fred"); + vnfNames.add("bob"); + vnfNames.add(""); + vnfNames.add(null); + + // Build a rule per expression + for (String expression : expressionsToTest) { + GroovyRule rule = buildRule(Arrays.asList(attribute1, attribute2), expression); + + // Now run the tests, computing the expected Boolean result each time + for (String heatStackId : heatStackIds) { + Map<String, Object> map = new HashMap<>(); + map.put(attribute1, heatStackId); + for (String vnfName : vnfNames) { + map.put(attribute2, vnfName); + boolean expectedExpressionResult = // Java equivalent of the expression + heatStackId != null && heatStackId.length() > 10 + && heatStackId.substring(0, 11).equals(vnfName); + testWithAttributeValue(rule, map, expectedExpressionResult); + } + } + } + } + + /** + * @param rule + * @param tests + */ + public void assertTestResults(GroovyRule rule, Map<Object, Boolean> tests) { + for (Entry<?, ?> e : tests.entrySet()) { + Object attributeValue = e.getKey(); + Boolean expectedResult = (Boolean) e.getValue(); + RuleHelper.assertRuleResult(rule, attributeValue, expectedResult); + } + } + + private void testWithAttributeValue(GroovyRule rule, Map<String, Object> map, boolean expectedResult) { + AttributeValues attributeValues = new AttributeValues(map); + RuleHelper.assertRuleResult(rule, attributeValues, expectedResult); + } + + private void testRuleExpression(String attributes, String expression, Map<Object, Boolean> tests) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + GroovyRule rule = buildRule("testRule", attributes, expression); + assertTestResults(rule, tests); + } + + /** + * Build a simple rule using a RuleConfiguration object + * + * @param name the rule name + * @param attribute a named variable, referenced in the expression + * @param expression the expression to evaluate (returns a Boolean value) + * @return + * @throws IOException + * @throws InstantiationException + * @throws IllegalAccessException + * @throws GroovyConfigurationException + */ + private GroovyRule buildRule(String name, String attribute, String expression) + throws IOException, InstantiationException, IllegalAccessException, GroovyConfigurationException { + RuleSection ruleConfig = new RuleSection(); + ruleConfig.setName(name); + ruleConfig.setAttributes(Collections.singletonList(attribute)); + ruleConfig.setExpression(expression); + return new GroovyRule(ruleConfig); + } + + private GroovyRule buildRule(String name, List<String> attributes, String expression) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + RuleSection ruleConfig = new RuleSection(); + ruleConfig.setName(name); + ruleConfig.setAttributes(attributes); + ruleConfig.setExpression(expression); + return new GroovyRule(ruleConfig); + } + + /** + * Build a simple rule (with a default name) using a RuleConfiguration object + * + * @see TestRuleExecution#buildRule(String, String, String) + * + * @param attribute a named variable, referenced in the expression + * @param expression the expression to evaluate (returns a Boolean value) + * @throws GroovyConfigurationException + */ + private GroovyRule buildRule(String attribute, String expression) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + return buildRule("testRule", attribute, expression); + } + + private GroovyRule buildRule(List<String> attributes, String expression) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + return buildRule("testRule", attributes, expression); + } + + private void assertRuleResult(GroovyRule rule, Object value, boolean expectedResult) { + RuleHelper.assertRuleResult(rule, value, expectedResult); + } + +} diff --git a/src/test/java/org/onap/aai/validation/ruledriven/rule/TestRuleValidation.java b/src/test/java/org/onap/aai/validation/ruledriven/rule/TestRuleValidation.java new file mode 100644 index 0000000..0650743 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/rule/TestRuleValidation.java @@ -0,0 +1,229 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.rule; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.validation.ruledriven.configuration.GroovyConfigurationException; +import org.onap.aai.validation.ruledriven.configuration.RuleSection; +import org.onap.aai.validation.ruledriven.rule.GroovyRule; + +/** + * Tests for creating an AuditRule object and then executing the rule expression against fixed attribute values + * + * @see GroovyRule + * + */ +public class TestRuleValidation { + + static { + System.setProperty("APP_HOME", "."); + } + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + /** + * Test multiple sample expressions each with various different attribute names. Each of the attribute names used in + * this test is valid for use within a rule. + * + * @throws GroovyConfigurationException + * @throws IOException + * @throws IllegalAccessException + * @throws InstantiationException + * + * @throws Exception + */ + @Test + public void testValidAttributeNames() + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + testValidExpressions("clli"); // Sample name + testValidExpressions("c"); + testValidExpressions("i"); // Short attribute name, part of the size() text + testValidExpressions("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + testValidExpressions("size"); // Does not interfere with .size() method call + testValidExpressions("s12"); // Digits allowed in the attribute name + testValidExpressions("s12s"); + testValidExpressions("12s"); + testValidExpressions("12-s"); // Hyphens supported + testValidExpressions("12_s"); // Underscores supported + testValidExpressions("if"); // Keyword + testValidExpressions("return"); + testValidExpressions("A.B.C"); // Dots indicate a JSON Path + } + + /** + * Test that the attribute name is sanitised. Each of the following attribute names is invalid for use in the rules + * configuration. + * + * @throws Exception + */ + @Test + public void testInvalidAttributeNames() throws Exception { + testInvalidAttributeName(""); // Zero-length + testInvalidAttributeName("null"); // Reserved keyword + testInvalidAttributeName("8"); // This would cause replacement of the value 8 in the expression + testInvalidAttributeName("size()"); // This would replace the call to size() + testInvalidAttributeName("s?"); // Special character not supported by the implementation + testInvalidAttributeName("\""); + testInvalidAttributeName("s\\"); + testInvalidAttributeName("s/"); + testInvalidAttributeName("s\""); + testInvalidAttributeName("s'"); + testInvalidAttributeName("=="); + } + + /** + * A rule cannot support an attribute that is zero-length. This test ensures that this is detected even when the + * expression itself is valid. + * + * @throws Exception + */ + @Test + public void testZeroLengthAttribute() throws Exception { + String attribute = ""; + String expression = "clli.size() == 8 || clli.size() == 11"; + GroovyRule rule = buildRule("testRule", attribute, expression); + assertThat(rule.toString(), rule.isValid(), is(equalTo(false))); + } + + @Test + public void testInvalidRuleSyntax() throws Exception { + String attribute = "fred"; + String expression = "fred. = 8 || fred.size() == 11"; + exception.expect(GroovyConfigurationException.class); + exception.expectMessage(containsString("unexpected")); + buildRule("testRule", attribute, expression); + } + + @Test + public void testInvalidAttribute() throws Exception { + String attribute = "fred"; + String expression = "size.size() == 8 || size.size() == 11"; + GroovyRule rule = buildRule("testRule", attribute, expression); + + assertThat(rule.toString(), rule.isValid(), is(equalTo(false))); + } + + /** + * Utility to build and test different expressions using the supplied attribute name + * + * @param attribute attribute (field) identifier + * @throws InstantiationException + * @throws IllegalAccessException + * @throws IOException + * @throws GroovyConfigurationException + */ + private void testValidExpressions(String attribute) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + testValidLengthRule(attribute); + } + + /** + * Utility to build and test an expression asserting that the size() of the attribute is 8 or 11 + * + * @param attribute attribute (field) identifier + * @throws InstantiationException + * @throws IllegalAccessException + * @throws IOException + * @throws GroovyConfigurationException + */ + private void testValidLengthRule(String attribute) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + String fieldName = attribute.substring(attribute.lastIndexOf(".") + 1); + String expression = fieldName + ".size() == 8 || " + fieldName + ".size() == 11"; + GroovyRule rule = buildRule("testRule", attribute, expression); + + // Test that the rule is valid + assertThat(rule.toString(), rule.isValid(), is(equalTo(true))); + + // Now test that the rule actually executes successfully + Map<Object, Boolean> tests = new HashMap<>(); + tests.put("", false); + tests.put("X", false); + tests.put("1234567", false); + tests.put("12345678", true); // 8 digits + tests.put("ABCDEFGH", true); // 8 chars + tests.put("12E4567890A", true); // 11 mixed digits/chars + tests.put("abcdefghijk", true); // 11 chars + tests.put("AbCdEfGhIjK", true); // 11 chars mixed case + tests.put("AbCdEfGhIj?", true); // special char + testRuleExpression(attribute, expression, tests); + } + + private void testRuleExpression(String attributes, String expression, Map<Object, Boolean> tests) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + GroovyRule rule = buildRule("testRule", attributes, expression); + assertThat("The rule should be valid", rule.isValid(), is(equalTo(true))); + for (Entry<?, ?> e : tests.entrySet()) { + Object attributeValue = e.getKey(); + Boolean expectedResult = (Boolean) e.getValue(); + RuleHelper.assertRuleResult(rule, attributeValue, expectedResult); + } + } + + /** + * Build a simple rule using a RuleConfiguration object + * + * @param name the rule name + * @param attribute a named variable, referenced in the expression + * @param expression the expression to evaluate (returns a Boolean value) + * @return + * @throws IOException + * @throws InstantiationException + * @throws IllegalAccessException + * @throws GroovyConfigurationException + */ + private GroovyRule buildRule(String name, String attribute, String expression) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + RuleSection ruleConfig = new RuleSection(); + ruleConfig.setName(name); + ruleConfig.setAttributes(Collections.singletonList(attribute)); + ruleConfig.setExpression(expression); + return new GroovyRule(ruleConfig); + } + + /** + * Utility to build a rule and test that the attribute is valid + * + * @param attribute attribute (field) identifier + * @throws InstantiationException + * @throws IllegalAccessException + * @throws IOException + * @throws GroovyConfigurationException + */ + private void testInvalidAttributeName(String attribute) + throws InstantiationException, IllegalAccessException, IOException, GroovyConfigurationException { + String expression = attribute + ".size() == 8 || " + attribute + ".size() == 11"; + GroovyRule rule = buildRule("testRule", attribute, expression); + + // Test that the rule is invalid + assertThat(rule.toString(), rule.isValid(), is(equalTo(false))); + } +} 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 new file mode 100644 index 0000000..cf1e874 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/ruledriven/validator/TestRuleDrivenValidator.java @@ -0,0 +1,125 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.ruledriven.validator; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +import com.google.gson.JsonSyntaxException; +import java.io.IOException; +import java.net.URISyntaxException; +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.List; +import java.util.function.BiPredicate; +import java.util.stream.Stream; +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.result.ValidationResult; +import org.onap.aai.validation.ruledriven.RuleDrivenValidator; +import org.onap.aai.validation.test.util.TestEntity; +import org.onap.aai.validation.test.util.ValidationResultIsEqual; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@TestPropertySource(properties = {"schemaIngestPropLoc = src/test/resources/oxm-reader/schemaIngest.properties"}) +@ContextConfiguration( + locations = {"classpath:" + TestRuleDrivenValidator.UNIT_TEST_FOLDER + "/test-rule-driven-validator-beans.xml"}) +public class TestRuleDrivenValidator { + + static { + System.setProperty("APP_HOME", "."); + } + + public static final String UNIT_TEST_FOLDER = "rule-driven-validator"; + private static final String TEST_EVENTS_PATH = "/test_events"; + + @Inject + private RuleDrivenValidator validator; + + /** + * @param testEntitiesPath + * @param testEventsPath + * @param resultsPath + * @return all test entities + * @throws URISyntaxException + */ + public static List<TestEntity> getEntities(String testEntitiesPath, String testEventsPath, String resultsPath) + throws URISyntaxException { + Path testEvents = Paths.get(ClassLoader.getSystemResource(testEntitiesPath + testEventsPath).toURI()); + + BiPredicate<Path, BasicFileAttributes> jsonMatcher = + (path, basicFileAttributes) -> path.toFile().getName().matches(".*\\.json"); + + List<TestEntity> entitiesList = new ArrayList<>(); + try (Stream<Path> paths = Files.find(testEvents, 2, jsonMatcher)) { + paths.forEach((path) -> entitiesList.add(new TestEntity(testEvents, path, testEventsPath, resultsPath))); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return entitiesList; + } + + /** + * @throws ValidationServiceException + * @throws JsonSyntaxException + * @throws URISyntaxException + * @throws IOException + */ + @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 void validateEntities(String inputEventsFolder, String testEventsPath, String resultsPath) + throws URISyntaxException, ValidationServiceException, IOException { + for (TestEntity entity : getEntities(inputEventsFolder, testEventsPath, resultsPath)) { + List<ValidationResult> results = validator.validate(entity.getJson()); + assertThat(results.size(), is(1)); + ValidationResult expectedResult = entity.getExpectedValidationResult(); + if (expectedResult == null) { + Path testEvents = Paths.get(ClassLoader.getSystemResource(inputEventsFolder + resultsPath).toURI()); + StringBuilder sb = new StringBuilder(); + Files.walk(testEvents).forEach((path) -> sb.append(path).append("\n")); + assertThat("Expected results missing (" + entity.expectedResultsFile + ")\n" + sb.toString(), + expectedResult, is(notNullValue())); + } + assertThat(entity.inputFile.getAbsolutePath(), results.get(0), + is(ValidationResultIsEqual.equalTo(expectedResult))); + } + } + +} diff --git a/src/test/java/org/onap/aai/validation/services/TestInfoService.java b/src/test/java/org/onap/aai/validation/services/TestInfoService.java new file mode 100644 index 0000000..0bfa8ba --- /dev/null +++ b/src/test/java/org/onap/aai/validation/services/TestInfoService.java @@ -0,0 +1,140 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.services; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; +import javax.inject.Inject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.aai.validation.controller.ValidationController; +import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.publisher.MockEventPublisher; +import org.onap.aai.validation.services.InfoService; +import org.onap.aai.validation.test.util.TestEntity; +import org.onap.aai.validation.test.util.TestUtil; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@TestPropertySource(properties = {"schemaIngestPropLoc = src/test/resources/oxm-reader/schemaIngest.properties"}) +@ContextConfiguration(locations = {"classpath:/info-service/test-validation-service-beans.xml"}) +public class TestInfoService { + + static { + System.setProperty("APP_HOME", "."); + } + + enum TestData { + // @formatter:off + VSERVER ("rule-driven-validator/test_events/vserver-create-event.json"); + + private String filename; + TestData(String filename) {this.filename = filename;} + public String getFilename() {return this.filename;} + // @formatter:on + } + + private InfoService infoService; + + @Inject + private ValidationController validationController; + + @Inject + MockEventPublisher messagePublisher; + + @Before + public void setUp() throws ValidationServiceException { + infoService = new InfoService(); + infoService.setValidationController(validationController); + } + + /** + * @throws ValidationServiceException + */ + @Test + public void testInitialisedInfoService() throws ValidationServiceException { + assertThat(infoService.getValidationController(), is(validationController)); + String info = infoService.getInfo(); + assertResultsStringFormatted(info); + } + + /** + * @throws ValidationServiceException + */ + @Test + public void testThrowableRecorded() throws ValidationServiceException { + validationController.recordThrowable(new Exception()); + String info = infoService.getInfo(); + assertResultsStringFormatted(info); + assertThat(info, containsString("Exception reported")); + } + + /** + * @throws ValidationServiceException + */ + @Test + public void testInvalidEventRecorded() throws ValidationServiceException { + validationController.execute("", "http"); + String info = infoService.getInfo(); + assertResultsStringFormatted(info); + assertThat(info, containsString("errored=1")); + } + + /** + * @throws ValidationServiceException + * @throws IOException + * @throws URISyntaxException + */ + @Test + public void testVserverEventRecorded() throws ValidationServiceException, URISyntaxException, IOException { + Path vserverTestFile = Paths.get(ClassLoader.getSystemResource(TestData.VSERVER.getFilename()).toURI()); + Path root = vserverTestFile.getParent(); + assertThat(root, is(not(nullValue()))); + TestEntity entity = new TestEntity(root, vserverTestFile, "test_events", "results/expected"); + messagePublisher.setTestEntity(entity); + messagePublisher.setTestDescription(entity.inputFile.getAbsolutePath()); + validationController.execute(TestUtil.getFileAsString(TestData.VSERVER.getFilename()), "http"); + String info = infoService.getInfo(); + assertResultsStringFormatted(info); + assertThat(info, containsString("total=1")); + } + + /** + * Assert that the info service status string contains the expected standard results and formatting. + * + * @param info + */ + private void assertResultsStringFormatted(String info) { + assertThat(info, startsWith("Status: Up\n")); + assertThat(info, containsString("Started at")); + assertThat(info, containsString("total=0")); + } + +} diff --git a/src/test/java/org/onap/aai/validation/services/TestValidateServiceImpl.java b/src/test/java/org/onap/aai/validation/services/TestValidateServiceImpl.java new file mode 100644 index 0000000..e23f7a2 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/services/TestValidateServiceImpl.java @@ -0,0 +1,115 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.services; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import java.net.URISyntaxException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; +import javax.security.auth.x500.X500Principal; +import javax.ws.rs.core.MultivaluedHashMap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.aai.auth.AAIMicroServiceAuth; +import org.onap.aai.validation.controller.ValidationController; +import org.onap.aai.validation.services.ValidateServiceImpl; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; + +public class TestValidateServiceImpl { + + static { + System.setProperty("APP_HOME", "."); + } + + private ValidationController mockValidationController; + private AAIMicroServiceAuth mockAaiMicroServiceAuth; + + @Before + public void setUp() { + mockValidationController = Mockito.mock(ValidationController.class); + mockAaiMicroServiceAuth = Mockito.mock(AAIMicroServiceAuth.class); + } + + @Test + public void validateConstructor() { + ValidateServiceImpl validateServiceImpl = + new ValidateServiceImpl(mockValidationController, mockAaiMicroServiceAuth); + assertNotNull(validateServiceImpl); + assertThat(validateServiceImpl.toString(), is(notNullValue())); + } + + @Test + public void testValidateEventWithoutHeaderFailure() { + ValidateServiceImpl validateServiceImpl = + new ValidateServiceImpl(mockValidationController, mockAaiMicroServiceAuth); + ResponseEntity<String> response = validateServiceImpl.validate("testEvent"); + assertThat(response.getStatusCode(), is(HttpStatus.INTERNAL_SERVER_ERROR)); + } + + /** + * Create a (mocked) HTTPS request and invoke the Babel generate artifacts API + * + * @param request for the Babel Service + * @return the Response from the HTTP API + * @throws URISyntaxException + */ + @Test + public void testRequestWithHeaders() throws URISyntaxException { + // Create mocked request headers map + MultivaluedHashMap<String, String> headersMap = new MultivaluedHashMap<>(); + headersMap.put("X-TransactionId", createSingletonList("transaction-id")); + headersMap.put("X-FromAppId", createSingletonList("app-id")); + headersMap.put("Host", createSingletonList("hostname")); + + HttpHeaders headers = Mockito.mock(HttpHeaders.class); + for (Entry<String, List<String>> entry : headersMap.entrySet()) { + Mockito.when(headers.get(entry.getKey())).thenReturn(entry.getValue()); + } + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + servletRequest.setSecure(true); + servletRequest.setScheme("https"); + servletRequest.setServerPort(9501); + servletRequest.setServerName("localhost"); + servletRequest.setRequestURI("/services/validation-service/v1/app/validate"); + + X509Certificate mockCertificate = Mockito.mock(X509Certificate.class); + Mockito.when(mockCertificate.getSubjectX500Principal()) + .thenReturn(new X500Principal("CN=test, OU=qa, O=Test Ltd, L=London, ST=London, C=GB")); + + servletRequest.setAttribute("javax.servlet.request.X509Certificate", new X509Certificate[] {mockCertificate}); + servletRequest.setAttribute("javax.servlet.request.cipher_suite", ""); + + ValidateServiceImpl service = new ValidateServiceImpl(mockValidationController, mockAaiMicroServiceAuth); + service.validate(headers, servletRequest, "testEvent"); + } + + private List<String> createSingletonList(String listItem) { + return Collections.<String>singletonList(listItem); + } +} diff --git a/src/test/java/org/onap/aai/validation/test/util/RandomString.java b/src/test/java/org/onap/aai/validation/test/util/RandomString.java new file mode 100644 index 0000000..ba2d85e --- /dev/null +++ b/src/test/java/org/onap/aai/validation/test/util/RandomString.java @@ -0,0 +1,40 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.test.util; + +import java.util.Random; + +public class RandomString { + + private static final String VALID_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final int MAX_STRING_LENGTH = 50; + private static Random rng = new Random(); + + public static String generate() { + return generateString(rng, VALID_CHARS, rng.nextInt(MAX_STRING_LENGTH) + 1); + } + + public static String generateString(Random rng, String characters, int length) { + char[] text = new char[length]; + for (int i = 0; i < length; i++) { + text[i] = characters.charAt(rng.nextInt(characters.length())); + } + return new String(text); + } + +} diff --git a/src/test/java/org/onap/aai/validation/test/util/TestEntity.java b/src/test/java/org/onap/aai/validation/test/util/TestEntity.java new file mode 100644 index 0000000..e42873a --- /dev/null +++ b/src/test/java/org/onap/aai/validation/test/util/TestEntity.java @@ -0,0 +1,88 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.test.util; + +import com.google.gson.JsonSyntaxException; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import org.onap.aai.validation.result.ValidationResult; + +public class TestEntity { + + public File inputFile; + public String expectedResultsFile; + + public TestEntity(Path root, Path inputFilePath, String inputEventsPath, String outputEventsPath) { + String rootUri = root.toUri().toString(); + String resultsRoot = rootUri.replaceAll(inputEventsPath + "/$", outputEventsPath + "/"); + String inputFileUri = inputFilePath.toUri().toString(); + this.inputFile = inputFilePath.toFile(); + this.expectedResultsFile = inputFileUri.replace(rootUri, resultsRoot).replaceAll("\\.json$", ".exp.json"); + } + + public String getJson() throws URISyntaxException, IOException { + return TestUtil.getFileAsString(inputFile.getPath()); + } + + /** + * @return the contents of the file that stores the expected JSON, or an empty string if there is no expected JSON + * @throws URISyntaxException + * @throws IOException + */ + public String getExpectedJson() throws URISyntaxException, IOException { + try { + return TestUtil.getFileAsString(new URI(expectedResultsFile).getPath()); + } catch (NoSuchFileException e) { + return ""; + } + } + + public ValidationResult getExpectedValidationResult() throws JsonSyntaxException, URISyntaxException, IOException { + return ValidationResult.fromJson(getExpectedJson()); + } + + @Override + public String toString() { + return "TestEntity [inputFile=" + inputFile + ", expectedResultsFile=" + expectedResultsFile + "]"; + } + + public boolean expectsError() throws URISyntaxException, IOException { + try { + getErrorFileContents(); + } catch (NoSuchFileException e) { + return false; + } + return true; + } + + public String getExpectedErrorMessage() throws URISyntaxException, IOException { + return getErrorFileContents().trim(); + } + + private String getErrorFileContents() throws URISyntaxException, IOException { + return TestUtil.getFileAsString(new URI(getErrorFileURI()).getPath()); + } + + private String getErrorFileURI() { + return expectedResultsFile.replaceAll("\\.exp\\.json$", ".error"); + } +} diff --git a/src/test/java/org/onap/aai/validation/test/util/TestUtil.java b/src/test/java/org/onap/aai/validation/test/util/TestUtil.java new file mode 100644 index 0000000..39d1246 --- /dev/null +++ b/src/test/java/org/onap/aai/validation/test/util/TestUtil.java @@ -0,0 +1,52 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.test.util; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +/** + * Test helper methods. + */ +public class TestUtil { + + /** + * Gets files, such as test data from the classpath. + * + * @param filename the name of the file + * @return a String with the file contents. + * @throws URISyntaxException + * @throws IOException + */ + public static String getFileAsString(String filename) throws URISyntaxException, IOException { + // Try loading the named file directly + URI uri = new File(filename).toURI(); + URL systemResource = ClassLoader.getSystemResource(filename); + if (systemResource != null) { + uri = systemResource.toURI(); + } + byte[] encoded = Files.readAllBytes(Paths.get(uri)); + return new String(encoded, StandardCharsets.UTF_8); + } +} diff --git a/src/test/java/org/onap/aai/validation/test/util/ValidationResultIsEqual.java b/src/test/java/org/onap/aai/validation/test/util/ValidationResultIsEqual.java new file mode 100644 index 0000000..aa6471f --- /dev/null +++ b/src/test/java/org/onap/aai/validation/test/util/ValidationResultIsEqual.java @@ -0,0 +1,58 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.test.util; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.onap.aai.validation.result.ValidationResult; + +/** + * Matcher for comparing actual and expected ValidationResults + * + */ +public class ValidationResultIsEqual extends BaseMatcher<ValidationResult> { + private final ValidationResult expected; + + public static Matcher<? super ValidationResult> equalTo(ValidationResult validationResult) { + return new ValidationResultIsEqual(validationResult); + } + + private ValidationResultIsEqual(ValidationResult expected) { + this.expected = expected; + } + + @Override + public boolean matches(Object o) { + if (expected == null) { + return false; + } + ValidationResult actual = (ValidationResult) o; + return actual.getEntityId().equals(expected.getEntityId()) && // + actual.getEntityType().equals(expected.getEntityType()) && // + (actual.getEntityLink() == null ? "" : actual.getEntityLink()).equals(expected.getEntityLink()) && // + actual.getResourceVersion().equals(expected.getResourceVersion()) && // + actual.getViolations().equals(expected.getViolations()); + } + + @Override + public void describeTo(Description description) { + description.appendText(expected == null ? "<not defined>" : expected.toString()); + } + +} diff --git a/src/test/java/org/onap/aai/validation/util/TestStringUtils.java b/src/test/java/org/onap/aai/validation/util/TestStringUtils.java new file mode 100644 index 0000000..038e10d --- /dev/null +++ b/src/test/java/org/onap/aai/validation/util/TestStringUtils.java @@ -0,0 +1,170 @@ +/* + * ============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===================================================== + */ +package org.onap.aai.validation.util; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.onap.aai.validation.exception.ValidationServiceException; +import org.onap.aai.validation.util.StringUtils; + +public class TestStringUtils { + + static { + System.setProperty("APP_HOME", "."); + } + + @Test + public void testStripSinglePrefix() throws Exception { + String prefixDelimiter = "."; + String prefix = "prefix"; + String suffix = "suffix"; + String testString = prefix + prefixDelimiter + suffix; + + String result = StringUtils.stripPrefix(testString, prefixDelimiter); + + assertEquals("Prefix incorrectly stripped.", suffix, result); + } + + @Test + public void testStripMultiplePrefix() throws Exception { + String prefixDelimiter = "***"; + String prefix = "prefix"; + String suffix = "suffix"; + String testString = prefix + prefixDelimiter + prefix + prefixDelimiter + suffix; + + String result = StringUtils.stripPrefix(testString, prefixDelimiter); + + assertEquals("Prefix incorrectly stripped.", suffix, result); + } + + @Test + public void testStripSubstr() { + List<String> stringList = Arrays.asList("/text()one", "tw/text()o", "three/text()"); + List<String> stripSubstr = StringUtils.stripSuffix(stringList, "/text()"); + assertThat(stripSubstr, containsInAnyOrder("/text()one", "tw/text()o", "three")); + } + + @Test + public void testStripStringRegex() throws Exception { + String prefixDelimiter = "/aai/v8/"; + String prefix = "prefix"; + String suffix = "suffix"; + String testString = prefix + prefixDelimiter + suffix; + String regex = "\\/aai\\/v[0-9]*\\/"; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, is(suffix)); + } + + @Test + public void testStripStringRegexNotFound() throws Exception { + String prefixDelimiter = "delimiter"; + String prefix = "prefix"; + String suffix = "suffix"; + String testString = prefix + prefixDelimiter + suffix; + String regex = "\\/aai\\/v[0-9]*\\/"; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, is(testString)); + } + + @Test + public void testStripStringRegexMultiplePrefix() throws Exception { + String prefixDelimiter = "/aai/v8/"; + String prefix = "prefix"; + String suffix = "text" + prefixDelimiter + "text"; + String testString = prefix + prefixDelimiter + suffix; + String regex = "\\/aai\\/v[0-9]*\\/"; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, is(suffix)); + } + + @Test + public void testStripStringRegexNullString() throws Exception { + String testString = null; + String regex = "\\/aai\\/v[0-9]*\\/"; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, nullValue()); + } + + @Test + public void testStripStringRegexEmptyString() throws Exception { + String testString = ""; + String regex = "\\/aai\\/v[0-9]*\\/"; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, is(testString)); + } + + @Test + public void testStripStringRegexNullRegex() throws Exception { + String testString = "test"; + String regex = null; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, is(testString)); + } + + @Test + public void testStripStringRegexEmptyRegex() throws Exception { + String testString = "test"; + String regex = ""; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, is(testString)); + } + + @Test(expected = ValidationServiceException.class) + public void testStripStringRegexInvalidRegex() throws Exception { + String prefixDelimiter = "/aai/v8/"; + String prefix = "prefix"; + String suffix = "suffix"; + String testString = prefix + prefixDelimiter + suffix; + String regex = "***"; + + StringUtils.stripPrefixRegex(testString, regex); + } + + @Test + public void testStripStringRegexLimitedPrefix() throws Exception { + String prefixDelimiter = "/aai/v8/"; + String suffix = "suffix"; + String testString = prefixDelimiter + suffix; + String regex = "\\/aai\\/v[0-9]*\\/"; + + String stripString = StringUtils.stripPrefixRegex(testString, regex); + + assertThat(stripString, is(suffix)); + } +} |