Update license date and text
[aai/champ.git] / champ-lib / champ-titan / src / test / java / org / onap / aai / champtitan / core / ChampTransactionTest.java
1 /**
2  * ============LICENSE_START==========================================
3  * org.onap.aai
4  * ===================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ===================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  */
21 package org.onap.aai.champtitan.core;
22
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.util.Optional;
28 import java.util.concurrent.CountDownLatch;
29
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.onap.aai.champcore.ChampTransaction;
33 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
34 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
35 import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
36 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
37 import org.onap.aai.champcore.exceptions.ChampTransactionException;
38 import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
39 import org.onap.aai.champcore.model.ChampObject;
40 import org.onap.aai.champcore.model.ChampRelationship;
41 import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl;
42
43 public class ChampTransactionTest {
44
45   public TitanChampGraphImpl graph = null;
46   public CountDownLatch latch = new CountDownLatch(2);
47   public ChampObject[] storedVertices = new ChampObject[2];
48
49   
50   @Before
51   public void setup() {
52     graph = new TitanChampGraphImpl.Builder("TransactionTestGraph")
53       .property("storage.backend", "inmemory")
54       .build();
55   }
56   
57   
58   /**
59    * This test validates that multiple CRUD operations can be performed against vertices within
60    * the same transactional context and that, once the transaction is committed, the final 
61    * state of the vertices reflects the sum of all of the operations performed within the
62    * transaction.
63    * 
64    * @throws ChampMarshallingException
65    * @throws ChampSchemaViolationException
66    * @throws ChampObjectNotExistsException
67    * @throws ChampUnmarshallingException
68    * @throws ChampTransactionException 
69    */
70   @Test
71   public void champObjectSingleTxTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampTransactionException {
72
73     ChampObject v1 = ChampObject.create()
74         .ofType("foo")
75         .withoutKey()
76         .withProperty("property1", "value1")
77         .withProperty("property2", "value2")
78         .build();
79     
80     ChampObject v2 = ChampObject.create()
81         .ofType("foo")
82         .withoutKey()
83         .withProperty("property3", "value3")
84         .withProperty("property4", "value4")
85         .build();
86     
87     ChampObject v3 = ChampObject.create()
88         .ofType("foo")
89         .withoutKey()
90         .withProperty("property5", "value5")
91         .withProperty("property6", "value6")
92         .build();
93     
94     ChampObject v4 = ChampObject.create()
95         .ofType("foo")
96         .withoutKey()
97         .withProperty("property7", "value7")
98         .withProperty("property8", "value8")
99         .build();
100     
101     
102     // Open a transaction with the graph data store.
103     ChampTransaction tx = graph.openTransaction();
104     
105       // Create all of our vertices.
106       ChampObject storedV1 = graph.storeObject(v1, Optional.of(tx));
107       ChampObject storedV2 = graph.storeObject(v2, Optional.of(tx));
108       ChampObject storedV3 = graph.storeObject(v3, Optional.of(tx));
109       ChampObject storedV4 = graph.storeObject(v4, Optional.of(tx));
110     
111       // Now, within the same transactional context, do a replacement against one of the 
112       // vertices that we just created.
113       ChampObject replacedV2 = graph.replaceObject(ChampObject.create()
114                                                        .ofType("foo")
115                                                        .withKey(storedV2.getKey().get())
116                                                        .withProperty("replacedProperty3", "replacedValue3")
117                                                        .withProperty("replacedProperty4", "replacedValue4")
118                                                        .build(), 
119                                                    Optional.of(tx));
120       
121       // Within the same transactional context, do an update against one of the vertices
122       // that we just created.
123       final ChampObject updatedV3 = graph.storeObject(ChampObject.create()
124                                                         .from(storedV3)
125                                                         .withKey(storedV3.getKey().get())
126                                                         .withProperty("updatedProperty", "updatedValue")
127                                                         .build(), Optional.of(tx));
128       
129       // Within the same transactional context, delete one of the vertices that we just
130       // created.
131       graph.deleteObject(storedV4.getKey().get(), Optional.of(tx));
132       
133     // Finally, commit our transaction.
134     tx.commit();
135     
136     tx = graph.openTransaction();
137     
138       Optional<ChampObject> retrievedV1 = graph.retrieveObject(storedV1.getKey().get(), Optional.of(tx));
139       assertTrue(retrievedV1.isPresent());
140       assertTrue(retrievedV1.get().getProperty("property1").get().equals("value1"));
141       assertTrue(retrievedV1.get().getProperty("property2").get().equals("value2"));
142
143       
144       Optional<ChampObject> retrievedV2 = graph.retrieveObject(storedV2.getKey().get(), Optional.of(tx));
145       assertTrue(retrievedV2.isPresent());
146       assertTrue(retrievedV2.get().getProperty("replacedProperty3").get().equals("replacedValue3"));
147       assertTrue(retrievedV2.get().getProperty("replacedProperty4").get().equals("replacedValue4"));
148       assertFalse(retrievedV2.get().getProperty("value3").isPresent());
149       assertFalse(retrievedV2.get().getProperty("value4").isPresent());
150       
151       Optional<ChampObject> retrievedV3 = graph.retrieveObject(storedV3.getKey().get(), Optional.of(tx));
152       assertTrue(retrievedV3.isPresent());
153       assertTrue(retrievedV3.get().getProperty("property5").get().equals("value5"));
154       assertTrue(retrievedV3.get().getProperty("property6").get().equals("value6"));
155       assertTrue(retrievedV3.get().getProperty("updatedProperty").get().equals("updatedValue"));
156
157       
158       Optional<ChampObject> retrievedV4 = graph.retrieveObject(storedV4.getKey().get(), Optional.of(tx));
159       assertFalse("Deleted vertex should not be present in graph", retrievedV4.isPresent());
160       
161     tx.commit();
162   }
163   
164
165   /**
166    * This test validates that multiple threads can each open their own transactions with the 
167    * graph data store, and that there is no leakage between each thread's transactions.
168    * 
169    * @throws ChampMarshallingException
170    * @throws ChampSchemaViolationException
171    * @throws ChampObjectNotExistsException
172    * @throws ChampUnmarshallingException
173    * @throws ChampTransactionException 
174    */
175   @Test
176   public void multipleTransactionTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampTransactionException {
177     
178     ChampObject v1 = ChampObject.create()
179         .ofType("foo")
180         .withoutKey()
181         .withProperty("property1", "value1")
182         .withProperty("property2", "value2")
183         .build();
184     
185     ChampObject v2 = ChampObject.create()
186         .ofType("bar")
187         .withoutKey()
188         .withProperty("property3", "value3")
189         .withProperty("property4", "value4")
190         .build();
191        
192     // Instantiate and start our two transactional worker threads...
193     Thread thread1 = new Thread(new VertexWriter(v1, 0));
194     Thread thread2 = new Thread(new VertexWriter(v2, 1));
195     thread1.start();
196     thread2.start();
197     
198     // and wait for the threads to complete.
199     try {
200       thread1.join();
201       thread2.join();
202       
203     } catch (InterruptedException e) { }
204         
205     // Now that all of our data has been committed, let's open a new transaction
206     // and verify that all of our vertices can be retrieved.
207     ChampTransaction tx3 = graph.openTransaction();
208
209     Optional<ChampObject> retrievedV1 = graph.retrieveObject(storedVertices[0].getKey().get(), Optional.of(tx3));
210     assertTrue(retrievedV1.isPresent());
211     Optional<ChampObject> retrievedV2 = graph.retrieveObject(storedVertices[1].getKey().get(), Optional.of(tx3));
212     assertTrue(retrievedV2.isPresent());
213     
214     tx3.commit();
215   }
216
217   
218   /**
219    * This method validates that edges can be successfully created within a single transaction.
220    * 
221    * @throws ChampMarshallingException
222    * @throws ChampSchemaViolationException
223    * @throws ChampObjectNotExistsException
224    * @throws ChampUnmarshallingException
225    * @throws ChampRelationshipNotExistsException
226    * @throws ChampTransactionException 
227    */
228   @Test
229   public void edgeTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampRelationshipNotExistsException, ChampTransactionException {
230     
231     // Create the source and target vertices for our edge.
232     final ChampObject source = ChampObject.create()
233         .ofType("foo")
234         .withoutKey()
235         .withProperty("property1", "value1")
236         .build();
237
238     final ChampObject target = ChampObject.create()
239         .ofType("foo")
240         .withoutKey()
241         .build();
242
243     // Open a transaction with the graph data store.
244     ChampTransaction tx = graph.openTransaction();
245     
246       // Now, create our vertices.
247       ChampObject storedSource = graph.storeObject(source, Optional.of(tx));
248       ChampObject storedTarget = graph.storeObject(target, Optional.of(tx));
249       
250       // Create the edge between the vertices.
251       ChampRelationship relationship = new ChampRelationship.Builder(storedSource, storedTarget, "relationship")
252           .property("property-1", "value-1")
253           .property("property-2", 3)
254           .build();
255       ChampRelationship storedRelationship = graph.storeRelationship(relationship, Optional.of(tx));
256       
257       // Validate that we can read back the edge within the transactional context.
258       Optional<ChampRelationship> retrievedRelationship = graph.retrieveRelationship(storedRelationship.getKey().get(), Optional.of(tx));
259       assertTrue("Failed to retrieve stored relationship", retrievedRelationship.isPresent());
260       
261     // Commit our transaction.
262     graph.commitTransaction(tx);
263     
264     // Now, open a new transaction.
265     tx = graph.openTransaction();
266     
267       // Now, read back the edge that we just created again, validating that it was
268       // successfully committed to the graph.
269       retrievedRelationship = graph.retrieveRelationship(storedRelationship.getKey().get(), Optional.of(tx));
270       assertTrue("Failed to retrieve stored relationship", retrievedRelationship.isPresent());
271
272     graph.commitTransaction(tx);
273   }
274   
275   private class VertexWriter implements Runnable {
276     
277     ChampObject vertex;
278     int         index;
279     
280     public VertexWriter(ChampObject vertex, int index) {
281       this.vertex = vertex;
282       this.index  = index;
283     }
284     
285     public void run() {
286       
287       ChampTransaction tx=null;
288       try {
289         
290         // Open a threaded transaction to do some work in.
291         tx = graph.openTransaction();
292         
293         // Now store one of our two vertices within the context of this transaction.
294         storedVertices[index] = graph.storeObject(vertex, Optional.of(tx));
295         
296         // Use our latch to indicate that we are done creating vertices, and wait for
297         // the other thread to do the same.          
298         latch.countDown();
299         latch.await();
300         
301         // Validate that the vertex we created is visible to us in the graph, but the
302         // one that the other thread created is not.          
303         Optional<ChampObject> retrievedV2 = graph.retrieveObject(storedVertices[index].getKey().get(), Optional.of(tx));
304         assertTrue(retrievedV2.isPresent());
305         Optional<ChampObject> retrievedV1 = graph.retrieveObject(storedVertices[(index+1)%2].getKey().get(), Optional.of(tx));
306         assertFalse(retrievedV1.isPresent());
307                 
308       } catch (InterruptedException | 
309                ChampUnmarshallingException | 
310                ChampMarshallingException | 
311                ChampSchemaViolationException | 
312                ChampObjectNotExistsException | ChampTransactionException e) {
313         
314         fail("Thread failed to interact with graph due to " + e.getMessage());
315       
316       } finally {
317         
318         try {
319           Thread.sleep(index * 500);
320         } catch (InterruptedException e) {
321           // TODO Auto-generated catch block
322           e.printStackTrace();
323         }
324         // Now, commit our transaction and bail...          
325         try {
326           graph.commitTransaction(tx);
327         } catch (ChampTransactionException e) {
328
329         }
330       }
331     }
332   };
333 }
334