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();
95 graph.traversal().addV().property("aai-node-type", "vpn-binding").property("vpn-id", "addKey")
96 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/addKey")
97 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
98 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
99 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
100 .as("v1").addV().property("aai-node-type", "vpn-binding").property("vpn-id", "modifyKey")
101 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/modifyKey")
102 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
103 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
104 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
105 .as("v2").addV().property("aai-node-type", "route-target")
106 .property("global-route-target", "modifyTargetKey").property("route-target-role", "modifyRoleKey")
107 .property("linked", true)
108 .property(AAIProperties.AAI_URI,
109 "/network/vpn-bindings/vpn-binding/modifyKey/route-targets/route-target/modifyTargetKey/modifyRoleKey")
110 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
111 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
112 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
113 .as("v3").addE("org.onap.relationships.inventory.BelongsTo").to("v2").from("v3")
114 .property(EdgeProperty.CONTAINS.toString(), true).addV().property("aai-node-type", "vpn-binding")
115 .property("vpn-id", "deleteKey")
116 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/deleteKey")
117 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
118 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
119 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
120 .as("v4").addV().property("aai-node-type", "route-target")
121 .property("global-route-target", "deleteTargetKey").property("route-target-role", "deleteRoleKey")
122 .property("linked", true)
123 .property(AAIProperties.AAI_URI,
124 "/network/vpn-bindings/vpn-binding/deleteKey/route-targets/route-target/deleteTargetKey/deleteRoleKey")
125 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
126 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
127 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
128 .as("v5").addE("org.onap.relationships.inventory.BelongsTo").to("v4").from("v5")
129 .property(EdgeProperty.CONTAINS.toString(), true).addV().property("aai-node-type", "vpn-binding")
130 .property("vpn-id", "getKey")
131 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKey")
132 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
133 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
134 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
135 .as("v6").addV().property("aai-node-type", "route-target")
136 .property("global-route-target", "getTargetKey").property("route-target-role", "getRoleKey")
137 .property("linked", true)
138 .property(AAIProperties.AAI_URI,
139 "/network/vpn-bindings/vpn-binding/getKey/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink")
140 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
141 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
142 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
143 .as("v7").addE("org.onap.relationships.inventory.BelongsTo").to("v6").from("v7")
144 .property(EdgeProperty.CONTAINS.toString(), true).addV().property("aai-node-type", "vpn-binding")
145 .property("vpn-id", "getKeyNoLink")
146 .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKeyNoLink")
147 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
148 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
149 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
150 .as("v8").addV().property("aai-node-type", "route-target")
151 .property("global-route-target", "getTargetKeyNoLink").property("route-target-role", "getRoleKeyNoLink")
152 .property(AAIProperties.AAI_URI,
153 "/network/vpn-bindings/vpn-binding/getKeyNoLink/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink")
154 .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()).property(AAIProperties.CREATED_TS, 123)
155 .property(AAIProperties.SOURCE_OF_TRUTH, "sot").property(AAIProperties.RESOURCE_VERSION, "123")
156 .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot").property(AAIProperties.LAST_MOD_TS, 333)
157 .as("v9").addE("org.onap.relationships.inventory.BelongsTo").to("v8").from("v9")
158 .property(EdgeProperty.CONTAINS.toString(), true).next();
164 public static void tearDown() {
165 graph.tx().rollback();
170 public void initMock() {
171 loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion());
172 MockitoAnnotations.initMocks(this);
173 dbEngine = new JanusGraphDBEngine(queryStyle, loader);
177 public void verifyCreationOfVertex()
178 throws AAIException, UnsupportedEncodingException, IllegalArgumentException, SecurityException {
180 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
181 final Introspector obj = loader.introspectorFromName("vpn-binding");
182 obj.setValue("vpn-id", "addKey");
183 obj.setValue("global-route-target", "key1");
184 obj.setValue("route-target-role", "key2");
185 TransactionalGraphEngine spy = spy(dbEngine);
186 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
187 Graph g = graph.newTransaction();
188 GraphTraversalSource traversal = g.traversal();
189 when(spy.asAdmin()).thenReturn(adminSpy);
190 when(adminSpy.getTraversalSource()).thenReturn(traversal);
191 when(spy.tx()).thenReturn(g);
192 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
193 when(prop.orElse(null)).thenReturn(obj.getURI());
194 DBSerializer serializer =
195 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
196 SideEffectRunner runner =
197 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
199 runner.execute(obj, self);
201 assertTrue("route-target vertex found", traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
202 .has("global-route-target", "key1").has("route-target-role", "key2").has("linked", true).hasNext());
208 public void verifyModificationOfVertex()
209 throws AAIException, UnsupportedEncodingException, IllegalArgumentException, SecurityException {
211 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
212 final Introspector obj = loader.introspectorFromName("vpn-binding");
213 obj.setValue("vpn-id", "modifyKey");
214 obj.setValue("global-route-target", "modifyTargetKey2");
215 obj.setValue("route-target-role", "modifyRoleKey2");
216 TransactionalGraphEngine spy = spy(dbEngine);
217 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
218 Graph g = graph.newTransaction();
219 GraphTraversalSource traversal = g.traversal();
221 when(spy.asAdmin()).thenReturn(adminSpy);
222 when(adminSpy.getTraversalSource()).thenReturn(traversal);
223 when(spy.tx()).thenReturn(g);
224 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
225 when(prop.orElse(null)).thenReturn(obj.getURI());
226 DBSerializer serializer =
227 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
228 SideEffectRunner runner =
229 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
230 runner.execute(obj, self);
232 assertThat("new route-target vertex found with/or without link",
233 traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
234 .has("global-route-target", "modifyTargetKey2").has("route-target-role", "modifyRoleKey2")
237 assertThat("new route-target vertex found",
238 traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
239 .has("global-route-target", "modifyTargetKey2").has("route-target-role", "modifyRoleKey2")
240 .has("linked", true).hasNext(),
242 assertThat("previous link removed",
243 traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "modifyTargetKey")
244 .has("route-target-role", "modifyRoleKey").has("linked").hasNext(),
246 assertThat("previous vertex still exists", traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
247 .has("global-route-target", "modifyTargetKey").has("route-target-role", "modifyRoleKey").hasNext(),
254 public void verifyDeleteOfVertex() throws Exception {
256 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
257 final Introspector obj = loader.introspectorFromName("vpn-binding");
258 obj.setValue("vpn-id", "deleteKey");
259 TransactionalGraphEngine spy = spy(dbEngine);
260 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
261 Graph g = graph.newTransaction();
262 GraphTraversalSource traversal = g.traversal();
263 when(spy.asAdmin()).thenReturn(adminSpy);
264 when(adminSpy.getTraversalSource()).thenReturn(traversal);
265 when(adminSpy.getReadOnlyTraversalSource()).thenReturn(traversal);
266 when(spy.tx()).thenReturn(g);
267 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
268 when(prop.orElse(null)).thenReturn(obj.getURI());
269 DBSerializer serializer =
270 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
271 SideEffectRunner runner =
272 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
274 runner.execute(obj, self);
276 assertFalse("route-target vertex not found",
277 traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "deleteTargetKey")
278 .has("route-target-role", "deleteRoleKey").has("linked", true).hasNext());
285 public void verifyPropertyPopulation() throws Exception {
287 final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
288 final Introspector obj = loader.introspectorFromName("vpn-binding");
289 obj.setValue("vpn-id", "getKey");
290 TransactionalGraphEngine spy = spy(dbEngine);
291 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
292 Graph g = graph.newTransaction();
293 GraphTraversalSource traversal = g.traversal();
294 when(spy.asAdmin()).thenReturn(adminSpy);
295 when(adminSpy.getTraversalSource()).thenReturn(traversal);
296 when(spy.tx()).thenReturn(g);
297 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
298 when(prop.orElse(null)).thenReturn(obj.getURI());
299 DBSerializer serializer =
300 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
301 SideEffectRunner runner =
302 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkReader.class).build();
304 runner.execute(obj, self);
306 assertTrue("both properties have been populated in target object",
307 obj.getValue("global-route-target").equals("getTargetKey")
308 && obj.getValue("route-target-role").equals("getRoleKey"));
314 public void verifyPropertyPopulationWithV10OnlyPut()
315 throws AAIException, UnsupportedEncodingException, IllegalArgumentException, SecurityException {
316 final Introspector obj = loader.introspectorFromName("vpn-binding");
317 obj.setValue("vpn-id", "getKeyNoLink");
318 final Introspector routeTargets = loader.introspectorFromName("route-targets");
319 obj.setValue("route-targets", routeTargets.getUnderlyingObject());
320 List<Object> targets = routeTargets.getValue("route-target");
321 final Introspector routeTargetOne = loader.introspectorFromName("route-target");
322 routeTargetOne.setValue("global-route-target", "getTargetKeyNoLink");
323 routeTargetOne.setValue("route-target-role", "getRoleKeyNoLink");
324 targets.add(routeTargetOne.getUnderlyingObject());
325 final Introspector routeTargetTwo = loader.introspectorFromName("route-target");
326 routeTargetTwo.setValue("global-route-target", "getTargetKeyNoLink2");
327 routeTargetTwo.setValue("route-target-role", "getRoleKeyNoLink2");
328 targets.add(routeTargetTwo.getUnderlyingObject());
329 TransactionalGraphEngine spy = spy(dbEngine);
330 TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
331 Graph g = graph.newTransaction();
332 GraphTraversalSource traversal = g.traversal();
333 when(spy.tx()).thenReturn(g);
334 when(spy.asAdmin()).thenReturn(adminSpy);
335 when(adminSpy.getTraversalSource()).thenReturn(traversal);
336 when(spy.tx()).thenReturn(g);
337 when(parser.isDependent()).thenReturn(false);
338 when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
339 when(prop.orElse(null)).thenReturn(obj.getURI());
340 DBSerializer serializer =
341 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
342 Vertex v = serializer.createNewVertex(obj);
343 serializer.serializeToDb(obj, v, parser, obj.getURI(), "testing");
344 Vertex routeTargetOneV = traversal.V().has("global-route-target", "getTargetKeyNoLink").next();
345 Vertex routeTargetTwoV = traversal.V().has("global-route-target", "getTargetKeyNoLink2").next();
347 assertEquals("first route target put has linked", true,
348 routeTargetOneV.property(AAIProperties.LINKED).orElse(false));
349 assertEquals("second route target put does not have linked", false,
350 routeTargetTwoV.property(AAIProperties.LINKED).orElse(false));