Merge "Release 1.14.0 maven artifact"
[aai/aai-common.git] / aai-core / src / test / java / org / onap / aai / rest / db / HttpEntryTest.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright © 2023 Deutsche Telekom.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *    http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.aai.rest.db;
24
25 import static org.onap.aai.edges.enums.AAIDirection.NONE;
26 import static org.hamcrest.Matchers.containsString;
27 import static org.hamcrest.Matchers.not;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertFalse;
30 import static org.junit.Assert.assertThat;
31 import static org.junit.Assert.assertTrue;
32 import static org.mockito.ArgumentMatchers.any;
33 import static org.mockito.Mockito.doNothing;
34 import static org.mockito.Mockito.times;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
37
38 import com.fasterxml.jackson.core.JsonProcessingException;
39 import com.fasterxml.jackson.databind.JsonMappingException;
40 import com.fasterxml.jackson.databind.ObjectMapper;
41 import com.google.gson.JsonObject;
42 import com.google.gson.JsonParser;
43
44 import java.io.UnsupportedEncodingException;
45 import java.net.URI;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.Collection;
49 import java.util.HashSet;
50 import java.util.List;
51 import java.util.Set;
52 import java.util.UUID;
53
54 import javax.ws.rs.core.HttpHeaders;
55 import javax.ws.rs.core.MediaType;
56 import javax.ws.rs.core.MultivaluedHashMap;
57 import javax.ws.rs.core.MultivaluedMap;
58 import javax.ws.rs.core.Response;
59 import javax.ws.rs.core.UriBuilder;
60 import javax.ws.rs.core.UriInfo;
61
62 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
63 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
64 import org.apache.tinkerpop.gremlin.structure.Edge;
65 import org.apache.tinkerpop.gremlin.structure.Vertex;
66 import org.javatuples.Pair;
67 import org.json.JSONArray;
68 import org.json.JSONObject;
69 import org.junit.After;
70 import org.junit.Assert;
71 import org.junit.Before;
72 import org.junit.FixMethodOrder;
73 import org.junit.Test;
74 import org.junit.runner.RunWith;
75 import org.junit.runners.MethodSorters;
76 import org.junit.runners.Parameterized;
77 import org.mockito.Mockito;
78 import org.onap.aai.AAISetup;
79 import org.onap.aai.db.props.AAIProperties;
80 import org.onap.aai.edges.enums.EdgeField;
81 import org.onap.aai.edges.enums.EdgeProperty;
82 import org.onap.aai.exceptions.AAIException;
83 import org.onap.aai.introspection.Introspector;
84 import org.onap.aai.introspection.Loader;
85 import org.onap.aai.introspection.ModelType;
86 import org.onap.aai.parsers.query.QueryParser;
87 import org.onap.aai.prevalidation.ValidationService;
88 import org.onap.aai.rest.db.responses.ErrorResponse;
89 import org.onap.aai.rest.db.responses.Relationship;
90 import org.onap.aai.rest.db.responses.RelationshipWrapper;
91 import org.onap.aai.rest.db.responses.ServiceException;
92 import org.onap.aai.rest.ueb.UEBNotification;
93 import org.onap.aai.restcore.HttpMethod;
94 import org.onap.aai.serialization.engines.QueryStyle;
95 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
96 import org.onap.aai.util.AAIConfig;
97 import org.skyscreamer.jsonassert.JSONAssert;
98 import org.skyscreamer.jsonassert.JSONCompareMode;
99 import org.springframework.boot.test.mock.mockito.MockBean;
100
101 @RunWith(value = Parameterized.class)
102 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
103 public class HttpEntryTest extends AAISetup {
104
105     @MockBean ValidationService validationService;
106
107     protected static final MediaType APPLICATION_JSON = MediaType.valueOf("application/json");
108
109     private static final Set<Integer> VALID_HTTP_STATUS_CODES = new HashSet<>();
110
111     static {
112         VALID_HTTP_STATUS_CODES.add(200);
113         VALID_HTTP_STATUS_CODES.add(201);
114         VALID_HTTP_STATUS_CODES.add(204);
115     }
116
117     @Parameterized.Parameter(value = 0)
118     public QueryStyle queryStyle;
119
120     /*
121      * TODO Change the HttpEntry instances accoringly
122      */
123     @Parameterized.Parameters(name = "QueryStyle.{0}")
124     public static Collection<Object[]> data() {
125         return Arrays.asList(new Object[][] { { QueryStyle.TRAVERSAL } });
126     }
127
128     private Loader loader;
129     private TransactionalGraphEngine dbEngine;
130     private GraphTraversalSource traversal;
131
132     private HttpHeaders httpHeaders;
133
134     private UriInfo uriInfo;
135
136     private MultivaluedMap<String, String> headersMultiMap;
137     private MultivaluedMap<String, String> queryParameters;
138
139     private List<String> aaiRequestContextList;
140
141     private List<MediaType> outputMediaTypes;
142
143     ObjectMapper mapper = new ObjectMapper();
144
145     @Before
146     public void setup() {
147
148         httpHeaders = Mockito.mock(HttpHeaders.class);
149         uriInfo = Mockito.mock(UriInfo.class);
150
151         headersMultiMap = new MultivaluedHashMap<>();
152         queryParameters = Mockito.spy(new MultivaluedHashMap<>());
153
154         headersMultiMap.add("X-FromAppId", "JUNIT");
155         headersMultiMap.add("X-TransactionId", UUID.randomUUID().toString());
156         headersMultiMap.add("Real-Time", "true");
157         headersMultiMap.add("Accept", "application/json");
158         headersMultiMap.add("aai-request-context", "");
159
160         outputMediaTypes = new ArrayList<>();
161         outputMediaTypes.add(APPLICATION_JSON);
162
163         aaiRequestContextList = new ArrayList<>();
164         aaiRequestContextList.add("");
165
166         traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion());
167         loader = traversalHttpEntry.getLoader();
168         dbEngine = traversalHttpEntry.getDbEngine();
169         traversal = dbEngine.tx().traversal();
170
171         when(httpHeaders.getAcceptableMediaTypes()).thenReturn(outputMediaTypes);
172         when(httpHeaders.getRequestHeaders()).thenReturn(headersMultiMap);
173
174         when(httpHeaders.getRequestHeader("aai-request-context")).thenReturn(aaiRequestContextList);
175
176         when(uriInfo.getQueryParameters()).thenReturn(queryParameters);
177         when(uriInfo.getQueryParameters(false)).thenReturn(queryParameters);
178
179         // TODO - Check if this is valid since RemoveDME2QueryParameters seems to be
180         // very unreasonable
181         Mockito.doReturn(null).when(queryParameters).remove(any());
182
183         when(httpHeaders.getMediaType()).thenReturn(APPLICATION_JSON);
184     }
185
186     @After
187     public void rollback() {
188         dbEngine.rollback();
189     }
190
191     @Test
192     public void thatObjectsCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
193         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
194         traversal.addV()
195                 .property("aai-node-type", "pserver")
196                 .property("hostname", "theHostname")
197                 .property("equip-type", "theEquipType")
198                 .property(AAIProperties.AAI_URI, uri)
199                 .next();
200         String requestBody = new JSONObject()
201                 .put("hostname", "theHostname")
202                 .put("equip-type", "theEquipType")
203                 .toString();
204
205         JSONObject expectedResponseBody = new JSONObject()
206                 .put("hostname", "theHostname")
207                 .put("equip-type", "theEquipType");
208         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
209         JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
210
211         JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
212         assertEquals("Expected the pserver to be returned", 200, response.getStatus());
213         verify(validationService, times(1)).validate(any());
214     }
215
216     @Test
217     public void thatObjectsCanNotBeFound() throws UnsupportedEncodingException, AAIException {
218         String uri = "/cloud-infrastructure/pservers/pserver/junit-test2";
219         String requestBody = "";
220
221         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
222         assertEquals("The pserver is not found", 404, response.getStatus());
223     }
224
225     @Test
226     public void thatObjectCanBeCreatedViaPUT() throws UnsupportedEncodingException, AAIException {
227         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
228         String requestBody = new JSONObject().put("hostname", "theHostname").toString();
229
230         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
231         assertEquals("Expecting the pserver to be created", 201, response.getStatus());
232         verify(validationService, times(1)).validate(any());
233     }
234
235     @Test
236     public void thatObjectCreationFailsWhenResourceVersionIsProvided()
237             throws UnsupportedEncodingException, AAIException, JsonMappingException, JsonProcessingException {
238         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
239         String requestBody = new JSONObject()
240                 .put("hostname", "theHostname")
241                 .put("resource-version", "123")
242                 .toString();
243
244         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
245         ErrorResponse errorResponseEntity = mapper.readValue(response.getEntity().toString(), ErrorResponse.class);
246         assertEquals("Expecting the pserver to be created", 412, response.getStatus());
247         assertEquals(
248                 "Resource version specified on create:resource-version passed for create of /cloud-infrastructure/pservers/pserver/theHostname",
249                 errorResponseEntity.getRequestError().getServiceException().getVariables().get(2));
250     }
251
252     @Test
253     public void thatObjectCanBeUpdatedViaPUT() throws UnsupportedEncodingException, AAIException {
254         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
255         traversal.addV()
256                 .property("aai-node-type", "pserver")
257                 .property("hostname", "theHostname")
258                 .property("number-of-cpus", "10")
259                 .property(AAIProperties.AAI_URI, uri)
260                 .property(AAIProperties.RESOURCE_VERSION, "123")
261                 .next();
262         String requestBody = new JSONObject()
263                 .put("hostname", "updatedHostname")
264                 .put("resource-version", "123")
265                 .toString();
266
267         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
268         assertEquals("Expecting the pserver to be updated", 200, response.getStatus());
269         assertTrue("That old properties are removed",
270                 traversal.V().has("hostname", "updatedHostname").hasNot("number-of-cpus").hasNext());
271         verify(validationService, times(1)).validate(any());
272     }
273
274     @Test
275     public void thatUpdateFailsWhenResourceVersionsMismatch()
276             throws UnsupportedEncodingException, AAIException, JsonMappingException, JsonProcessingException {
277         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
278         traversal.addV()
279                 .property("aai-node-type", "pserver")
280                 .property("hostname", "theHostname")
281                 .property(AAIProperties.AAI_URI, uri)
282                 .property(AAIProperties.RESOURCE_VERSION, "123")
283                 .next();
284         String requestBody = new JSONObject()
285                 .put("hostname", "updatedHostname")
286                 .put("resource-version", "456")
287                 .toString();
288
289         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
290         ErrorResponse errorResponseEntity = mapper.readValue(response.getEntity().toString(), ErrorResponse.class);
291         assertEquals("Expecting the update to fail", 412, response.getStatus());
292         assertEquals(
293                 "Precondition Failed:resource-version MISMATCH for update of /cloud-infrastructure/pservers/pserver/updatedHostname",
294                 errorResponseEntity.getRequestError().getServiceException().getVariables().get(2));
295     }
296
297     @Test
298     public void thatUpdateFailsWhenResourceVersionIsNotProvided()
299             throws UnsupportedEncodingException, AAIException, JsonMappingException, JsonProcessingException {
300         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
301         traversal.addV()
302                 .property("aai-node-type", "pserver")
303                 .property("hostname", "theHostname")
304                 .property("in-maint", "false")
305                 .property(AAIProperties.AAI_URI, uri)
306                 .next();
307
308         String requestBody = new JSONObject()
309                 .put("hostname", "theHostname")
310                 .put("is-maint", "true")
311                 .toString();
312
313         doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
314         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
315         ErrorResponse errorResponseEntity = mapper.readValue(response.getEntity().toString(), ErrorResponse.class);
316         assertEquals("Request should fail when no resource-version is provided", 412, response.getStatus());
317         assertEquals(
318                 "Precondition Required:resource-version not passed for update of /cloud-infrastructure/pservers/pserver/theHostname",
319                 errorResponseEntity.getRequestError().getServiceException().getVariables().get(2));
320     }
321
322     @Test
323     public void thatCreateViaPUTAddsRelationshipsToExistingObjects() throws UnsupportedEncodingException, AAIException {
324         traversal.addV()
325                 .property("aai-node-type", "pserver")
326                 .property("hostname", "hostname")
327                 .property(AAIProperties.AAI_URI, "/cloud-infrastructure/pservers/pserver/hostname")
328                 .next();
329         String uri = "/cloud-infrastructure/pservers/pserver/hostname/p-interfaces/p-interface/p1";
330         String requestBody = new JSONObject().put("interface-name", "p1").toString();
331
332         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
333         assertEquals("response is successful", 201, response.getStatus());
334         assertTrue("p-interface was created",
335                 traversal.V().has("aai-node-type", "p-interface").has("interface-name", "p1").hasNext());
336         assertTrue("p-interface has outgoing edge to p-server",
337                 traversal.V().has("aai-node-type", "p-interface").has("aai-uri", uri).has("interface-name", "p1")
338                         .out("tosca.relationships.network.BindsTo").has("aai-node-type", "pserver")
339                         .has("hostname", "hostname").hasNext());
340         verify(validationService, times(1)).validate(any());
341     }
342
343     @Test
344     public void thatObjectsCanBePatched() throws UnsupportedEncodingException, AAIException {
345         String uri = "/cloud-infrastructure/pservers/pserver/the-hostname";
346         traversal.addV()
347                 .property("aai-node-type", "pserver")
348                 .property("hostname", "the-hostname")
349                 .property("equip-type", "the-equip-type")
350                 .property(AAIProperties.AAI_URI, uri)
351                 .next();
352         String requestBody = new JSONObject()
353                 .put("hostname", "new-hostname")
354                 .toString();
355         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.MERGE_PATCH, uri, requestBody);
356         assertEquals("Expected the pserver to be updated", 200, response.getStatus());
357         assertTrue("object should be updated while keeping old properties",
358                 traversal.V().has("aai-node-type", "pserver").has("hostname", "new-hostname")
359                         .has("equip-type", "the-equip-type").hasNext());
360         verify(validationService, times(1)).validate(any());
361     }
362
363     @Test
364     public void thatObjectsCanBeDeleted() throws UnsupportedEncodingException, AAIException {
365         String uri = "/cloud-infrastructure/pservers/pserver/the-hostname";
366         String resourceVersion = "123";
367         traversal.addV()
368                 .property("aai-node-type", "pserver")
369                 .property("hostname", "the-hostname")
370                 .property(AAIProperties.AAI_URI, uri)
371                 .property(AAIProperties.RESOURCE_VERSION, resourceVersion)
372                 .next();
373         assertEquals("Expecting a No Content response", 204,
374                 doDelete(resourceVersion, uri, "pserver").getStatus());
375         assertTrue("Expecting the pserver to be deleted",
376                 !traversal.V().has("aai-node-type", "pserver").has("hostname", "the-hostname").hasNext());
377         verify(validationService, times(1)).validate(any());
378     }
379
380     @Test
381     public void thatRelationshipCanBeCreated() throws UnsupportedEncodingException, AAIException {
382         String uri = "/cloud-infrastructure/pservers/pserver/edge-test-pserver";
383         traversal.addV()
384                 .property("aai-node-type", "pserver")
385                 .property("hostname", "edge-test-pserver")
386                 .property(AAIProperties.AAI_URI, uri)
387                 .property(AAIProperties.RESOURCE_VERSION, "123")
388                 .next();
389         uri = "/cloud-infrastructure/complexes/complex/edge-test-complex";
390         traversal.addV()
391                 .property("aai-node-type", "complex")
392                 .property("physical-location-id", "edge-test-complex")
393                 .property("physical-location-type", "AAIDefault")
394                 .property("street1", "AAIDefault")
395                 .property("city", "AAIDefault")
396                 .property("postal-code", "07748")
397                 .property("country", "USA")
398                 .property("region", "US")
399                 .property(AAIProperties.AAI_URI, uri)
400                 .property(AAIProperties.RESOURCE_VERSION, "234")
401                 .next();
402
403         uri = "/cloud-infrastructure/complexes/complex/edge-test-complex/relationship-list/relationship";
404         String requestBody = new JSONObject()
405                 .put("related-to", "pserver")
406                 .put("related-link",
407                         String.format("/aai/%s/cloud-infrastructure/pservers/pserver/edge-test-pserver",
408                                 schemaVersions.getDefaultVersion().toString()))
409                 .put("relationship-label", "org.onap.relationships.inventory.LocatedIn")
410                 .toString();
411
412         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT_EDGE, uri, requestBody);
413         assertEquals("Expected the pserver relationship to be created", 200, response.getStatus());
414         GraphTraversal<Vertex, Vertex> vertexQuery = traversal.V()
415                 .has("aai-node-type", "complex")
416                 .has("physical-location-id", "edge-test-complex")
417                 .in("org.onap.relationships.inventory.LocatedIn")
418                 .has("aai-node-type", "pserver")
419                 .has("hostname", "edge-test-pserver");
420         GraphTraversal<Edge, Edge> edgeQuery = traversal.E()
421                 .has(EdgeField.PRIVATE.toString(), "false")
422                 .has(EdgeProperty.CONTAINS.toString(), NONE.toString())
423                 .has(EdgeProperty.DELETE_OTHER_V.toString(), NONE.toString())
424                 .has(EdgeProperty.PREVENT_DELETE.toString(), "IN");
425         assertTrue("p-server has incoming edge from complex", vertexQuery.hasNext());
426         assertTrue("Created Edge has expected properties", edgeQuery.hasNext());
427         verify(validationService, times(1)).validate(any());
428     }
429
430     @Test
431     public void thatRelationshipCanNotBeCreatedEdgeMultiplicity()
432             throws UnsupportedEncodingException, AAIException, JsonMappingException, JsonProcessingException {
433         String uri = "/cloud-infrastructure/pservers/pserver/httpEntryTest-pserver-01";
434         traversal
435                 .addV() // pserver
436                 .property("aai-node-type", "pserver")
437                 .property("hostname", "httpEntryTest-pserver-01")
438                 .property(AAIProperties.AAI_URI, uri)
439                 .property(AAIProperties.RESOURCE_VERSION, "123")
440                 .as("v1")
441                 .addV() // complex
442                 .property("aai-node-type", "complex")
443                 .property("physical-location-id", "httpEntryTest-complex-01")
444                 .property("physical-location-type", "AAIDefault")
445                 .property("street1", "AAIDefault")
446                 .property("city", "AAIDefault")
447                 .property("postal-code", "07748")
448                 .property("country", "USA")
449                 .property("region", "US")
450                 .property(AAIProperties.AAI_URI, "/cloud-infrastructure/complexes/complex/httpEntryTest-complex-01")
451                 .property(AAIProperties.RESOURCE_VERSION, "234")
452                 .as("v2")
453                 // edge between pserver and complex
454                 .addE("org.onap.relationships.inventory.LocatedIn").from("v1").to("v2")
455                 .next();
456
457         // Put Relationship
458         uri = "/cloud-infrastructure/pservers/pserver/httpEntryTest-pserver-01/relationship-list/relationship";
459         String requestBody = new JSONObject()
460                 .put("related-to", "complex")
461                 .put("related-link",
462                         String.format("/aai/%s/cloud-infrastructure/complexes/complex/httpEntryTest-complex-01",
463                                 schemaVersions.getDefaultVersion().toString()))
464                 .put("relationship-label", "org.onap.relationships.inventory.LocatedIn")
465                 .toString();
466         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT_EDGE, uri, requestBody);
467         ServiceException serviceException = mapper.readValue(response.getEntity().toString(), ErrorResponse.class)
468                 .getRequestError().getServiceException();
469
470         assertEquals("Expected the response code to be Bad Request", 400, response.getStatus());
471         assertEquals("ERR.5.4.6140", serviceException.getVariables().get(3));
472         assertEquals(
473                 "Edge multiplicity violated:multiplicity rule violated: only one edge can exist with label: org.onap.relationships.inventory.LocatedIn between pserver and complex",
474                 serviceException.getVariables().get(2));
475     }
476
477     @Test
478     public void putEdgeWrongLabelTest()
479             throws UnsupportedEncodingException, AAIException, JsonMappingException, JsonProcessingException {
480         String uri = "/cloud-infrastructure/pservers/pserver/edge-test-pserver";
481         traversal.addV()
482                 .property("aai-node-type", "pserver")
483                 .property("hostname", "edge-test-pserver")
484                 .property(AAIProperties.AAI_URI, uri)
485                 .property(AAIProperties.RESOURCE_VERSION, "123")
486                 .next();
487         uri = "/cloud-infrastructure/complexes/complex/edge-test-complex";
488         traversal.addV()
489                 .property("aai-node-type", "complex")
490                 .property("physical-location-id", "edge-test-complex")
491                 .property("physical-location-type", "AAIDefault")
492                 .property("street1", "AAIDefault")
493                 .property("city", "AAIDefault")
494                 .property("postal-code", "07748")
495                 .property("country", "USA")
496                 .property("region", "US")
497                 .property(AAIProperties.AAI_URI, uri)
498                 .property(AAIProperties.RESOURCE_VERSION, "234")
499                 .next();
500
501         uri = "/cloud-infrastructure/complexes/complex/edge-test-complex/relationship-list/relationship";
502         String requestBody = new JSONObject()
503                 .put("related-to", "pserver")
504                 .put("related-link",
505                         String.format("/aai/%s/cloud-infrastructure/pservers/pserver/edge-test-pserver",
506                                 schemaVersions.getDefaultVersion().toString()))
507                 .put("relationship-label", "does.not.exist")
508                 .toString();
509
510         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT_EDGE, uri, requestBody);
511         ServiceException serviceException = mapper.readValue(response.getEntity().toString(), ErrorResponse.class)
512                 .getRequestError().getServiceException();
513
514         assertEquals("Expected the pserver to be created", 400, response.getStatus());
515         assertEquals("ERR.5.4.6107", serviceException.getVariables().get(3));
516         assertEquals(
517                 "Required Edge-property not found in input data:org.onap.aai.edges.exceptions.EdgeRuleNotFoundException: No rule found for EdgeRuleQuery with filter params node type: complex, node type: pserver, label: does.not.exist, type: COUSIN, isPrivate: false.",
518                 serviceException.getVariables().get(2));
519     }
520
521     @Test
522     public void thatObjectsCanBeRetrievedInPathedResponseFormat() throws UnsupportedEncodingException, AAIException {
523         traversal
524                 .addV() // pserver
525                 .property("aai-node-type", "pserver")
526                 .property("hostname", "pserver-1")
527                 .property(AAIProperties.AAI_URI, "/cloud-infrastructure/pservers/pserver/pserver-1")
528                 .property(AAIProperties.RESOURCE_VERSION, "123")
529                 .addV() // pserver
530                 .property("aai-node-type", "pserver")
531                 .property("hostname", "pserver-2")
532                 .property(AAIProperties.AAI_URI, "/cloud-infrastructure/pservers/pserver/pserver-2")
533                 .property(AAIProperties.RESOURCE_VERSION, "234")
534                 .next();
535
536         queryParameters.add("format", "pathed");
537         String requestBody = "";
538         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET,
539                 "/cloud-infrastructure/pservers", requestBody);
540         queryParameters.remove("format");
541
542         String responseEntity = response.getEntity().toString();
543         assertEquals("Expected get to succeed", 200, response.getStatus());
544         assertThat(responseEntity, containsString("/cloud-infrastructure/pservers/pserver/pserver-1"));
545         assertThat(responseEntity, containsString("/cloud-infrastructure/pservers/pserver/pserver-2"));
546         verify(validationService, times(1)).validate(any());
547     }
548
549     @Test
550     public void thatRelatedObjectsCanBeRetrieved() throws UnsupportedEncodingException, AAIException {
551         String uri = "/cloud-infrastructure/pservers/pserver/related-to-pserver";
552         traversal
553                 .addV() // pserver
554                 .property("aai-node-type", "pserver")
555                 .property("hostname", "related-to-pserver")
556                 .property(AAIProperties.AAI_URI, uri)
557                 .property(AAIProperties.RESOURCE_VERSION, "123")
558                 .as("v1")
559                 .addV() // complex
560                 .property("aai-node-type", "complex")
561                 .property("physical-location-id", "related-to-complex")
562                 .property("physical-location-type", "AAIDefault")
563                 .property("street1", "AAIDefault")
564                 .property("city", "AAIDefault")
565                 .property("postal-code", "07748")
566                 .property("country", "USA")
567                 .property("region", "US")
568                 .property(AAIProperties.AAI_URI, "/cloud-infrastructure/complexes/complex/related-to-complex")
569                 .property(AAIProperties.RESOURCE_VERSION, "234")
570                 .as("v2")
571                 // edge between pserver and complex
572                 .addE("org.onap.relationships.inventory.LocatedIn").from("v1").to("v2")
573                 .next();
574
575         uri = "/cloud-infrastructure/complexes/complex/related-to-complex/related-to/pservers";
576         String responseBody = "";
577         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, responseBody);
578
579         assertEquals("Expected the response to be successful", 200, response.getStatus());
580         assertThat("Related pserver is returned", response.getEntity().toString(),
581                 containsString("\"hostname\":\"related-to-pserver\""));
582         verify(validationService, times(1)).validate(any());
583
584     }
585
586     @Test
587     public void getAbstractTest() throws UnsupportedEncodingException, AAIException {
588         String uri = "/cloud-infrastructure/pservers/pserver/abstract-pserver";
589         traversal
590                 .addV() // pserver
591                 .property("aai-node-type", "pserver")
592                 .property("hostname", "abstract-pserver")
593                 .property(AAIProperties.AAI_URI, uri)
594                 .property(AAIProperties.RESOURCE_VERSION, "123")
595                 .as("v1")
596                 .addV() // generic-vnf
597                 .property("aai-node-type", "generic-vnf")
598                 .property("vnf-id", "abstract-generic-vnf")
599                 .property("vnf-name", "the-vnf-name")
600                 .property(AAIProperties.AAI_URI, "/network/generic-vnfs/generic-vnf/abstract-generic-vnf")
601                 .property(AAIProperties.RESOURCE_VERSION, "234")
602                 .as("v2")
603                 // edge between pserver and generic-vnf
604                 .addE("tosca.relationships.HostedOn").from("v2").to("v1")
605                 .next();
606
607         String requestBody = "";
608         uri = "/network/generic-vnfs/generic-vnf/abstract-generic-vnf/related-to/pservers";
609         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
610         assertThat("Related to pserver is returned.", response.getEntity().toString(),
611                 containsString("\"hostname\":\"abstract-pserver\""));
612         verify(validationService, times(1)).validate(any());
613     }
614
615     @Test
616     public void getRelationshipListTest()
617             throws UnsupportedEncodingException, AAIException, JsonMappingException, JsonProcessingException {
618         String uri = "/cloud-infrastructure/pservers/pserver/related-to-pserver";
619         traversal
620                 .addV() // pserver
621                 .property("aai-node-type", "pserver")
622                 .property("hostname", "related-to-pserver")
623                 .property(AAIProperties.AAI_URI, uri)
624                 .property(AAIProperties.RESOURCE_VERSION, "123")
625                 .as("v1")
626                 .addV() // complex
627                 .property("aai-node-type", "complex")
628                 .property("physical-location-id", "related-to-complex")
629                 .property("physical-location-type", "AAIDefault")
630                 .property("street1", "AAIDefault")
631                 .property("city", "AAIDefault")
632                 .property("postal-code", "07748")
633                 .property("country", "USA")
634                 .property("region", "US")
635                 .property(AAIProperties.AAI_URI, "/cloud-infrastructure/complexes/complex/related-to-complex")
636                 .property(AAIProperties.RESOURCE_VERSION, "234")
637                 .as("v2")
638                 // edge between pserver and complex
639                 .addE("org.onap.relationships.inventory.LocatedIn").from("v1").to("v2")
640                 // these properties are required when finding related edges
641                 .property(EdgeProperty.CONTAINS.toString(), NONE.toString())
642                 .property(EdgeField.PRIVATE.toString(), "false")
643                 .next();
644
645         // Get Relationship
646         uri = "/cloud-infrastructure/pservers/pserver/related-to-pserver";
647         String requestBody = "";
648         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET_RELATIONSHIP, uri,
649                 requestBody);
650         Relationship[] relationships = mapper.readValue(response.getEntity().toString(), RelationshipWrapper.class)
651                 .getRelationships();
652
653         assertEquals("complex", relationships[0].getRelatedTo());
654         assertEquals("org.onap.relationships.inventory.LocatedIn", relationships[0].getRelationshipLabel());
655         assertEquals("/aai/v14/cloud-infrastructure/complexes/complex/related-to-complex",
656                 relationships[0].getRelatedLink());
657         assertEquals("complex.physical-location-id", relationships[0].getRelationshipData()[0].getRelationshipKey());
658         assertEquals("related-to-complex", relationships[0].getRelationshipData()[0].getRelationshipValue());
659         verify(validationService, times(1)).validate(any());
660     }
661
662     @Test
663     public void getRelationshipListTestWithFormatSimple() throws UnsupportedEncodingException, AAIException {
664         String uri = "/cloud-infrastructure/pservers/pserver/related-to-pserver";
665         traversal
666                 .addV() // pserver
667                 .property("aai-node-type", "pserver")
668                 .property("hostname", "related-to-pserver")
669                 .property(AAIProperties.AAI_URI, uri)
670                 .property(AAIProperties.RESOURCE_VERSION, "123")
671                 .as("v1")
672                 .addV() // complex
673                 .property("aai-node-type", "complex")
674                 .property("physical-location-id", "related-to-complex")
675                 .property("physical-location-type", "AAIDefault")
676                 .property("street1", "AAIDefault")
677                 .property("city", "AAIDefault")
678                 .property("postal-code", "07748")
679                 .property("country", "USA")
680                 .property("region", "US")
681                 .property(AAIProperties.AAI_URI, "/cloud-infrastructure/complexes/complex/related-to-complex")
682                 .property(AAIProperties.RESOURCE_VERSION, "234")
683                 .as("v2")
684                 // edge between pserver and complex
685                 .addE("org.onap.relationships.inventory.LocatedIn").from("v1").to("v2")
686                 // these properties are required when finding related edges
687                 .property(EdgeProperty.CONTAINS.toString(), NONE.toString())
688                 .property(EdgeField.PRIVATE.toString(), "false")
689                 .next();
690
691         // Get Relationship
692         uri = "/cloud-infrastructure/pservers/pserver/related-to-pserver";
693         queryParameters.add("format", "resource");
694         String requestBody = "";
695         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET_RELATIONSHIP, uri,
696                 requestBody);
697
698         JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
699
700         // Define the expected response
701         JSONObject relationshipData = new JSONObject().put("relationship-key", "complex.physical-location-id")
702                 .put("relationship-value", "related-to-complex");
703         JSONObject relationship = new JSONObject()
704                 .put("related-to", "complex")
705                 .put("relationship-label", "org.onap.relationships.inventory.LocatedIn")
706                 .put("related-link",
707                         String.format("/aai/%s/cloud-infrastructure/complexes/complex/related-to-complex",
708                                 schemaVersions.getDefaultVersion()))
709                 .put("relationship-data", new JSONArray().put(relationshipData));
710         JSONObject pserver = new JSONObject()
711                 .put("hostname", "related-to-pserver")
712                 .put("resource-version", "123")
713                 .put("relationship-list", new JSONObject().put("relationship", new JSONArray().put(relationship)));
714         JSONObject expectedResponseBody = new JSONObject()
715                 .put("results", new JSONArray().put(new JSONObject().put("pserver", pserver)));
716
717         JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
718         queryParameters.remove("format");
719         verify(validationService, times(1)).validate(any());
720     }
721
722     @Test
723     public void notificationOnRelatedToTest() throws UnsupportedEncodingException, AAIException {
724
725         Loader ld = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion());
726         UEBNotification uebNotification = Mockito.spy(new UEBNotification(ld, loaderFactory, schemaVersions));
727         traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), uebNotification);
728
729         Loader loader = traversalHttpEntry.getLoader();
730         TransactionalGraphEngine dbEngine = traversalHttpEntry.getDbEngine();
731         // Put pserver
732         String uri = "/cloud-infrastructure/pservers/pserver/junit-edge-test-pserver";
733         String content = "{\"hostname\":\"junit-edge-test-pserver\"}";
734         doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, content);
735         // Put complex
736         uri = "/cloud-infrastructure/complexes/complex/junit-edge-test-complex";
737         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\"}";
738         doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, content);
739
740         // PutEdge
741         uri = "/cloud-infrastructure/complexes/complex/junit-edge-test-complex/relationship-list/relationship";
742         content = "{\"related-to\":\"pserver\",\"related-link\":\"/aai/" + schemaVersions.getDefaultVersion().toString()
743                 + "/cloud-infrastructure/pservers/pserver/junit-edge-test-pserver\",\"relationship-label\":\"org.onap.relationships.inventory.LocatedIn\"}";
744
745         doNothing().when(uebNotification).triggerEvents();
746         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT_EDGE, uri, content);
747
748         assertEquals("Expected the pserver relationship to be deleted", 200, response.getStatus());
749         assertEquals("Two notifications", 2, uebNotification.getEvents().size());
750         assertEquals("Notification generated for PUT edge", "UPDATE",
751                 uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString());
752         assertThat("Event body for the edge create has the related to",
753                 uebNotification.getEvents().get(0).getObj().marshal(false),
754                 containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver"));
755
756         response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.DELETE_EDGE, uri, content);
757         assertEquals("Expected the pserver relationship to be deleted", 204, response.getStatus());
758         assertEquals("Two notifications", 2, uebNotification.getEvents().size());
759         assertEquals("Notification generated for DELETE edge", "UPDATE",
760                 uebNotification.getEvents().get(0).getEventHeader().getValue("action").toString());
761         assertThat("Event body for the edge delete does not have the related to",
762                 uebNotification.getEvents().get(0).getObj().marshal(false),
763                 not(containsString("cloud-infrastructure/pservers/pserver/junit-edge-test-pserver")));
764         dbEngine.rollback();
765
766     }
767
768     private Response doRequest(HttpEntry httpEntry, Loader loader, TransactionalGraphEngine dbEngine, HttpMethod method,
769             String uri, String requestBody) throws UnsupportedEncodingException, AAIException {
770         URI uriObject = UriBuilder.fromPath(uri).build();
771         QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
772         String objType = uriQuery.getResultType();
773         if (uri.endsWith("relationship")) {
774             objType = "relationship";
775         }
776         Introspector obj;
777         if (method.equals(HttpMethod.GET) || method.equals(HttpMethod.GET_RELATIONSHIP)) {
778             obj = loader.introspectorFromName(objType);
779         } else {
780             obj = loader.unmarshal(objType, requestBody, org.onap.aai.restcore.MediaType.getEnum("application/json"));
781         }
782
783         DBRequest dbRequest = new DBRequest.Builder(method, uriObject, uriQuery, obj, httpHeaders, uriInfo,
784                 "JUNIT-TRANSACTION")
785                 .rawRequestContent(requestBody).build();
786
787         List<DBRequest> dbRequestList = new ArrayList<>();
788         dbRequestList.add(dbRequest);
789
790         Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(dbRequestList, "JUNIT");
791         return responsesTuple.getValue1().get(0).getValue1();
792     }
793
794     private Response doDelete(String resourceVersion, String uri, String nodeType)
795             throws UnsupportedEncodingException, AAIException {
796         queryParameters.add("resource-version", resourceVersion);
797
798         URI uriObject = UriBuilder.fromPath(uri).build();
799
800         QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
801
802         String content = "";
803
804         Introspector obj = loader.introspectorFromName(nodeType);
805
806         DBRequest dbRequest = new DBRequest.Builder(HttpMethod.DELETE, uriObject, uriQuery, obj, httpHeaders, uriInfo,
807                 "JUNIT-TRANSACTION").rawRequestContent(content).build();
808
809         Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = traversalHttpEntry.process(Arrays.asList(dbRequest),
810                 "JUNIT");
811         return responsesTuple.getValue1().get(0).getValue1();
812     }
813
814     @Test
815     public void testSetGetPaginationMethods() {
816         traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion());
817         traversalHttpEntry.setPaginationBucket(10);
818         traversalHttpEntry.setPaginationIndex(1);
819         traversalHttpEntry.setTotalsForPaging(101, traversalHttpEntry.getPaginationBucket());
820         assertEquals("Expected the pagination bucket size to be 10", 10, traversalHttpEntry.getPaginationBucket());
821         assertEquals("Expected the total number of pagination buckets to be 11", 11,
822                 traversalHttpEntry.getTotalPaginationBuckets());
823         assertEquals("Expected the pagination index to be 1", 1, traversalHttpEntry.getPaginationIndex());
824         assertEquals("Expected the total amount of vertices to be 101", 101, traversalHttpEntry.getTotalVertices());
825     }
826
827     @Test
828     public void setDepthTest() throws AAIException {
829         System.setProperty("AJSC_HOME", ".");
830         System.setProperty("BUNDLECONFIG_DIR", "src/main/test/resources");
831
832         String depthParam = AAIConfig.get("aai.rest.getall.depthparam");
833         traversalHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion());
834         int depth = traversalHttpEntry.setDepth(null, depthParam);
835         assertEquals(AAIProperties.MAXIMUM_DEPTH.intValue(), depth);
836     }
837
838     @Test
839     public void thatEventsAreValidated() throws AAIException, UnsupportedEncodingException {
840         String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
841         traversal.addV()
842                 .property("aai-node-type", "pserver")
843                 .property("hostname", "theHostname")
844                 .property("equip-type", "theEquipType")
845                 .property(AAIProperties.AAI_URI, uri)
846                 .next();
847         String requestBody = new JSONObject()
848                 .put("hostname", "theHostname")
849                 .put("equip-type", "theEquipType")
850                 .toString();
851
852         JSONObject expectedResponseBody = new JSONObject()
853                 .put("hostname", "theHostname")
854                 .put("equip-type", "theEquipType");
855         Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
856         JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
857
858         JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
859         assertEquals("Expected the pserver to be returned", 200, response.getStatus());
860         verify(validationService, times(1)).validate(any());
861     }
862 }