Enhancements for the aai-common library
[aai/aai-common.git] / aai-core / src / test / java / org / onap / aai / introspection / sideeffect / DataLinkTest.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
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
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.aai.introspection.sideeffect;
22
23 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
24 import org.apache.tinkerpop.gremlin.structure.Graph;
25 import org.apache.tinkerpop.gremlin.structure.Vertex;
26 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
27 import org.janusgraph.core.Cardinality;
28 import org.janusgraph.core.JanusGraph;
29 import org.janusgraph.core.JanusGraphFactory;
30 import org.janusgraph.core.schema.JanusGraphManagement;
31 import org.junit.*;
32 import org.junit.rules.ExpectedException;
33 import org.junit.runner.RunWith;
34 import org.junit.runners.Parameterized;
35 import org.mockito.Mock;
36 import org.mockito.MockitoAnnotations;
37 import org.onap.aai.DataLinkSetup;
38 import org.onap.aai.db.props.AAIProperties;
39 import org.onap.aai.edges.enums.EdgeProperty;
40 import org.onap.aai.exceptions.AAIException;
41 import org.onap.aai.introspection.Introspector;
42 import org.onap.aai.introspection.Loader;
43 import org.onap.aai.introspection.ModelType;
44 import org.onap.aai.parsers.query.QueryParser;
45 import org.onap.aai.serialization.db.DBSerializer;
46 import org.onap.aai.serialization.engines.JanusGraphDBEngine;
47 import org.onap.aai.serialization.engines.QueryStyle;
48 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
49
50 import java.io.UnsupportedEncodingException;
51 import java.util.Arrays;
52 import java.util.Collection;
53 import java.util.List;
54 import java.util.UUID;
55
56 import static org.hamcrest.MatcherAssert.assertThat;
57 import static org.hamcrest.Matchers.is;
58 import static org.hamcrest.Matchers.not;
59 import static org.junit.Assert.*;
60 import static org.mockito.Mockito.spy;
61 import static org.mockito.Mockito.when;
62
63 @RunWith(value = Parameterized.class)
64 public class DataLinkTest extends DataLinkSetup {
65
66     private static JanusGraph graph;
67     private final static ModelType introspectorFactoryType = ModelType.MOXY;
68     private static Loader loader;
69     private static TransactionalGraphEngine dbEngine;
70     @Mock
71     private QueryParser parser;
72     @Mock
73     private Vertex self;
74     @Mock
75     private VertexProperty<String> prop;
76     @Rule
77     public ExpectedException thrown = ExpectedException.none();
78
79     @Parameterized.Parameter
80     public QueryStyle queryStyle;
81
82     @Parameterized.Parameters(name = "QueryStyle.{0}")
83     public static Collection<Object[]> data() {
84         return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}, {QueryStyle.TRAVERSAL_URI}});
85     }
86
87     @BeforeClass
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)
92             .make();
93         graphMgt.makePropertyKey(AAIProperties.LAST_MOD_TS).dataType(Long.class).cardinality(Cardinality.SINGLE)
94             .make();
95         graphMgt.commit();
96
97         graph.traversal()
98             .addV()
99             .property("aai-node-type", "vpn-binding")
100             .property("vpn-id", "addKey")
101             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/addKey")
102             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
103             .property(AAIProperties.CREATED_TS, 123)
104             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
105             .property(AAIProperties.RESOURCE_VERSION, "123")
106             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
107             .property(AAIProperties.LAST_MOD_TS, 333)
108             .as("v1")
109             .addV()
110             .property("aai-node-type", "vpn-binding")
111             .property("vpn-id", "modifyKey")
112             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/modifyKey")
113             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
114             .property(AAIProperties.CREATED_TS, 123)
115             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
116             .property(AAIProperties.RESOURCE_VERSION, "123")
117             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
118             .property(AAIProperties.LAST_MOD_TS, 333)
119             .as("v2")
120             .addV()
121             .property("aai-node-type", "route-target")
122             .property("global-route-target", "modifyTargetKey")
123             .property("route-target-role", "modifyRoleKey")
124             .property("linked", true)
125             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/modifyKey/route-targets/route-target/modifyTargetKey/modifyRoleKey")
126             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
127             .property(AAIProperties.CREATED_TS, 123)
128             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
129             .property(AAIProperties.RESOURCE_VERSION, "123")
130             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
131             .property(AAIProperties.LAST_MOD_TS, 333)
132             .as("v3")
133             .addE("org.onap.relationships.inventory.BelongsTo").to("v2").from("v3")
134             .property(EdgeProperty.CONTAINS.toString(), true)
135             .addV()
136             .property("aai-node-type", "vpn-binding")
137             .property("vpn-id", "deleteKey")
138             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/deleteKey")
139             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
140             .property(AAIProperties.CREATED_TS, 123)
141             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
142             .property(AAIProperties.RESOURCE_VERSION, "123")
143             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
144             .property(AAIProperties.LAST_MOD_TS, 333)
145             .as("v4")
146             .addV()
147             .property("aai-node-type", "route-target")
148             .property("global-route-target", "deleteTargetKey")
149             .property("route-target-role", "deleteRoleKey")
150             .property("linked", true)
151             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/deleteKey/route-targets/route-target/deleteTargetKey/deleteRoleKey")
152             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
153             .property(AAIProperties.CREATED_TS, 123)
154             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
155             .property(AAIProperties.RESOURCE_VERSION, "123")
156             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
157             .property(AAIProperties.LAST_MOD_TS, 333)
158             .as("v5")
159             .addE("org.onap.relationships.inventory.BelongsTo").to("v4").from("v5")
160             .property(EdgeProperty.CONTAINS.toString(), true)
161             .addV()
162             .property("aai-node-type", "vpn-binding")
163             .property("vpn-id", "getKey")
164             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKey")
165             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
166             .property(AAIProperties.CREATED_TS, 123)
167             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
168             .property(AAIProperties.RESOURCE_VERSION, "123")
169             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
170             .property(AAIProperties.LAST_MOD_TS, 333)
171             .as("v6")
172             .addV()
173             .property("aai-node-type", "route-target")
174             .property("global-route-target", "getTargetKey")
175             .property("route-target-role", "getRoleKey")
176             .property("linked", true)
177             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKey/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink")
178             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
179             .property(AAIProperties.CREATED_TS, 123)
180             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
181             .property(AAIProperties.RESOURCE_VERSION, "123")
182             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
183             .property(AAIProperties.LAST_MOD_TS, 333)
184             .as("v7")
185             .addE("org.onap.relationships.inventory.BelongsTo").to("v6").from("v7")
186             .property(EdgeProperty.CONTAINS.toString(), true)
187             .addV()
188             .property("aai-node-type", "vpn-binding")
189             .property("vpn-id", "getKeyNoLink")
190             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKeyNoLink")
191             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
192             .property(AAIProperties.CREATED_TS, 123)
193             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
194             .property(AAIProperties.RESOURCE_VERSION, "123")
195             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
196             .property(AAIProperties.LAST_MOD_TS, 333)
197             .as("v8")
198             .addV()
199             .property("aai-node-type", "route-target")
200             .property("global-route-target", "getTargetKeyNoLink")
201             .property("route-target-role", "getRoleKeyNoLink")
202             .property(AAIProperties.AAI_URI, "/network/vpn-bindings/vpn-binding/getKeyNoLink/route-targets/route-target/getTargetKeyNoLink/getRoleKeyNoLink")
203             .property(AAIProperties.AAI_UUID, UUID.randomUUID().toString())
204             .property(AAIProperties.CREATED_TS, 123)
205             .property(AAIProperties.SOURCE_OF_TRUTH, "sot")
206             .property(AAIProperties.RESOURCE_VERSION, "123")
207             .property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, "lmsot")
208             .property(AAIProperties.LAST_MOD_TS, 333)
209             .as("v9")
210             .addE("org.onap.relationships.inventory.BelongsTo").to("v8").from("v9")
211             .property(EdgeProperty.CONTAINS.toString(), true)
212                 .next();
213         graph.tx().commit();
214
215     }
216
217     @AfterClass
218     public static void tearDown() {
219         graph.tx().rollback();
220         graph.close();
221     }
222
223     @Before
224     public void initMock() {
225         loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, schemaVersions.getDefaultVersion());
226         MockitoAnnotations.initMocks(this);
227         dbEngine = new JanusGraphDBEngine(queryStyle, loader);
228     }
229
230     @Test
231     public void verifyCreationOfVertex() throws AAIException, UnsupportedEncodingException,
232             IllegalArgumentException, SecurityException {
233
234         final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
235         final Introspector obj = loader.introspectorFromName("vpn-binding");
236         obj.setValue("vpn-id", "addKey");
237         obj.setValue("global-route-target", "key1");
238         obj.setValue("route-target-role", "key2");
239         TransactionalGraphEngine spy = spy(dbEngine);
240         TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
241         Graph g = graph.newTransaction();
242         GraphTraversalSource traversal = g.traversal();
243         when(spy.asAdmin()).thenReturn(adminSpy);
244         when(adminSpy.getTraversalSource()).thenReturn(traversal);
245         when(spy.tx()).thenReturn(g);
246         when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
247         when(prop.orElse(null)).thenReturn(obj.getURI());
248         DBSerializer serializer =
249                 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
250         SideEffectRunner runner =
251                 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
252
253         runner.execute(obj, self);
254
255         assertTrue("route-target vertex found", traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "key1").has("route-target-role", "key2").has("linked", true).hasNext());
256         g.tx().rollback();
257
258     }
259
260     @Test
261     public void verifyModificationOfVertex() throws AAIException, UnsupportedEncodingException,
262             IllegalArgumentException, SecurityException {
263
264         final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
265         final Introspector obj = loader.introspectorFromName("vpn-binding");
266         obj.setValue("vpn-id", "modifyKey");
267         obj.setValue("global-route-target", "modifyTargetKey2");
268         obj.setValue("route-target-role", "modifyRoleKey2");
269         TransactionalGraphEngine spy = spy(dbEngine);
270         TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
271         Graph g = graph.newTransaction();
272         GraphTraversalSource traversal = g.traversal();
273
274         when(spy.asAdmin()).thenReturn(adminSpy);
275         when(adminSpy.getTraversalSource()).thenReturn(traversal);
276         when(spy.tx()).thenReturn(g);
277         when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
278         when(prop.orElse(null)).thenReturn(obj.getURI());
279         DBSerializer serializer =
280                 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
281         SideEffectRunner runner =
282                 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
283         runner.execute(obj, self);
284
285         assertThat("new route-target vertex found with/or without link",
286                 traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
287                         .has("global-route-target", "modifyTargetKey2").has("route-target-role", "modifyRoleKey2")
288                         .hasNext(),
289                 is(true));
290         assertThat("new route-target vertex found",
291                 traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
292                         .has("global-route-target", "modifyTargetKey2").has("route-target-role", "modifyRoleKey2")
293                         .has("linked", true).hasNext(),
294                 is(true));
295         assertThat("previous link removed",
296                 traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "modifyTargetKey")
297                         .has("route-target-role", "modifyRoleKey").has("linked").hasNext(),
298                 is(not(true)));
299         assertThat("previous vertex still exists", traversal.V().has(AAIProperties.NODE_TYPE, "route-target")
300                 .has("global-route-target", "modifyTargetKey").has("route-target-role", "modifyRoleKey").hasNext(),
301                 is(true));
302         g.tx().rollback();
303
304     }
305
306     @Test
307     public void verifyDeleteOfVertex() throws Exception {
308
309         final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
310         final Introspector obj = loader.introspectorFromName("vpn-binding");
311         obj.setValue("vpn-id", "deleteKey");
312         TransactionalGraphEngine spy = spy(dbEngine);
313         TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
314         Graph g = graph.newTransaction();
315         GraphTraversalSource traversal = g.traversal();
316         when(spy.asAdmin()).thenReturn(adminSpy);
317         when(adminSpy.getTraversalSource()).thenReturn(traversal);
318         when(adminSpy.getReadOnlyTraversalSource()).thenReturn(traversal);
319         when(spy.tx()).thenReturn(g);
320         when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
321         when(prop.orElse(null)).thenReturn(obj.getURI());
322         DBSerializer serializer =
323                 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
324         SideEffectRunner runner =
325                 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkWriter.class).build();
326
327         runner.execute(obj, self);
328
329         assertFalse("route-target vertex not found", traversal.V().has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "deleteTargetKey").has("route-target-role", "deleteRoleKey").has("linked", true).hasNext());
330
331         g.tx().rollback();
332
333     }
334
335     @Test
336     public void verifyPropertyPopulation() throws Exception {
337
338         final Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDepthVersion());
339         final Introspector obj = loader.introspectorFromName("vpn-binding");
340         obj.setValue("vpn-id", "getKey");
341         TransactionalGraphEngine spy = spy(dbEngine);
342         TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
343         Graph g = graph.newTransaction();
344         GraphTraversalSource traversal = g.traversal();
345         when(spy.asAdmin()).thenReturn(adminSpy);
346         when(adminSpy.getTraversalSource()).thenReturn(traversal);
347         when(spy.tx()).thenReturn(g);
348         when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
349         when(prop.orElse(null)).thenReturn(obj.getURI());
350         DBSerializer serializer =
351                 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
352         SideEffectRunner runner =
353                 new SideEffectRunner.Builder(spy, serializer).addSideEffect(DataLinkReader.class).build();
354
355         runner.execute(obj, self);
356
357         assertTrue("both properties have been populated in target object", obj.getValue("global-route-target").equals("getTargetKey") && obj.getValue("route-target-role").equals("getRoleKey"));
358         g.tx().rollback();
359
360     }
361
362     @Test
363     public void verifyPropertyPopulationWithV10OnlyPut() throws AAIException,
364             UnsupportedEncodingException, IllegalArgumentException, SecurityException {
365         final Introspector obj = loader.introspectorFromName("vpn-binding");
366         obj.setValue("vpn-id", "getKeyNoLink");
367         final Introspector routeTargets = loader.introspectorFromName("route-targets");
368         obj.setValue("route-targets", routeTargets.getUnderlyingObject());
369         List<Object> targets = routeTargets.getValue("route-target");
370         final Introspector routeTargetOne = loader.introspectorFromName("route-target");
371         routeTargetOne.setValue("global-route-target", "getTargetKeyNoLink");
372         routeTargetOne.setValue("route-target-role", "getRoleKeyNoLink");
373         targets.add(routeTargetOne.getUnderlyingObject());
374         final Introspector routeTargetTwo = loader.introspectorFromName("route-target");
375         routeTargetTwo.setValue("global-route-target", "getTargetKeyNoLink2");
376         routeTargetTwo.setValue("route-target-role", "getRoleKeyNoLink2");
377         targets.add(routeTargetTwo.getUnderlyingObject());
378         TransactionalGraphEngine spy = spy(dbEngine);
379         TransactionalGraphEngine.Admin adminSpy = spy(dbEngine.asAdmin());
380         Graph g = graph.newTransaction();
381         GraphTraversalSource traversal = g.traversal();
382         when(spy.tx()).thenReturn(g);
383         when(spy.asAdmin()).thenReturn(adminSpy);
384         when(adminSpy.getTraversalSource()).thenReturn(traversal);
385         when(spy.tx()).thenReturn(g);
386         when(parser.isDependent()).thenReturn(false);
387         when(self.<String>property(AAIProperties.AAI_URI)).thenReturn(prop);
388         when(prop.orElse(null)).thenReturn(obj.getURI());
389         DBSerializer serializer =
390                 new DBSerializer(schemaVersions.getDefaultVersion(), spy, introspectorFactoryType, "AAI_TEST");
391         Vertex v = serializer.createNewVertex(obj);
392         serializer.serializeToDb(obj, v, parser, obj.getURI(), "testing");
393         Vertex routeTargetOneV = traversal.V().has("global-route-target", "getTargetKeyNoLink").next();
394         Vertex routeTargetTwoV = traversal.V().has("global-route-target", "getTargetKeyNoLink2").next();
395
396         assertEquals("first route target put has linked", true,
397                 routeTargetOneV.property(AAIProperties.LINKED).orElse(false));
398         assertEquals("second route target put does not have linked", false,
399                 routeTargetTwoV.property(AAIProperties.LINKED).orElse(false));
400
401         g.tx().rollback();
402
403     }
404 }