diff options
-rw-r--r-- | aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java | 3 | ||||
-rw-r--r-- | aai-core/src/main/java/org/onap/aai/rest/notification/NotificationService.java | 18 | ||||
-rw-r--r-- | aai-core/src/main/java/org/onap/aai/web/KafkaConfig.java | 3 | ||||
-rw-r--r-- | aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryNotificationIntegrationTest.java | 212 | ||||
-rw-r--r-- | aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java | 91 | ||||
-rw-r--r-- | aai-core/src/test/java/org/onap/aai/rest/notification/NotificationServiceTest.java | 128 | ||||
-rw-r--r-- | aai-core/src/test/java/org/onap/aai/rest/notification/UEBNotificationTest.java (renamed from aai-core/src/test/java/org/onap/aai/rest/ueb/UEBNotificationTest.java) | 3 |
7 files changed, 375 insertions, 83 deletions
diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java index 7030cf7d..c1a4f2a7 100644 --- a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java +++ b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationConfiguration.java @@ -26,10 +26,9 @@ import org.onap.aai.restclient.RestClient; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -@Profile("pre-validation") @Configuration +@ConditionalOnProperty(name = "aai.notification.validation.enabled", havingValue = "true") public class ValidationConfiguration { @Bean(name = "validationRestClient") diff --git a/aai-core/src/main/java/org/onap/aai/rest/notification/NotificationService.java b/aai-core/src/main/java/org/onap/aai/rest/notification/NotificationService.java index d6a3f897..9c3dde15 100644 --- a/aai-core/src/main/java/org/onap/aai/rest/notification/NotificationService.java +++ b/aai-core/src/main/java/org/onap/aai/rest/notification/NotificationService.java @@ -35,7 +35,6 @@ import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.prevalidation.ValidationService; -import org.onap.aai.rest.db.HttpEntry; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.engines.query.QueryEngine; import org.onap.aai.setup.SchemaVersion; @@ -43,8 +42,8 @@ import org.onap.aai.util.AAIConfig; import org.onap.aai.util.delta.DeltaEvents; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; @Service @@ -52,28 +51,23 @@ public class NotificationService { public static final Logger LOGGER = LoggerFactory.getLogger(NotificationService.class); + private final ValidationService validationService; private final LoaderFactory loaderFactory; private final boolean isDeltaEventsEnabled; private final String basePath; public NotificationService( + @Nullable ValidationService validationService, LoaderFactory loaderFactory, @Value("${schema.uri.base.path}") String basePath, @Value("${delta.events.enabled:false}") boolean isDeltaEventsEnabled) { + this.validationService = validationService; this.loaderFactory = loaderFactory; this.basePath = basePath; this.isDeltaEventsEnabled = isDeltaEventsEnabled; } /** - * Inject the validation service if the profile pre-valiation is enabled, - * Otherwise this variable will be set to null and thats why required=false - * so that it can continue even if pre validation isn't enabled - */ - @Autowired(required = false) - private ValidationService validationService; - - /** * Generate notification events for the resulting db requests. */ public void generateEvents(UEBNotification notification, int notificationDepth, String sourceOfTruth, DBSerializer serializer, @@ -100,9 +94,7 @@ public class NotificationService { LOGGER.warn("Encountered exception generating events", e); } - // Since @Autowired required is set to false, we need to do a null check - // for the existence of the validationService since its only enabled if profile - // is enabled + // validation is configurable via aai.notification.validation.enabled if (validationService != null) { validationService.validate(notification.getEvents()); } diff --git a/aai-core/src/main/java/org/onap/aai/web/KafkaConfig.java b/aai-core/src/main/java/org/onap/aai/web/KafkaConfig.java index 05e4768d..c1e8357d 100644 --- a/aai-core/src/main/java/org/onap/aai/web/KafkaConfig.java +++ b/aai-core/src/main/java/org/onap/aai/web/KafkaConfig.java @@ -176,9 +176,10 @@ public class KafkaConfig { } @Bean + @ConditionalOnMissingBean public NotificationService notificationService(LoaderFactory loaderFactory, @Value("${schema.uri.base.path}") String basePath, @Value("${delta.events.enabled:false}") boolean isDeltaEventsEnabled) { - return new NotificationService(loaderFactory, basePath, isDeltaEventsEnabled); + return new NotificationService(null, loaderFactory, basePath, isDeltaEventsEnabled); } } diff --git a/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryNotificationIntegrationTest.java b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryNotificationIntegrationTest.java new file mode 100644 index 00000000..e8e3d691 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryNotificationIntegrationTest.java @@ -0,0 +1,212 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom. All rights reserved. + * ================================================================================ + * 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.rest.db; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.javatuples.Pair; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.aai.AAISetup; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.query.builder.QueryOptions; +import org.onap.aai.rest.notification.UEBNotification; +import org.onap.aai.restcore.HttpMethod; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.springframework.test.annotation.DirtiesContext; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +public class HttpEntryNotificationIntegrationTest extends AAISetup { + + private static final MediaType APPLICATION_JSON = MediaType.valueOf("application/json"); + private Loader loader; + private TransactionalGraphEngine dbEngine; + private GraphTraversalSource traversal; + private HttpHeaders httpHeaders; + private UriInfo uriInfo; + private MultivaluedMap<String, String> headersMultiMap; + private MultivaluedMap<String, String> queryParameters; + private List<String> aaiRequestContextList; + private List<MediaType> outputMediaTypes; + + ObjectMapper mapper = new ObjectMapper(); + + @Before + public void setup() { + + httpHeaders = Mockito.mock(HttpHeaders.class); + uriInfo = Mockito.mock(UriInfo.class); + + headersMultiMap = new MultivaluedHashMap<>(); + queryParameters = Mockito.spy(new MultivaluedHashMap<>()); + + headersMultiMap.add("X-FromAppId", "JUNIT"); + headersMultiMap.add("X-TransactionId", UUID.randomUUID().toString()); + headersMultiMap.add("Real-Time", "true"); + headersMultiMap.add("Accept", "application/json"); + headersMultiMap.add("aai-request-context", ""); + + outputMediaTypes = new ArrayList<>(); + outputMediaTypes.add(APPLICATION_JSON); + + aaiRequestContextList = new ArrayList<>(); + aaiRequestContextList.add(""); + + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); + loader = traversalHttpEntry.getLoader(); + dbEngine = traversalHttpEntry.getDbEngine(); + traversal = dbEngine.tx().traversal(); + + when(httpHeaders.getAcceptableMediaTypes()).thenReturn(outputMediaTypes); + when(httpHeaders.getRequestHeaders()).thenReturn(headersMultiMap); + + when(httpHeaders.getRequestHeader("aai-request-context")).thenReturn(aaiRequestContextList); + + when(uriInfo.getQueryParameters()).thenReturn(queryParameters); + when(uriInfo.getQueryParameters(false)).thenReturn(queryParameters); + + // TODO - Check if this is valid since RemoveDME2QueryParameters seems to be + // very unreasonable + Mockito.doReturn(null).when(queryParameters).remove(any()); + + when(httpHeaders.getMediaType()).thenReturn(APPLICATION_JSON); + } + + @After + public void rollback() { + dbEngine.rollback(); + } + + @Test + public void notificationOnRelatedToTest() throws UnsupportedEncodingException, AAIException { + + Loader ld = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); + UEBNotification uebNotification = Mockito.spy(new UEBNotification(ld, loaderFactory, schemaVersions)); + traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), uebNotification); + + Loader loader = traversalHttpEntry.getLoader(); + TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); + // Put pserver + String uri = "/cloud-infrastructure/pservers/pserver/junit-edge-test-pserver"; + String content = "{\"hostname\":\"junit-edge-test-pserver\"}"; + doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, content); + // Put complex + uri = "/cloud-infrastructure/complexes/complex/junit-edge-test-complex"; + content = "{\"physical-location-id\":\"junit-edge-test-complex\",\"physical-location-type\":\"AAIDefault\",\"street1\":\"AAIDefault\",\"city\":\"AAIDefault\",\"state\":\"NJ\",\"postal-code\":\"07748\",\"country\":\"USA\",\"region\":\"US\"}"; + doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, content); + + // PutEdge + uri = "/cloud-infrastructure/complexes/complex/junit-edge-test-complex/relationship-list/relationship"; + content = "{\"related-to\":\"pserver\",\"related-link\":\"/aai/" + schemaVersions.getDefaultVersion().toString() + + "/cloud-infrastructure/pservers/pserver/junit-edge-test-pserver\",\"relationship-label\":\"org.onap.relationships.inventory.LocatedIn\"}"; + + doNothing().when(uebNotification).triggerEvents(); + Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT_EDGE, uri, + content); + + assertEquals("Expected the pserver relationship to be deleted", 200, response.getStatus()); + assertEquals("Two notifications", 2, uebNotification.getEvents().size()); + assertEquals("Notification generated for PUT edge", "UPDATE", + uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString()); + assertThat("Event body for the edge create has the related to", + uebNotification.getEvents().get(0).getObj().marshal(false), + containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver")); + + response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.DELETE_EDGE, uri, content); + assertEquals("Expected the pserver relationship to be deleted", 204, response.getStatus()); + assertEquals("Two notifications", 2, uebNotification.getEvents().size()); + assertEquals("Notification generated for DELETE edge", "UPDATE", + uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString()); + assertThat("Event body for the edge delete does not have the related to", + uebNotification.getEvents().get(0).getObj().marshal(false), + not(containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver"))); + dbEngine.rollback(); + + } + + private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method, + String uri, String requestBody) throws UnsupportedEncodingException, AAIException { + return doRequest(httpEntry, loader, dbEngine, method, uri, requestBody, null); + } + + private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method, + String uri, String requestBody, QueryOptions queryOptions) throws UnsupportedEncodingException, AAIException { + URI uriObject = UriBuilder.fromPath(uri).build(); + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); + String objType; + if (!uriQuery.getContainerType().equals("")) { + objType = uriQuery.getContainerType(); + } else { + objType = uriQuery.getResultType(); + } + if (uri.endsWith("relationship")) { + objType = "relationship"; + } + Introspector obj; + if (method.equals(HttpMethod.GET) || method.equals(HttpMethod.GET_RELATIONSHIP)) { + obj = loader.introspectorFromName(objType); + } else { + obj = loader.unmarshal(objType, requestBody, org.onap.aai.restcore.MediaType.getEnum("application/json")); + } + + DBRequest.Builder builder = new DBRequest.Builder(method, uriObject, uriQuery, obj, httpHeaders, uriInfo, + "JUNIT-TRANSACTION"); + DBRequest dbRequest = requestBody != null + ? builder.rawRequestContent(requestBody).build() + : builder.build(); + + List<DBRequest> dbRequestList = Collections.singletonList(dbRequest); + + Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(dbRequestList, "JUNIT", + Collections.emptySet(), true, queryOptions); + return responsesTuple.getValue1().get(0).getValue1(); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java index ccc2c74c..5ecffbc0 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java @@ -31,8 +31,10 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; - import static org.mockito.Mockito.doNothing; - import static org.mockito.Mockito.times; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -95,6 +97,7 @@ import org.onap.aai.rest.db.responses.Relationship; import org.onap.aai.rest.db.responses.RelationshipWrapper; import org.onap.aai.rest.db.responses.ServiceException; +import org.onap.aai.rest.notification.NotificationService; import org.onap.aai.rest.notification.UEBNotification; import org.onap.aai.restcore.HttpMethod; import org.onap.aai.serialization.engines.QueryStyle; @@ -110,6 +113,7 @@ import org.onap.aai.restcore.HttpMethod; public class HttpEntryTest extends AAISetup { @MockBean ValidationService validationService; + @MockBean NotificationService notificationService; protected static final MediaType APPLICATION_JSON = MediaType.valueOf("application/json"); @@ -213,7 +217,7 @@ import org.onap.aai.restcore.HttpMethod; JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE); assertEquals("Expected the pserver to be returned", 200, response.getStatus()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -249,7 +253,7 @@ import org.onap.aai.restcore.HttpMethod; JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE); assertEquals("Expected the pservers to be returned", 200, response.getStatus()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -283,7 +287,7 @@ import org.onap.aai.restcore.HttpMethod; assertNull(response.getHeaderString("total-results")); assertEquals(1, actualResponseBody.getJSONArray("pserver").length()); assertEquals("Expected the pservers to be returned", 200, response.getStatus()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); queryOptions = QueryOptions.builder().pageable(new Pageable(0,5).includeTotalCount()).build(); response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions); @@ -307,6 +311,7 @@ import org.onap.aai.restcore.HttpMethod; assertTrue( response.getEntity().toString().contains("Node Not Found:No Node of type pserver found at: /cloud-infrastructure/pservers")); assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatus()); + verify(notificationService, never()).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @@ -344,7 +349,7 @@ import org.onap.aai.restcore.HttpMethod; assertEquals(2, Integer.parseInt(totalPages)); assertEquals(1, actualResponseBody.getJSONArray("pserver").length()); assertEquals("Expected the pservers to be returned", 200, response.getStatus()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); queryOptions = QueryOptions.builder().pageable(new Pageable(0, 2)).build(); response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, queryOptions); @@ -392,7 +397,6 @@ import org.onap.aai.restcore.HttpMethod; actualResponseBody = new JSONObject(response.getEntity().toString()); assertEquals("theEquipType2", actualResponseBody.getJSONArray("pserver").getJSONObject(0).getString("equip-type")); assertEquals("theEquipType", actualResponseBody.getJSONArray("pserver").getJSONObject(1).getString("equip-type")); - } @Test @@ -401,6 +405,7 @@ import org.onap.aai.restcore.HttpMethod; Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri); assertEquals("The pserver is not found", 404, response.getStatus()); + verify(notificationService, never()).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -410,7 +415,7 @@ import org.onap.aai.restcore.HttpMethod; Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody); assertEquals("Expecting the pserver to be created", 201, response.getStatus()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -428,6 +433,7 @@ import org.onap.aai.restcore.HttpMethod; assertEquals( "Resource version specified on create:resource-version passed for create of /cloud-infrastructure/pservers/pserver/theHostname", errorResponseEntity.getRequestError().getServiceException().getVariables().get(2)); + verify(notificationService, never()).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -449,7 +455,7 @@ import org.onap.aai.restcore.HttpMethod; assertEquals("Expecting the pserver to be updated", 200, response.getStatus()); assertTrue("That old properties are removed", traversal.V().has("hostname", "updatedHostname").hasNot("number-of-cpus").hasNext()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -473,6 +479,7 @@ import org.onap.aai.restcore.HttpMethod; assertEquals( "Precondition Failed:resource-version MISMATCH for update of /cloud-infrastructure/pservers/pserver/updatedHostname", errorResponseEntity.getRequestError().getServiceException().getVariables().get(2)); + verify(notificationService, never()).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -518,7 +525,7 @@ import org.onap.aai.restcore.HttpMethod; traversal.V().has("aai-node-type", "p-interface").has("aai-uri", uri).has("interface-name", "p1") .out("tosca.relationships.network.BindsTo").has("aai-node-type", "pserver") .has("hostname", "hostname").hasNext()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -538,7 +545,7 @@ import org.onap.aai.restcore.HttpMethod; assertTrue("object should be updated while keeping old properties", traversal.V().has("aai-node-type", "pserver").has("hostname", "new-hostname") .has("equip-type", "the-equip-type").hasNext()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -555,7 +562,7 @@ import org.onap.aai.restcore.HttpMethod; doDelete(resourceVersion, uri, "pserver").getStatus()); assertTrue("Expecting the pserver to be deleted", !traversal.V().has("aai-node-type", "pserver").has("hostname", "the-hostname").hasNext()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -605,7 +612,7 @@ import org.onap.aai.restcore.HttpMethod; .has(EdgeProperty.PREVENT_DELETE.toString(), "IN"); assertTrue("p-server has incoming edge from complex", vertexQuery.hasNext()); assertTrue("Created Edge has expected properties", edgeQuery.hasNext()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -724,7 +731,7 @@ import org.onap.aai.restcore.HttpMethod; assertEquals("Expected get to succeed", 200, response.getStatus()); assertThat(responseEntity, containsString("/cloud-infrastructure/pservers/pserver/pserver-1")); assertThat(responseEntity, containsString("/cloud-infrastructure/pservers/pserver/pserver-2")); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -759,7 +766,7 @@ import org.onap.aai.restcore.HttpMethod; assertEquals("Expected the response to be successful", 200, response.getStatus()); assertThat("Related pserver is returned", response.getEntity().toString(), containsString("\"hostname\":\"related-to-pserver\"")); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @@ -788,7 +795,7 @@ import org.onap.aai.restcore.HttpMethod; Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri); assertThat("Related to pserver is returned.", response.getEntity().toString(), containsString("\"hostname\":\"abstract-pserver\"")); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -833,7 +840,7 @@ import org.onap.aai.restcore.HttpMethod; relationships[0].getRelatedLink()); assertEquals("complex.physical-location-id", relationships[0].getRelationshipData()[0].getRelationshipKey()); assertEquals("related-to-complex", relationships[0].getRelationshipData()[0].getRelationshipValue()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } @Test @@ -891,53 +898,7 @@ import org.onap.aai.restcore.HttpMethod; JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE); queryParameters.remove("format"); - verify(validationService, times(1)).validate(any()); - } - - @Test - public void notificationOnRelatedToTest() throws UnsupportedEncodingException, AAIException { - - Loader ld = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); - UEBNotification uebNotification = Mockito.spy(new UEBNotification(ld, loaderFactory, schemaVersions)); - traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), uebNotification); - - Loader loader = traversalHttpEntry.getLoader(); - TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine(); - // Put pserver - String uri = "/cloud-infrastructure/pservers/pserver/junit-edge-test-pserver"; - String content = "{\"hostname\":\"junit-edge-test-pserver\"}"; - doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, content); - // Put complex - uri = "/cloud-infrastructure/complexes/complex/junit-edge-test-complex"; - content = "{\"physical-location-id\":\"junit-edge-test-complex\",\"physical-location-type\":\"AAIDefault\",\"street1\":\"AAIDefault\",\"city\":\"AAIDefault\",\"state\":\"NJ\",\"postal-code\":\"07748\",\"country\":\"USA\",\"region\":\"US\"}"; - doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, content); - - // PutEdge - uri = "/cloud-infrastructure/complexes/complex/junit-edge-test-complex/relationship-list/relationship"; - content = "{\"related-to\":\"pserver\",\"related-link\":\"/aai/" + schemaVersions.getDefaultVersion().toString() - + "/cloud-infrastructure/pservers/pserver/junit-edge-test-pserver\",\"relationship-label\":\"org.onap.relationships.inventory.LocatedIn\"}"; - - doNothing().when(uebNotification).triggerEvents(); - Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT_EDGE, uri, content); - - assertEquals("Expected the pserver relationship to be deleted", 200, response.getStatus()); - assertEquals("Two notifications", 2, uebNotification.getEvents().size()); - assertEquals("Notification generated for PUT edge", "UPDATE", - uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString()); - assertThat("Event body for the edge create has the related to", - uebNotification.getEvents().get(0).getObj().marshal(false), - containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver")); - - response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.DELETE_EDGE, uri, content); - assertEquals("Expected the pserver relationship to be deleted", 204, response.getStatus()); - assertEquals("Two notifications", 2, uebNotification.getEvents().size()); - assertEquals("Notification generated for DELETE edge", "UPDATE", - uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString()); - assertThat("Event body for the edge delete does not have the related to", - uebNotification.getEvents().get(0).getObj().marshal(false), - not(containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver"))); - dbEngine.rollback(); - + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method, @@ -1035,6 +996,6 @@ import org.onap.aai.restcore.HttpMethod; JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE); assertEquals("Expected the pserver to be returned", 200, response.getStatus()); - verify(validationService, times(1)).validate(any()); + verify(notificationService, times(1)).generateEvents(any(), anyInt(), any(), any(), any(), any(), any(), any()); } } diff --git a/aai-core/src/test/java/org/onap/aai/rest/notification/NotificationServiceTest.java b/aai-core/src/test/java/org/onap/aai/rest/notification/NotificationServiceTest.java new file mode 100644 index 00000000..b3556bbe --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/rest/notification/NotificationServiceTest.java @@ -0,0 +1,128 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom. All rights reserved. + * ================================================================================ + * 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.rest.notification; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.core.Response.Status; + +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.aai.AAISetup; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.LoaderFactory; +import org.onap.aai.prevalidation.ValidationService; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.engines.query.QueryEngine; +import org.onap.aai.setup.SchemaVersion; +import org.onap.aai.setup.SchemaVersions; + +public class NotificationServiceTest extends AAISetup { + + @Mock LoaderFactory loaderFactory; + @Mock SchemaVersions schemaVersions; + @Mock UEBNotification uebNotification; + @Mock ValidationService validationService; + @Mock DBSerializer dbSerializer; + @Mock QueryEngine queryEngine; + @Mock Introspector introspector; + + boolean isDeltaEventsEnabled = false; + String basePath = "/aai"; + NotificationService notificationService; + + @Before + public void setup() throws UnsupportedEncodingException, AAIException { + MockitoAnnotations.openMocks(this); + + when(dbSerializer.touchStandardVertexPropertiesForEdges()).thenReturn(Collections.emptySet()); + when(dbSerializer.getLatestVersionView(any(),anyInt())).thenReturn(introspector); + + notificationService = new NotificationService(validationService, loaderFactory, basePath, isDeltaEventsEnabled); + when(schemaVersions.getDefaultVersion()).thenReturn(new SchemaVersion("v29")); + doNothing().when(uebNotification).createNotificationEvent(any(),any(),any(),any(),any(),any(),any()); + } + + @Test + public void thatNotificationsCanBeCreatedWithoutEdges() throws AAIException, UnsupportedEncodingException { + + Map<String, Object> properties = new HashMap<>(); + properties.put(AAIProperties.NODE_TYPE, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "pserver", new HashMap<>()))); + properties.put(AAIProperties.AAI_URI, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "/pservers/pserver/hostname", new HashMap<>()))); + properties.put(AAIProperties.CREATED_TS, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "12", new HashMap<>()))); + properties.put(AAIProperties.LAST_MOD_TS, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "34", new HashMap<>()))); + + Vertex vertex = new DetachedVertex("1","label", properties); + Set<Vertex> mainVertexesToNotifyOn = new HashSet<>(); + mainVertexesToNotifyOn.add(vertex); + SchemaVersion schemaVersion = new SchemaVersion("v29"); + when(dbSerializer.getUpdatedVertexes()).thenReturn(Collections.emptyMap()); + + notificationService.generateEvents(uebNotification, AAIProperties.MINIMUM_DEPTH, "sourceOfTruth", dbSerializer, "transactionId", queryEngine, mainVertexesToNotifyOn, schemaVersion); + + verify(uebNotification, times(1)).createNotificationEvent(eq("transactionId"), eq("sourceOfTruth"), eq(Status.OK), eq(URI.create("/aai/v29/pservers/pserver/hostname")), eq(introspector), any(), eq("/aai")); + verify(validationService, times(1)).validate(anyList()); + verify(uebNotification, times(1)).triggerEvents(); + } + + @Test + public void thatValidationCanBeDisabled() throws AAIException, UnsupportedEncodingException { + + Map<String, Object> properties = new HashMap<>(); + properties.put(AAIProperties.NODE_TYPE, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "pserver", new HashMap<>()))); + properties.put(AAIProperties.AAI_URI, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "/pservers/pserver/hostname", new HashMap<>()))); + properties.put(AAIProperties.CREATED_TS, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "12", new HashMap<>()))); + properties.put(AAIProperties.LAST_MOD_TS, Collections.singletonList(new DetachedVertexProperty<String>("1", null, "34", new HashMap<>()))); + + Vertex vertex = new DetachedVertex("1","label", properties); + Set<Vertex> mainVertexesToNotifyOn = new HashSet<>(); + mainVertexesToNotifyOn.add(vertex); + SchemaVersion schemaVersion = new SchemaVersion("v29"); + when(dbSerializer.getUpdatedVertexes()).thenReturn(Collections.emptyMap()); + + notificationService = new NotificationService(null, loaderFactory, basePath, isDeltaEventsEnabled); + notificationService.generateEvents(uebNotification, AAIProperties.MINIMUM_DEPTH, "sourceOfTruth", dbSerializer, "transactionId", queryEngine, mainVertexesToNotifyOn, schemaVersion); + + verify(uebNotification, times(1)).triggerEvents(); + } +} diff --git a/aai-core/src/test/java/org/onap/aai/rest/ueb/UEBNotificationTest.java b/aai-core/src/test/java/org/onap/aai/rest/notification/UEBNotificationTest.java index 57422587..229abae4 100644 --- a/aai-core/src/test/java/org/onap/aai/rest/ueb/UEBNotificationTest.java +++ b/aai-core/src/test/java/org/onap/aai/rest/notification/UEBNotificationTest.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.aai.rest.ueb; +package org.onap.aai.rest.notification; import static org.junit.Assert.assertEquals; @@ -38,7 +38,6 @@ import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.ModelType; -import org.onap.aai.rest.notification.UEBNotification; import org.onap.aai.serialization.db.EdgeSerializer; import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.setup.SchemaVersion; |