You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ke...@apache.org on 2023/10/27 16:40:05 UTC
(tinkerpop) 01/01: TINKERPOP-3010 Move TinkerTransactionGraph-specific tests.
This is an automated email from the ASF dual-hosted git repository.
kenhuuu pushed a commit to branch move-txn-tests
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 35d56d94652ab7f452d4f5b4d3fada919cfdfa11
Author: Ken Hu <10...@users.noreply.github.com>
AuthorDate: Fri Oct 27 00:27:43 2023 -0700
TINKERPOP-3010 Move TinkerTransactionGraph-specific tests.
---
CHANGELOG.asciidoc | 1 +
.../structure/TransactionMultiThreadedTest.java | 483 +--------------------
.../structure/TinkerTransactionGraphTest.java | 441 +++++++++++++++++++
3 files changed, 444 insertions(+), 481 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index bb91a6decc..42cdae12cc 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -46,6 +46,7 @@ This release also includes changes from <<release-3-6-6, 3.6.6>> and <<release-3
* Added `agent` parameter to `DriverRemoteConnection` options to allow a user-provided `http.Agent` implementation.
* Fixed deserialization of element properties for GraphBinary.
* Fixed bug in `union()` as a start step where the `Path` was including the starting dummy traverser.
+* Moved some TinkerGraph specific transaction tests from `TransactionMultiThreadedTest` to `TinkerTransactionGraphTest`
* Improved performance for Element comparison by comparing hashCode() prior to doing more expensive checks.
[[release-3-7.0]]
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionMultiThreadedTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionMultiThreadedTest.java
index 17f399e0f3..fa3de5cc06 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionMultiThreadedTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/TransactionMultiThreadedTest.java
@@ -21,19 +21,16 @@ package org.apache.tinkerpop.gremlin.structure;
import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
import org.apache.tinkerpop.gremlin.FeatureRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.util.TransactionException;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES;
-import static org.apache.tinkerpop.gremlin.structure.Graph.Features.EdgeFeatures.FEATURE_REMOVE_EDGES;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.ElementFeatures.FEATURE_ADD_PROPERTY;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.GraphFeatures.FEATURE_TRANSACTIONS;
-import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexFeatures.*;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES;
+import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexFeatures.FEATURE_REMOVE_VERTICES;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
/**
* Tests for graphs that has multithreaded access
@@ -117,46 +114,6 @@ public class TransactionMultiThreadedTest extends AbstractGremlinTest {
countElementsInNewThreadTx(g, 1, 0);
}
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_REMOVE_VERTICES)
- public void shouldHandleConcurrentVertexDelete() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- gtx.tx().commit();
-
- gtx.V(v1.id()).drop().iterate();
-
- // other tx try to remove same vertex
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
-
- gtx2.V(v1.id()).drop().iterate();
-
- // should be ok
- assertEquals(0, (long) gtx2.V().count().next());
- assertEquals(0, (long) gtx2.E().count().next());
-
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- // try do delete in initial tx
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
- assertEquals(0, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 0, 0);
- }
-
@Test
@FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
@FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
@@ -179,91 +136,6 @@ public class TransactionMultiThreadedTest extends AbstractGremlinTest {
assertEquals(2, gtx.V(v1.id()).values("test").next());
}
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_PROPERTY)
- public void shouldHandleConcurrentChangeForVertexProperty() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- gtx.tx().commit();
-
- // change test property
- gtx.V(v1.id()).property("test", 1).iterate();
-
- // change property in other tx
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.V(v1.id()).property("test", 2).iterate();
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- // should be only 1 vertex with updated property
- assertEquals(1L, (long) gtx.V().count().next());
- assertEquals(2, gtx.V(v1.id()).values("test").next());
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_PROPERTY)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_META_PROPERTIES)
- public void shouldHandleConcurrentChangeForVertexMetaProperty() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().property("test", 1).next();
- gtx.tx().commit();
-
- // change meta property
- gtx.V(v1.id()).properties("test").property("meta1", "tx1").iterate();
-
- // change same property in other tx
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.V(v1.id()).properties("test").property("meta2", "tx2").iterate();
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- try {
- gtx.tx().commit();
- //fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- // should be only 1 vertex with updated property
- assertEquals(1L, (long) gtx.V().count().next());
- assertEquals("tx2", gtx.V(v1.id()).properties("test").values("meta1", "meta2").next());
- }
-
- @Test(expected = IllegalArgumentException.class)
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_PROPERTY)
- public void shouldThrowExceptionWhenTryToAddVertexWithUsedId() {
- final GraphTraversalSource gtx = g.tx().begin();
-
- // add vertex
- final Vertex v1 = gtx.addV().next();
- gtx.tx().commit();
-
- // try to add vertex with same id
- gtx.addV().property(T.id, v1.id()).iterate();
- gtx.tx().commit();
- }
-
@Test
@FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
@FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
@@ -286,26 +158,6 @@ public class TransactionMultiThreadedTest extends AbstractGremlinTest {
countElementsInNewThreadTx(g, 0, 0);
}
- ///// transaction tests
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- public void shouldReopenClosedTransaction() {
- final GraphTraversalSource gtx = g.tx().begin();
- gtx.addV().iterate();
- gtx.tx().commit();
-
- gtx.addV().iterate();
- assertTrue(gtx.tx().isOpen());
- gtx.tx().commit();
-
- final GraphTraversalSource gtx2 = g.tx().begin();
- assertEquals(2L, (long) gtx2.V().count().next());
- }
-
- ///// Edge tests
-
@Test
@FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
@FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
@@ -363,337 +215,6 @@ public class TransactionMultiThreadedTest extends AbstractGremlinTest {
countElementsInNewThreadTx(g, 0, 0);
}
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ADD_EDGES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_REMOVE_EDGES)
- public void shouldDeleteEdgeOnCommit() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- final Vertex v2 = gtx.addV().next();
- gtx.addE("tests").from(v1).to(v2).next();
- gtx.tx().commit();
-
- assertEquals(2, (long) gtx.V().count().next());
- assertEquals(1, (long) gtx.E().count().next());
-
- gtx.E().hasLabel("tests").drop().iterate();
-
- assertEquals(2, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- // test count in other thread transaction
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- assertEquals(2L, (long) gtx2.V().count().next());
- assertEquals(1L, (long) gtx2.E().count().next());
- });
- thread.start();
- thread.join();
-
- gtx.tx().commit();
-
- assertEquals(2, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 2, 0);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ADD_EDGES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_REMOVE_EDGES)
- public void shouldHandleConcurrentDeleteEdge() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- final Vertex v2 = gtx.addV().next();
- gtx.addE("tests").from(v1).to(v2).next();
- gtx.tx().commit();
-
- assertEquals(2, (long) gtx.V().count().next());
- assertEquals(1, (long) gtx.E().count().next());
-
- gtx.E().hasLabel("tests").drop().iterate();
-
- assertEquals(2, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- // other tx try to remove same edge
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- assertEquals(2L, (long) gtx2.V().count().next());
- assertEquals(1L, (long) gtx2.E().count().next());
-
- // try to remove edge
- gtx2.E().hasLabel("tests").drop().iterate();
-
- // should be ok
- assertEquals(2, (long) gtx2.V().count().next());
- assertEquals(0, (long) gtx2.E().count().next());
-
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- // try do delete in initial tx
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- assertEquals(2, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 2, 0);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ADD_EDGES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ADD_PROPERTY)
- public void shouldHandleConcurrentChangeForProperty() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- final Vertex v2 = gtx.addV().next();
- final Edge edge = gtx.addE("tests").from(v1).to(v2).next();
- gtx.tx().commit();
-
- // change test property
- gtx.E(edge.id()).property("test", 1).iterate();
-
- // change property in other tx
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.E(edge.id()).property("test", 2).iterate();
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- // should be only 1 edge with updated property
- assertEquals(1L, (long) gtx.E(edge.id()).count().next());
- assertEquals(2, gtx.E(edge.id()).values("test").next());
- }
-
-
- //tx1 adds a property to v1, tx2 deletes v1
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_PROPERTY)
- public void shouldHandleAddingPropertyWhenOtherTxDeleteVertex() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- gtx.tx().commit();
-
- // tx1 try to add property
- gtx.V(v1.id()).property("test", 1).iterate();
-
- // tx2 in same time delete vertex used by tx1
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.V(v1.id()).drop().iterate();
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- assertEquals(0, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 0, 0);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_PROPERTY)
- public void shouldHandleAddingPropertyWhenOtherTxAttemptsDeleteThenRollsback() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- gtx.tx().commit();
-
- // tx1 try to add property
- gtx.V(v1.id()).property("test", 1).iterate();
-
- // tx2 in same time delete vertex used by tx1
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.V(v1.id()).drop().iterate();
- gtx2.tx().rollback();
- });
- thread.start();
- thread.join();
-
- gtx.tx().commit();
-
- assertEquals(1, (long) gtx.V().count().next());
- assertEquals(1, gtx.V(v1.id()).values("test").next());
-
- countElementsInNewThreadTx(g, 1, 0);
- }
-
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ADD_EDGES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ADD_PROPERTY)
- public void shouldHandleAddingPropertyWhenOtherTxDeleteEdge() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- final Vertex v2 = gtx.addV().next();
- final Edge edge = gtx.addE("tests").from(v1).to(v2).next();
- gtx.tx().commit();
-
- // tx1 try to add property
- gtx.E(edge.id()).property("test", 1).iterate();
-
- // tx2 in same time delete edge used by tx1
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.E(edge.id()).drop().iterate();
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- assertEquals(2, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 2, 0);
- }
-
- // tx1 adds an edge from v1 to v2, tx2 deletes v1 or v2
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_REMOVE_VERTICES)
- @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ADD_EDGES)
- public void shouldHandleAddingEdgeWhenOtherTxDeleteVertex() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
- final Vertex v2 = gtx.addV().next();
- gtx.tx().commit();
-
- // tx1 try to add Edge
- gtx.addE("test").from(v1).to(v2).iterate();
-
- // tx2 in same time delete one of vertices used by tx1
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.V(v1.id()).drop().iterate();
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- assertEquals(1, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 1, 0);
- }
-
- // tx1 adds a new vertex v1, tx2 adds the same vertex
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- public void shouldHandleAddingSameVertexInDifferentTx() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
-
- // tx2 in same time add vertex with same id
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.addV().property(T.id, v1.id()).iterate();
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- try {
- gtx.tx().commit();
- fail("should throw TransactionException");
- } catch (TransactionException e) {
-
- }
-
- assertEquals(1, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 1, 0);
- }
-
- // tx1 adds vertex v1, tx2 removes vertex v1
- @Test
- @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
- @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ADD_VERTICES)
- public void shouldHandleAddingVertexWhenOtherTxTryToDeleteSameVertex() throws InterruptedException {
- final GraphTraversalSource gtx = g.tx().begin();
-
- final Vertex v1 = gtx.addV().next();
-
- // tx2 in same time try to delete same vertex
- final Thread thread = new Thread(() -> {
- final GraphTraversalSource gtx2 = g.tx().begin();
- gtx2.V(v1.id()).drop().iterate();
-
- assertEquals(0, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
- gtx2.tx().commit();
- });
- thread.start();
- thread.join();
-
- gtx.tx().commit();
-
- assertEquals(1, (long) gtx.V().count().next());
- assertEquals(0, (long) gtx.E().count().next());
-
- countElementsInNewThreadTx(g, 1, 0);
- }
-
private void countElementsInNewThreadTx(final GraphTraversalSource g, final long verticesCount, final long edgesCount) throws InterruptedException {
final AtomicLong vCount = new AtomicLong(-1);
final AtomicLong eCount = new AtomicLong(-1);
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java
index 3ac5c30754..d92284a0cd 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java
@@ -34,6 +34,7 @@ import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class TinkerTransactionGraphTest {
@@ -971,4 +972,444 @@ public class TinkerTransactionGraphTest {
assertEquals(1, gtx2Read.get());
assertEquals(2, (long) gtx.E().values("a").next());
}
+
+ @Test
+ public void shouldHandleAddingPropertyWhenOtherTxDeleteEdge() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ final Vertex v2 = gtx.addV().next();
+ final Edge edge = gtx.addE("tests").from(v1).to(v2).next();
+ gtx.tx().commit();
+
+ // tx1 try to add property
+ gtx.E(edge.id()).property("test", 1).iterate();
+
+ // tx2 in same time delete edge used by tx1
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.E(edge.id()).drop().iterate();
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ assertEquals(2, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 2, 0);
+ }
+
+ //tx1 adds a property to v1, tx2 deletes v1
+ @Test
+ public void shouldHandleAddingPropertyWhenOtherTxDeleteVertex() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ gtx.tx().commit();
+
+ // tx1 try to add property
+ gtx.V(v1.id()).property("test", 1).iterate();
+
+ // tx2 in same time delete vertex used by tx1
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.V(v1.id()).drop().iterate();
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ assertEquals(0, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 0, 0);
+ }
+
+ @Test
+ public void shouldDeleteEdgeOnCommit() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ final Vertex v2 = gtx.addV().next();
+ gtx.addE("tests").from(v1).to(v2).next();
+ gtx.tx().commit();
+
+ assertEquals(2, (long) gtx.V().count().next());
+ assertEquals(1, (long) gtx.E().count().next());
+
+ gtx.E().hasLabel("tests").drop().iterate();
+
+ assertEquals(2, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ // test count in other thread transaction
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ assertEquals(2L, (long) gtx2.V().count().next());
+ assertEquals(1L, (long) gtx2.E().count().next());
+ });
+ thread.start();
+ thread.join();
+
+ gtx.tx().commit();
+
+ assertEquals(2, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 2, 0);
+ }
+
+ @Test
+ public void shouldHandleConcurrentChangeForProperty() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ final Vertex v2 = gtx.addV().next();
+ final Edge edge = gtx.addE("tests").from(v1).to(v2).next();
+ gtx.tx().commit();
+
+ // change test property
+ gtx.E(edge.id()).property("test", 1).iterate();
+
+ // change property in other tx
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.E(edge.id()).property("test", 2).iterate();
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ // should be only 1 edge with updated property
+ assertEquals(1L, (long) gtx.E(edge.id()).count().next());
+ assertEquals(2, gtx.E(edge.id()).values("test").next());
+ }
+
+ // tx1 adds an edge from v1 to v2, tx2 deletes v1 or v2
+ @Test
+ public void shouldHandleAddingEdgeWhenOtherTxDeleteVertex() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ final Vertex v2 = gtx.addV().next();
+ gtx.tx().commit();
+
+ // tx1 try to add Edge
+ gtx.addE("test").from(v1).to(v2).iterate();
+
+ // tx2 in same time delete one of vertices used by tx1
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.V(v1.id()).drop().iterate();
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ assertEquals(1, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 1, 0);
+ }
+
+ @Test
+ public void shouldHandleConcurrentChangeForVertexProperty() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ gtx.tx().commit();
+
+ // change test property
+ gtx.V(v1.id()).property("test", 1).iterate();
+
+ // change property in other tx
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.V(v1.id()).property("test", 2).iterate();
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ // should be only 1 vertex with updated property
+ assertEquals(1L, (long) gtx.V().count().next());
+ assertEquals(2, gtx.V(v1.id()).values("test").next());
+ }
+
+ @Test
+ public void shouldHandleConcurrentDeleteEdge() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ final Vertex v2 = gtx.addV().next();
+ gtx.addE("tests").from(v1).to(v2).next();
+ gtx.tx().commit();
+
+ assertEquals(2, (long) gtx.V().count().next());
+ assertEquals(1, (long) gtx.E().count().next());
+
+ gtx.E().hasLabel("tests").drop().iterate();
+
+ assertEquals(2, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ // other tx try to remove same edge
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ assertEquals(2L, (long) gtx2.V().count().next());
+ assertEquals(1L, (long) gtx2.E().count().next());
+
+ // try to remove edge
+ gtx2.E().hasLabel("tests").drop().iterate();
+
+ // should be ok
+ assertEquals(2, (long) gtx2.V().count().next());
+ assertEquals(0, (long) gtx2.E().count().next());
+
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ // try do delete in initial tx
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ assertEquals(2, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 2, 0);
+ }
+
+ // tx1 adds a new vertex v1, tx2 adds the same vertex
+ @Test
+ public void shouldHandleAddingSameVertexInDifferentTx() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+
+ // tx2 in same time add vertex with same id
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.addV().property(T.id, v1.id()).iterate();
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ assertEquals(1, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 1, 0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionWhenTryToAddVertexWithUsedId() {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ // add vertex
+ final Vertex v1 = gtx.addV().next();
+ gtx.tx().commit();
+
+ // try to add vertex with same id
+ gtx.addV().property(T.id, v1.id()).iterate();
+ gtx.tx().commit();
+ }
+
+ @Test
+ public void shouldHandleConcurrentVertexDelete() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ gtx.tx().commit();
+
+ gtx.V(v1.id()).drop().iterate();
+
+ // other tx try to remove same vertex
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+
+ gtx2.V(v1.id()).drop().iterate();
+
+ // should be ok
+ assertEquals(0, (long) gtx2.V().count().next());
+ assertEquals(0, (long) gtx2.E().count().next());
+
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ // try do delete in initial tx
+ try {
+ gtx.tx().commit();
+ fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+ assertEquals(0, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 0, 0);
+ }
+
+ @Test
+ public void shouldHandleConcurrentChangeForVertexMetaProperty() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().property("test", 1).next();
+ gtx.tx().commit();
+
+ // change meta property
+ gtx.V(v1.id()).properties("test").property("meta1", "tx1").iterate();
+
+ // change same property in other tx
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.V(v1.id()).properties("test").property("meta2", "tx2").iterate();
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ try {
+ gtx.tx().commit();
+ //fail("should throw TransactionException");
+ } catch (TransactionException e) {
+
+ }
+
+ // should be only 1 vertex with updated property
+ assertEquals(1L, (long) gtx.V().count().next());
+ assertEquals("tx2", gtx.V(v1.id()).properties("test").values("meta1", "meta2").next());
+ }
+
+ @Test
+ public void shouldReopenClosedTransaction() {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+ gtx.addV().iterate();
+ gtx.tx().commit();
+
+ gtx.addV().iterate();
+ assertTrue(gtx.tx().isOpen());
+ gtx.tx().commit();
+
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ assertEquals(2L, (long) gtx2.V().count().next());
+ }
+
+ @Test
+ public void shouldHandleAddingPropertyWhenOtherTxAttemptsDeleteThenRollsback() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+ gtx.tx().commit();
+
+ // tx1 try to add property
+ gtx.V(v1.id()).property("test", 1).iterate();
+
+ // tx2 in same time delete vertex used by tx1
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.V(v1.id()).drop().iterate();
+ gtx2.tx().rollback();
+ });
+ thread.start();
+ thread.join();
+
+ gtx.tx().commit();
+
+ assertEquals(1, (long) gtx.V().count().next());
+ assertEquals(1, gtx.V(v1.id()).values("test").next());
+
+ countElementsInNewThreadTx(g, 1, 0);
+ }
+
+ // tx1 adds vertex v1, tx2 removes vertex v1
+ @Test
+ public void shouldHandleAddingVertexWhenOtherTxTryToDeleteSameVertex() throws InterruptedException {
+ final TinkerTransactionGraph g = TinkerTransactionGraph.open();
+ final GraphTraversalSource gtx = g.tx().begin();
+
+ final Vertex v1 = gtx.addV().next();
+
+ // tx2 in same time try to delete same vertex
+ final Thread thread = new Thread(() -> {
+ final GraphTraversalSource gtx2 = g.tx().begin();
+ gtx2.V(v1.id()).drop().iterate();
+
+ assertEquals(0, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+ gtx2.tx().commit();
+ });
+ thread.start();
+ thread.join();
+
+ gtx.tx().commit();
+
+ assertEquals(1, (long) gtx.V().count().next());
+ assertEquals(0, (long) gtx.E().count().next());
+
+ countElementsInNewThreadTx(g, 1, 0);
+ }
}