2 * ============LICENSE_START==========================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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============================================
21 package org.onap.aai.champtitan.core;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
27 import java.util.Optional;
28 import java.util.concurrent.CountDownLatch;
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;
43 public class ChampTransactionTest {
45 public TitanChampGraphImpl graph = null;
46 public CountDownLatch latch = new CountDownLatch(2);
47 public ChampObject[] storedVertices = new ChampObject[2];
52 graph = new TitanChampGraphImpl.Builder("TransactionTestGraph")
53 .property("storage.backend", "inmemory")
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
64 * @throws ChampMarshallingException
65 * @throws ChampSchemaViolationException
66 * @throws ChampObjectNotExistsException
67 * @throws ChampUnmarshallingException
68 * @throws ChampTransactionException
71 public void champObjectSingleTxTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampTransactionException {
73 ChampObject v1 = ChampObject.create()
76 .withProperty("property1", "value1")
77 .withProperty("property2", "value2")
80 ChampObject v2 = ChampObject.create()
83 .withProperty("property3", "value3")
84 .withProperty("property4", "value4")
87 ChampObject v3 = ChampObject.create()
90 .withProperty("property5", "value5")
91 .withProperty("property6", "value6")
94 ChampObject v4 = ChampObject.create()
97 .withProperty("property7", "value7")
98 .withProperty("property8", "value8")
102 // Open a transaction with the graph data store.
103 ChampTransaction tx = graph.openTransaction();
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));
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()
115 .withKey(storedV2.getKey().get())
116 .withProperty("replacedProperty3", "replacedValue3")
117 .withProperty("replacedProperty4", "replacedValue4")
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()
125 .withKey(storedV3.getKey().get())
126 .withProperty("updatedProperty", "updatedValue")
127 .build(), Optional.of(tx));
129 // Within the same transactional context, delete one of the vertices that we just
131 graph.deleteObject(storedV4.getKey().get(), Optional.of(tx));
133 // Finally, commit our transaction.
136 tx = graph.openTransaction();
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"));
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());
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"));
158 Optional<ChampObject> retrievedV4 = graph.retrieveObject(storedV4.getKey().get(), Optional.of(tx));
159 assertFalse("Deleted vertex should not be present in graph", retrievedV4.isPresent());
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.
169 * @throws ChampMarshallingException
170 * @throws ChampSchemaViolationException
171 * @throws ChampObjectNotExistsException
172 * @throws ChampUnmarshallingException
173 * @throws ChampTransactionException
176 public void multipleTransactionTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampTransactionException {
178 ChampObject v1 = ChampObject.create()
181 .withProperty("property1", "value1")
182 .withProperty("property2", "value2")
185 ChampObject v2 = ChampObject.create()
188 .withProperty("property3", "value3")
189 .withProperty("property4", "value4")
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));
198 // and wait for the threads to complete.
203 } catch (InterruptedException e) { }
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();
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());
219 * This method validates that edges can be successfully created within a single transaction.
221 * @throws ChampMarshallingException
222 * @throws ChampSchemaViolationException
223 * @throws ChampObjectNotExistsException
224 * @throws ChampUnmarshallingException
225 * @throws ChampRelationshipNotExistsException
226 * @throws ChampTransactionException
229 public void edgeTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampRelationshipNotExistsException, ChampTransactionException {
231 // Create the source and target vertices for our edge.
232 final ChampObject source = ChampObject.create()
235 .withProperty("property1", "value1")
238 final ChampObject target = ChampObject.create()
243 // Open a transaction with the graph data store.
244 ChampTransaction tx = graph.openTransaction();
246 // Now, create our vertices.
247 ChampObject storedSource = graph.storeObject(source, Optional.of(tx));
248 ChampObject storedTarget = graph.storeObject(target, Optional.of(tx));
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)
255 ChampRelationship storedRelationship = graph.storeRelationship(relationship, Optional.of(tx));
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());
261 // Commit our transaction.
262 graph.commitTransaction(tx);
264 // Now, open a new transaction.
265 tx = graph.openTransaction();
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());
272 graph.commitTransaction(tx);
275 private class VertexWriter implements Runnable {
280 public VertexWriter(ChampObject vertex, int index) {
281 this.vertex = vertex;
287 ChampTransaction tx=null;
290 // Open a threaded transaction to do some work in.
291 tx = graph.openTransaction();
293 // Now store one of our two vertices within the context of this transaction.
294 storedVertices[index] = graph.storeObject(vertex, Optional.of(tx));
296 // Use our latch to indicate that we are done creating vertices, and wait for
297 // the other thread to do the same.
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());
308 } catch (InterruptedException |
309 ChampUnmarshallingException |
310 ChampMarshallingException |
311 ChampSchemaViolationException |
312 ChampObjectNotExistsException | ChampTransactionException e) {
314 fail("Thread failed to interact with graph due to " + e.getMessage());
319 Thread.sleep(index * 500);
320 } catch (InterruptedException e) {
321 // TODO Auto-generated catch block
324 // Now, commit our transaction and bail...
326 graph.commitTransaction(tx);
327 } catch (ChampTransactionException e) {