2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.aai.introspection.sideeffect;
23 import static org.hamcrest.MatcherAssert.assertThat;
24 import static org.hamcrest.Matchers.is;
25 import static org.hamcrest.Matchers.not;
26 import static org.junit.Assert.*;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.when;
30 import java.io.UnsupportedEncodingException;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.List;
34 import java.util.UUID;
36 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
37 import org.apache.tinkerpop.gremlin.structure.Graph;
38 import org.apache.tinkerpop.gremlin.structure.Vertex;
39 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
40 import org.janusgraph.core.Cardinality;
41 import org.janusgraph.core.JanusGraph;
42 import org.janusgraph.core.JanusGraphFactory;
43 import org.janusgraph.core.schema.JanusGraphManagement;
45 import org.junit.rules.ExpectedException;
46 import org.junit.runner.RunWith;
47 import org.junit.runners.Parameterized;
48 import org.mockito.Mock;
49 import org.mockito.MockitoAnnotations;
50 import org.onap.aai.DataLinkSetup;
51 import org.onap.aai.db.props.AAIProperties;
52 import org.onap.aai.edges.enums.EdgeProperty;
53 import org.onap.aai.exceptions.AAIException;
54 import org.onap.aai.introspection.Introspector;
55 import org.onap.aai.introspection.Loader;
56 import org.onap.aai.introspection.ModelType;
57 import org.onap.aai.parsers.query.QueryParser;
58 import org.onap.aai.serialization.db.DBSerializer;
59 import org.onap.aai.serialization.engines.JanusGraphDBEngine;
60 import org.onap.aai.serialization.engines.QueryStyle;
61 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
63 @RunWith(value = Parameterized.class)
64 public class DataLinkTest extends DataLinkSetup {
66 private static JanusGraph graph;
67 private final static ModelType introspectorFactoryType = ModelType.MOXY;
68 private static Loader loader;
69 private static TransactionalGraphEngine dbEngine;
71 private QueryParser parser;
75 private VertexProperty<String> prop;
77 public ExpectedException thrown = ExpectedException.none();
79 @Parameterized.Parameter
80 public QueryStyle queryStyle;
82 @Parameterized.Parameters(name = "QueryStyle.{0}")
83 public static Collection<Object[]> data() {
84 return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}, {QueryStyle.TRAVERSAL_URI}});
88 public static void setup() {
89 graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open();
90 JanusGraphManagement graphMgt = graph.openManagement();
91 graphMgt.makePropertyKey(AAIProperties.CREATED_TS).dataType(Long.class).cardinality(Cardinality.SINGLE).make();
92 graphMgt.makePropertyKey(AAIProperties.LAST_MOD_TS).dataType(Long.class).cardinality(Cardinality.SINGLE).make();
97 .property("aai-node-type", "vpn-binding")
98 .property("vpn-id", "addKey")
99 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/addKey")
100 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
101 .property(AAIProperties.CREATED_TS, 123)
102 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
103 .property(AAIProperties.RESOURCE_VERSION, "123")
104 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
105 .property(AAIProperties.LAST_MOD_TS, 333)
108 .property("aai-node-type", "vpn-binding")
109 .property("vpn-id", "modifyKey")
110 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/modifyKey")
111 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
112 .property(AAIProperties.CREATED_TS, 123)
113 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
114 .property(AAIProperties.RESOURCE_VERSION, "123")
115 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
116 .property(AAIProperties.LAST_MOD_TS, 333)
119 .property("aai-node-type", "route-target")
120 .property("global-route-target", "modifyTargetKey")
121 .property("route-target-role", "modifyRoleKey")
122 .property("linked", true)
123 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/modifyKey/route-targets/route-target/modifyTargetKey/modifyRoleKey")
124 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
125 .property(AAIProperties.CREATED_TS, 123)
126 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
127 .property(AAIProperties.RESOURCE_VERSION, "123")
128 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
129 .property(AAIProperties.LAST_MOD_TS, 333)
131 .addE("org.onap.relationships.inventory.BelongsTo").to("v2").from("v3")
132 .property(EdgeProperty.CONTAINS.toString(), true)
134 .property("aai-node-type", "vpn-binding")
135 .property("vpn-id", "deleteKey")
136 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/deleteKey")
137 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
138 .property(AAIProperties.CREATED_TS, 123)
139 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
140 .property(AAIProperties.RESOURCE_VERSION, "123")
141 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
142 .property(AAIProperties.LAST_MOD_TS, 333)
145 .property("aai-node-type", "route-target")
146 .property("global-route-target", "deleteTargetKey")
147 .property("route-target-role", "deleteRoleKey")
148 .property("linked", true)
149 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/deleteKey/route-targets/route-target/deleteTargetKey/deleteRoleKey")
150 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
151 .property(AAIProperties.CREATED_TS, 123)
152 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
153 .property(AAIProperties.RESOURCE_VERSION, "123")
154 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
155 .property(AAIProperties.LAST_MOD_TS, 333)
157 .addE("org.onap.relationships.inventory.BelongsTo").to("v4").from("v5")
158 .property(EdgeProperty.CONTAINS.toString(), true)
160 .property("aai-node-type", "vpn-binding")
161 .property("vpn-id", "getKey")
162 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKey")
163 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
164 .property(AAIProperties.CREATED_TS, 123)
165 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
166 .property(AAIProperties.RESOURCE_VERSION, "123")
167 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
168 .property(AAIProperties.LAST_MOD_TS, 333)
171 .property("aai-node-type", "route-target")
172 .property("global-route-target", "getTargetKey")
173 .property("route-target-role", "getRoleKey")
174 .property("linked", true)
175 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKey/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink")
176 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
177 .property(AAIProperties.CREATED_TS, 123)
178 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
179 .property(AAIProperties.RESOURCE_VERSION, "123")
180 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
181 .property(AAIProperties.LAST_MOD_TS, 333)
183 .addE("org.onap.relationships.inventory.BelongsTo").to("v6").from("v7")
184 .property(EdgeProperty.CONTAINS.toString(), true)
186 .property("aai-node-type", "vpn-binding")
187 .property("vpn-id", "getKeyNoLink")
188 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKeyNoLink")
189 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
190 .property(AAIProperties.CREATED_TS, 123)
191 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
192 .property(AAIProperties.RESOURCE_VERSION, "123")
193 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
194 .property(AAIProperties.LAST_MOD_TS, 333)
197 .property("aai-node-type", "route-target")
198 .property("global-route-target", "getTargetKeyNoLink")
199 .property("route-target-role", "getRoleKeyNoLink")
200 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKeyNoLink/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink")
201 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
202 .property(AAIProperties.CREATED_TS, 123)
203 .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
204 .property(AAIProperties.RESOURCE_VERSION, "123")
205 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
206 .property(AAIProperties.LAST_MOD_TS, 333)
208 .addE("org.onap.relationships.inventory.BelongsTo").to("v8").from("v9")
209 .property(EdgeProperty.CONTAINS.toString(), true)
216 public static void tearDown() {
217 graph.tx().rollback();
222 public void initMock() {
223 loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion());
224 MockitoAnnotations.initMocks(this);
225 dbEngine = new JanusGraphDBEngine(queryStyle, loader);
229 public void verifyCreationOfVertex()
230 throws AAIException, UnsupportedEncodingException, IllegalArgumentException, SecurityException {
232 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
233 final Introspector obj = loader.introspectorFromName("vpn-binding");
234 obj.setValue("vpn-id", "addKey");
235 obj.setValue("global-route-target", "key1");
236 obj.setValue("route-target-role", "key2");
237 TransactionalGraphEngine spy = spy(dbEngine);
238 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
239 Graph g = graph.newTransaction();
240 GraphTraversalSource traversal = g.traversal();
241 when(spy.asAdmin()).thenReturn(adminSpy);
242 when(adminSpy.getTraversalSource()).thenReturn(traversal);
243 when(spy.tx()).thenReturn(g);
244 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
245 when(prop.orElse(null)).thenReturn(obj.getURI());
246 DBSerializer serializer =
247 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
248 SideEffectRunner runner =
249 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
251 runner.execute(obj, self);
253 assertTrue("route-target vertex found", traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
254 .has("global-route-target", "key1").has("route-target-role", "key2").has("linked", true).hasNext());
260 public void verifyModificationOfVertex()
261 throws AAIException, UnsupportedEncodingException, IllegalArgumentException, SecurityException {
263 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
264 final Introspector obj = loader.introspectorFromName("vpn-binding");
265 obj.setValue("vpn-id", "modifyKey");
266 obj.setValue("global-route-target", "modifyTargetKey2");
267 obj.setValue("route-target-role", "modifyRoleKey2");
268 TransactionalGraphEngine spy = spy(dbEngine);
269 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
270 Graph g = graph.newTransaction();
271 GraphTraversalSource traversal = g.traversal();
273 when(spy.asAdmin()).thenReturn(adminSpy);
274 when(adminSpy.getTraversalSource()).thenReturn(traversal);
275 when(spy.tx()).thenReturn(g);
276 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
277 when(prop.orElse(null)).thenReturn(obj.getURI());
278 DBSerializer serializer =
279 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
280 SideEffectRunner runner =
281 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
282 runner.execute(obj, self);
284 assertThat("new route-target vertex found with/or without link",
286 .has(AAIProperties.NODE_TYPE, "route-target")
287 .has("global-route-target", "modifyTargetKey2")
288 .has("route-target-role", "modifyRoleKey2")
291 assertThat("new route-target vertex has link",
293 .has(AAIProperties.NODE_TYPE, "route-target")
294 .has("global-route-target", "modifyTargetKey2")
295 .has("route-target-role", "modifyRoleKey2")
299 assertThat("previous vertex still exists",
301 .has(AAIProperties.NODE_TYPE, "route-target")
302 .has("global-route-target", "modifyTargetKey")
303 .has("route-target-role", "modifyRoleKey")
306 assertThat("link of previous vert removed",
308 .has(AAIProperties.NODE_TYPE, "route-target")
309 .has("global-route-target", "modifyTargetKey")
310 .has("route-target-role", "modifyRoleKey")
314 assertThat("previous vertex still exists",
316 .has(AAIProperties.NODE_TYPE, "route-target")
317 .has("global-route-target", "modifyTargetKey")
318 .has("route-target-role", "modifyRoleKey")
326 public void verifyDeleteOfVertex() throws Exception {
328 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
329 final Introspector obj = loader.introspectorFromName("vpn-binding");
330 obj.setValue("vpn-id", "deleteKey");
331 TransactionalGraphEngine spy = spy(dbEngine);
332 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
333 Graph g = graph.newTransaction();
334 GraphTraversalSource traversal = g.traversal();
335 when(spy.asAdmin()).thenReturn(adminSpy);
336 when(adminSpy.getTraversalSource()).thenReturn(traversal);
337 when(adminSpy.getReadOnlyTraversalSource()).thenReturn(traversal);
338 when(spy.tx()).thenReturn(g);
339 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
340 when(prop.orElse(null)).thenReturn(obj.getURI());
341 DBSerializer serializer =
342 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
343 SideEffectRunner runner =
344 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
346 runner.execute(obj, self);
348 assertFalse("route-target vertex not found",
350 .has(AAIProperties.NODE_TYPE, "route-target")
351 .has("global-route-target", "deleteTargetKey")
352 .has("route-target-role", "deleteRoleKey")
360 public void verifyPropertyPopulation() throws Exception {
362 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
363 final Introspector obj = loader.introspectorFromName("vpn-binding");
364 obj.setValue("vpn-id", "getKey");
365 TransactionalGraphEngine spy = spy(dbEngine);
366 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
367 Graph g = graph.newTransaction();
368 GraphTraversalSource traversal = g.traversal();
369 when(spy.asAdmin()).thenReturn(adminSpy);
370 when(adminSpy.getTraversalSource()).thenReturn(traversal);
371 when(spy.tx()).thenReturn(g);
372 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
373 when(prop.orElse(null)).thenReturn(obj.getURI());
374 DBSerializer serializer =
375 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
376 SideEffectRunner runner =
377 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkReader.class).build();
379 runner.execute(obj, self);
381 assertTrue("both properties have been populated in target object",
382 obj.getValue("global-route-target").equals("getTargetKey")
383 && obj.getValue("route-target-role").equals("getRoleKey"));
388 public void verifyPropertyPopulationWithV10OnlyPut()
389 throws AAIException, UnsupportedEncodingException, IllegalArgumentException, SecurityException {
390 final Introspector obj = loader.introspectorFromName("vpn-binding");
391 obj.setValue("vpn-id", "getKeyNoLink");
392 final Introspector routeTargets = loader.introspectorFromName("route-targets");
393 obj.setValue("route-targets", routeTargets.getUnderlyingObject());
394 List<Object> targets = routeTargets.getValue("route-target");
395 final Introspector routeTargetOne = loader.introspectorFromName("route-target");
396 routeTargetOne.setValue("global-route-target", "getTargetKeyNoLink");
397 routeTargetOne.setValue("route-target-role", "getRoleKeyNoLink");
398 targets.add(routeTargetOne.getUnderlyingObject());
399 final Introspector routeTargetTwo = loader.introspectorFromName("route-target");
400 routeTargetTwo.setValue("global-route-target", "getTargetKeyNoLink2");
401 routeTargetTwo.setValue("route-target-role", "getRoleKeyNoLink2");
402 targets.add(routeTargetTwo.getUnderlyingObject());
403 TransactionalGraphEngine spy = spy(dbEngine);
404 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
405 Graph g = graph.newTransaction();
406 GraphTraversalSource traversal = g.traversal();
407 when(spy.tx()).thenReturn(g);
408 when(spy.asAdmin()).thenReturn(adminSpy);
409 when(adminSpy.getTraversalSource()).thenReturn(traversal);
410 when(spy.tx()).thenReturn(g);
411 when(parser.isDependent()).thenReturn(false);
412 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
413 when(prop.orElse(null)).thenReturn(obj.getURI());
414 DBSerializer serializer =
415 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
416 Vertex v = serializer.createNewVertex(obj);
417 serializer.serializeToDb(obj, v, parser, obj.getURI(), "testing");
418 Vertex routeTargetOneV = traversal.V().has("global-route-target", "getTargetKeyNoLink").next();
419 Vertex routeTargetTwoV = traversal.V().has("global-route-target", "getTargetKeyNoLink2").next();
421 assertEquals("first route target put has linked", true,
422 routeTargetOneV.property(AAIProperties.LINKED).orElse(false));
423 assertEquals("second route target put does not have linked", false,
424 routeTargetTwoV.property(AAIProperties.LINKED).orElse(false));