jena-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a...@apache.org
Subject [15/34] jena git commit: Testing for DatasetGraphWithLock
Date Sat, 06 Feb 2016 15:51:04 GMT
Testing for DatasetGraphWithLock

* Transactions, with and without abort support.
* Put concurrnecy/transaction tests in transaction test area.
* Fix issues arising.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/03ec3e97
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/03ec3e97
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/03ec3e97

Branch: refs/heads/master
Commit: 03ec3e9779f2a60f8789a408c72bb8df57261f48
Parents: d14a8c7
Author: Andy Seaborne <andy@apache.org>
Authored: Thu Feb 4 18:44:08 2016 +0000
Committer: Andy Seaborne <andy@apache.org>
Committed: Fri Feb 5 19:14:33 2016 +0000

----------------------------------------------------------------------
 .../jena/sparql/core/TransactionalMRSW.java     |   6 +-
 .../sparql/core/assembler/AssemblerUtils.java   |   1 -
 .../sparql/core/TestDatasetGraphWithLock.java   |  84 +---
 .../TestDatasetGraphInMemoryTransactions.java   |   4 +-
 .../transaction/AbstractTestTransaction.java    | 314 --------------
 .../AbstractTestTransactionLifecycle.java       | 418 +++++++++++++++++++
 .../jena/sparql/transaction/TS_Transaction.java |   3 +-
 .../transaction/TestTransactionDSGWithLock.java |  49 +++
 .../TestTransactionDSGWithLockWithAbort.java    |  41 ++
 .../sparql/transaction/TestTransactionMem.java  |  48 ---
 .../tdb/transaction/TestTransactionTDB.java     |   4 +-
 11 files changed, 518 insertions(+), 454 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMRSW.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMRSW.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMRSW.java
index 580453b..56420d3 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMRSW.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/TransactionalMRSW.java
@@ -66,8 +66,8 @@ public class TransactionalMRSW implements Transactional {
 
     @Override
     public void abort() {
-        if ( isTransactionType(ReadWrite.WRITE) )
-            error("Transactional.abort()") ;
+//        if ( isTransactionType(ReadWrite.WRITE) )
+//            error("Transactional.abort()") ;
         endOnce() ;
     }
 
@@ -87,7 +87,7 @@ public class TransactionalMRSW implements Transactional {
     @Override
     public void end() {
         if ( isTransactionType(ReadWrite.WRITE) )
-            error("Write tranasction - no commit or abort before end()") ;
+            error("Write transaction - no commit or abort before end()") ;
         endOnce() ;
     }
 

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
index 0378867..39c29ba 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
@@ -59,7 +59,6 @@ public class AssemblerUtils
         // Wire in the extension assemblers (extensions relative to the Jena assembler framework)
         registerDataset(DatasetAssembler.getType(),         new DatasetAssembler()) ;
         registerDataset(InMemDatasetAssembler.getType(),    new InMemDatasetAssembler())
;
-        registerDataset(DatasetNullAssembler.getType(),     new DatasetNullAssembler()) ;
     }
     
     private static Model modelExtras = ModelFactory.createDefaultModel() ;

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java
b/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java
index 4ff734e..0a3b0a6 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/core/TestDatasetGraphWithLock.java
@@ -18,95 +18,13 @@
 
 package org.apache.jena.sparql.core;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.* ;
-import java.util.concurrent.atomic.AtomicLong ;
-
-import org.apache.jena.atlas.lib.Lib ;
 import org.apache.jena.query.Dataset ;
 import org.apache.jena.query.DatasetFactory ;
-import org.apache.jena.query.ReadWrite ;
-import org.junit.Assert;
-import org.junit.Test;
 
+/** Non-transaction part of DatasetGraphWithLock testing */
 public class TestDatasetGraphWithLock extends AbstractTestDataset {
-
     @Override
     protected Dataset createDataset() {
         return DatasetFactory.wrap(new DatasetGraphWithLock(DatasetGraphFactory.create()));
     }
-
-    @Test
-    public synchronized void dsg_with_lock_concurrency_01() throws InterruptedException,
ExecutionException, TimeoutException {
-        ExecutorService executor = Executors.newFixedThreadPool(2);
-        AtomicLong counter = new AtomicLong(0) ;
-        try {
-            final DatasetGraphWithLock dsg = new DatasetGraphWithLock(DatasetGraphFactory.create());
-
-            Callable<Boolean> callable = new Callable<Boolean>() {
-
-                @Override
-                public Boolean call() {
-                    dsg.begin(ReadWrite.WRITE);
-                    long x = counter.incrementAndGet() ;
-                    // Hold the lock for a short while.
-                    // The W threads will take the sleep serially.
-                    Lib.sleep(500) ;
-                    long x1 = counter.get() ;
-                    Assert.assertEquals("Two writers in the transaction", x, x1);
-                    dsg.commit();
-                    return true;
-                }
-            };
-
-            // Fire off two threads
-            Future<Boolean> f1 = executor.submit(callable);
-            Future<Boolean> f2 = executor.submit(callable);
-            // Wait longer than the cumulative threads sleep
-            Assert.assertTrue(f1.get(4, TimeUnit.SECONDS));
-            Assert.assertTrue(f2.get(1, TimeUnit.SECONDS));
-        } finally {
-            executor.shutdownNow();
-        }
-    }
-
-    @Test
-    public synchronized void dsg_with_lock_concurrency_02() throws InterruptedException,
ExecutionException, TimeoutException {
-        ExecutorService executor = Executors.newCachedThreadPool();
-        AtomicLong counter = new AtomicLong(0) ;
-        
-        try {
-            final DatasetGraphWithLock dsg = new DatasetGraphWithLock(DatasetGraphFactory.create());
-
-            Callable<Boolean> callable = new Callable<Boolean>() {
-
-                @Override
-                public Boolean call() {
-                    dsg.begin(ReadWrite.READ);
-                    long x = counter.incrementAndGet() ;
-                    // Hold the lock for a few seconds - these should be in parallel.
-                    Lib.sleep(1000) ;
-                    dsg.commit();
-                    return true;
-                }
-            };
-
-            // Run the callable a bunch of times
-            List<Future<Boolean>> futures = new ArrayList<>();
-            for (int i = 0; i < 25; i++) {
-                futures.add(executor.submit(callable));
-            }
-
-            // Check all the futures come back OK
-            // Wait shorter than sum total of all sleep by thread
-            // which proves concurrent access.
-            for (Future<Boolean> f : futures) {
-                Assert.assertTrue(f.get(4, TimeUnit.SECONDS));
-            }
-        } finally {
-            executor.shutdownNow();
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryTransactions.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryTransactions.java
b/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryTransactions.java
index 0cdd81a..6e1146b 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryTransactions.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/core/mem/TestDatasetGraphInMemoryTransactions.java
@@ -21,11 +21,11 @@ package org.apache.jena.sparql.core.mem;
 import org.apache.jena.atlas.logging.LogCtl ;
 import org.apache.jena.query.Dataset ;
 import org.apache.jena.query.DatasetFactory ;
-import org.apache.jena.sparql.transaction.AbstractTestTransaction ;
+import org.apache.jena.sparql.transaction.AbstractTestTransactionLifecycle ;
 import org.junit.AfterClass ;
 import org.junit.BeforeClass ;
 
-public class TestDatasetGraphInMemoryTransactions extends AbstractTestTransaction {
+public class TestDatasetGraphInMemoryTransactions extends AbstractTestTransactionLifecycle
{
     static Class<?> targetClassLogger = DatasetGraphInMemory.class ;
     @BeforeClass public static void beforeClassLoggingOff() { LogCtl.disable(targetClassLogger)
; } 
     @AfterClass public static void afterClassLoggingOn()    { LogCtl.setInfo(targetClassLogger)
; }

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransaction.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransaction.java
b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransaction.java
deleted file mode 100644
index 8cf3ea9..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransaction.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.jena.sparql.transaction;
-
-import static org.apache.jena.query.ReadWrite.READ ;
-import static org.apache.jena.query.ReadWrite.WRITE ;
-import org.apache.jena.atlas.junit.BaseTest ;
-import org.apache.jena.query.Dataset ;
-import org.apache.jena.query.ReadWrite ;
-import org.apache.jena.sparql.JenaTransactionException ;
-import org.junit.Test ;
-
-public abstract class AbstractTestTransaction extends BaseTest
-{
-    protected abstract Dataset create() ;
-    
-    @Test
-    public void transaction_00() {
-        Dataset ds = create() ;
-        assertTrue(ds.supportsTransactions()) ;
-    }
-
-    @Test
-    public void transaction_01() {
-        Dataset ds = create() ;
-        ds.begin(ReadWrite.READ) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.end() ;
-        assertFalse(ds.isInTransaction()) ;
-    }
-
-    @Test
-    public void transaction_02() {
-        Dataset ds = create() ;
-        ds.begin(ReadWrite.WRITE) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.commit() ;
-        assertFalse(ds.isInTransaction()) ;
-    }
-
-    @Test
-    public void transaction_03() {
-        Dataset ds = create() ;
-        ds.begin(ReadWrite.WRITE) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.abort() ;
-        assertFalse(ds.isInTransaction()) ;
-    }
-
-    @Test
-    public void transaction_04() {
-        Dataset ds = create() ;
-        ds.begin(ReadWrite.WRITE) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.commit() ;
-        assertFalse(ds.isInTransaction()) ;
-        ds.end() ;
-        assertFalse(ds.isInTransaction()) ;
-    }
-
-    @Test
-    public void transaction_05() {
-        Dataset ds = create() ;
-        ds.begin(ReadWrite.WRITE) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.abort() ;
-        assertFalse(ds.isInTransaction()) ;
-        ds.end() ;
-        assertFalse(ds.isInTransaction()) ;
-    }
-
-    @Test
-    public void transaction_06() {
-        // .end is not necessary
-        Dataset ds = create() ;
-        ds.begin(ReadWrite.WRITE) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.abort() ;
-        assertFalse(ds.isInTransaction()) ;
-
-        ds.begin(ReadWrite.WRITE) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.abort() ;
-        assertFalse(ds.isInTransaction()) ;
-    }
-
-    // Patterns.
-    @Test
-    public void transaction_07() {
-        Dataset ds = create() ;
-        read1(ds) ;
-        read1(ds) ;
-    }
-
-    @Test
-    public void transaction_08() {
-        Dataset ds = create() ;
-        read2(ds) ;
-        read2(ds) ;
-    }
-
-    @Test
-    public void transaction_09() {
-        Dataset ds = create() ;
-        write(ds) ;
-        write(ds) ;
-    }
-
-    @Test
-    public void transaction_10() {
-        Dataset ds = create() ;
-        write(ds) ;
-        read2(ds) ;
-        read2(ds) ;
-        write(ds) ;
-        read2(ds) ;
-    }
-    
-    // Cycle misalignment.
-    // test : commit
-    // test : abort
-    // Permit explain .end() - the case of "end" when not sure:  begin...end.end. 
-    
-    @Test(expected=JenaTransactionException.class)
-    public void transaction_err_nontxn_commit_1() { 
-        Dataset ds = create() ;
-        ds.commit() ;
-    }    
-    
-    @Test(expected=JenaTransactionException.class)
-    public void transaction_err_nontxn_commit_2() { 
-        Dataset ds = create() ;
-        ds.begin(READ) ;
-        ds.end() ;
-        ds.commit() ;
-    }    
-    
-    @Test(expected=JenaTransactionException.class)
-    public void transaction_err_nontxn_commit_3() { 
-        Dataset ds = create() ;
-        ds.begin(WRITE) ;
-        ds.end() ;
-        ds.commit() ;
-    }    
-
-    @Test(expected=JenaTransactionException.class)
-    public void transaction_err_nontxn_abort_1() { 
-        Dataset ds = create() ;
-        ds.abort() ;
-    }    
-
-    @Test(expected=JenaTransactionException.class)
-    public void transaction_err_nontxn_abort_2() { 
-        Dataset ds = create() ;
-        ds.begin(READ) ;
-        ds.end() ;
-        ds.abort() ;
-    }    
-
-    @Test(expected=JenaTransactionException.class)
-    public void transaction_err_nontxn_abort_3() { 
-        Dataset ds = create() ;
-        ds.begin(WRITE) ;
-        ds.end() ;
-        ds.abort() ;
-    }    
-
-    
-    @Test
-    public void transaction_err_01()    { testBeginBegin(WRITE, WRITE) ; }
-
-    @Test
-    public void transaction_err_02()    { testBeginBegin(WRITE, READ) ; }
-
-    @Test
-    public void transaction_err_03()    { testBeginBegin(READ, READ) ; }
-
-    @Test
-    public void transaction_err_04()    { testBeginBegin(READ, WRITE) ; }
-
-    @Test 
-    public void transaction_err_05()    { testCommitCommit(READ) ; }
-
-    @Test 
-    public void transaction_err_06()    { testCommitCommit(WRITE) ; }
-
-    @Test 
-    public void transaction_err_07()    { testCommitAbort(READ) ; }
-
-    @Test 
-    public void transaction_err_08()    { testCommitAbort(WRITE) ; }
-
-    @Test 
-    public void transaction_err_09()    { testAbortAbort(READ) ; }
-
-    @Test 
-    public void transaction_err_10()    { testAbortAbort(WRITE) ; }
-
-    @Test 
-    public void transaction_err_11()    { testAbortCommit(READ) ; }
-
-    @Test 
-    public void transaction_err_12()    { testAbortCommit(WRITE) ; }
-
-    private void read1(Dataset ds) {
-        ds.begin(ReadWrite.READ) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.commit() ;
-        assertFalse(ds.isInTransaction()) ;
-        ds.end() ;
-    }
-
-    private void read2(Dataset ds) {
-        ds.begin(ReadWrite.READ) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.end() ;
-        assertFalse(ds.isInTransaction()) ;
-    }
-
-    private void write(Dataset ds) {
-        ds.begin(ReadWrite.WRITE) ;
-        assertTrue(ds.isInTransaction()) ;
-        ds.commit() ;
-        assertFalse(ds.isInTransaction()) ;
-        ds.end() ;
-    }
-
-    private static void safeEnd(Dataset ds) {
-        try { ds.end() ; } catch (JenaTransactionException ex) {}
-    }
-    
-    // Error conditions that should be detected.
-
-    private void testBeginBegin(ReadWrite mode1, ReadWrite mode2) {
-        Dataset ds = create() ;
-        ds.begin(mode1) ;
-        try {
-            ds.begin(mode2) ;
-            fail("Expected transaction exception - begin-begin (" + mode1 + ", " + mode2
+ ")") ;
-        }
-        catch (JenaTransactionException ex) {
-            safeEnd(ds) ;
-        }
-    }
-    
-    private void testCommitCommit(ReadWrite mode) {
-        Dataset ds = create() ;
-        ds.begin(mode) ;
-        ds.commit() ;
-        try {
-            ds.commit() ;
-            fail("Expected transaction exception - commit-commit(" + mode + ")") ;
-        }
-        catch (JenaTransactionException ex) {
-            safeEnd(ds) ;
-        }
-    }
-
-    private void testCommitAbort(ReadWrite mode) {
-        Dataset ds = create() ;
-        ds.begin(mode) ;
-        ds.commit() ;
-        try {
-            ds.abort() ;
-            fail("Expected transaction exception - commit-abort(" + mode + ")") ;
-        }
-        catch (JenaTransactionException ex) {
-            safeEnd(ds) ;
-        }
-    }
-
-    private void testAbortAbort(ReadWrite mode) {
-        Dataset ds = create() ;
-        ds.begin(mode) ;
-        ds.abort() ;
-        try {
-            ds.abort() ;
-            fail("Expected transaction exception - abort-abort(" + mode + ")") ;
-        }
-        catch (JenaTransactionException ex) {
-            ds.end() ;
-        }
-    }
-
-    private void testAbortCommit(ReadWrite mode) {
-        Dataset ds = create() ;
-        ds.begin(mode) ;
-        ds.abort() ;
-        try {
-            ds.commit() ;
-            fail("Expected transaction exception - abort-commit(" + mode + ")") ;
-        }
-        catch (JenaTransactionException ex) {
-            safeEnd(ds) ;
-        }
-    }    
-}
-

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
new file mode 100644
index 0000000..a60215d
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
@@ -0,0 +1,418 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.transaction;
+
+import static org.apache.jena.query.ReadWrite.READ ;
+import static org.apache.jena.query.ReadWrite.WRITE ;
+
+import java.util.ArrayList ;
+import java.util.List ;
+import java.util.concurrent.* ;
+import java.util.concurrent.atomic.AtomicLong ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.query.Dataset ;
+import org.apache.jena.query.ReadWrite ;
+import org.apache.jena.sparql.JenaTransactionException ;
+import org.junit.Assert ;
+import org.junit.Test ;
+
+public abstract class AbstractTestTransactionLifecycle extends BaseTest
+{
+    protected abstract Dataset create() ;
+    
+    @Test
+    public void transaction_00() {
+        Dataset ds = create() ;
+        assertTrue(ds.supportsTransactions()) ;
+    }
+
+    @Test
+    public void transaction_r01() {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    @Test
+    public void transaction_r02() {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    @Test
+    public void transaction_r03() {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.abort() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    @Test
+    public void transaction_w01() {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    @Test
+    public void transaction_w02() {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.abort() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    @Test
+    public void transaction_w03() {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    @Test
+    public void transaction_w04() {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.abort() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    @Test
+    public void transaction_w05() {
+        // .end is not necessary
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.abort() ;
+        assertFalse(ds.isInTransaction()) ;
+
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.abort() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    // Patterns.
+    @Test
+    public void transaction_pattern_01() {
+        Dataset ds = create() ;
+        read1(ds) ;
+        read1(ds) ;
+    }
+
+    @Test
+    public void transaction_pattern_02() {
+        Dataset ds = create() ;
+        read2(ds) ;
+        read2(ds) ;
+    }
+
+    @Test
+    public void transaction_pattern_03() {
+        Dataset ds = create() ;
+        write(ds) ;
+        write(ds) ;
+    }
+
+    @Test
+    public void transaction_pattern_04() {
+        Dataset ds = create() ;
+        write(ds) ;
+        read2(ds) ;
+        read2(ds) ;
+        write(ds) ;
+        read2(ds) ;
+    }
+    
+    // Cycle misalignment.
+    // test : commit
+    // test : abort
+    // Permit explain .end() - the case of "end" when not sure:  begin...end.end. 
+    
+    @Test(expected=JenaTransactionException.class)
+    public void transaction_err_nontxn_commit_1() { 
+        Dataset ds = create() ;
+        ds.commit() ;
+    }    
+    
+    @Test(expected=JenaTransactionException.class)
+    public void transaction_err_nontxn_commit_2() { 
+        Dataset ds = create() ;
+        ds.begin(READ) ;
+        ds.end() ;
+        ds.commit() ;
+    }    
+    
+    @Test(expected=JenaTransactionException.class)
+    public void transaction_err_nontxn_commit_3() { 
+        Dataset ds = create() ;
+        ds.begin(WRITE) ;
+        ds.end() ;
+        ds.commit() ;
+    }    
+
+    @Test(expected=JenaTransactionException.class)
+    public void transaction_err_nontxn_abort_1() { 
+        Dataset ds = create() ;
+        ds.abort() ;
+    }    
+
+    @Test(expected=JenaTransactionException.class)
+    public void transaction_err_nontxn_abort_2() { 
+        Dataset ds = create() ;
+        ds.begin(READ) ;
+        ds.end() ;
+        ds.abort() ;
+    }    
+
+    @Test(expected=JenaTransactionException.class)
+    public void transaction_err_nontxn_abort_3() { 
+        Dataset ds = create() ;
+        ds.begin(WRITE) ;
+        ds.end() ;
+        ds.abort() ;
+    }    
+
+    
+    @Test
+    public void transaction_err_01()    { testBeginBegin(WRITE, WRITE) ; }
+
+    @Test
+    public void transaction_err_02()    { testBeginBegin(WRITE, READ) ; }
+
+    @Test
+    public void transaction_err_03()    { testBeginBegin(READ, READ) ; }
+
+    @Test
+    public void transaction_err_04()    { testBeginBegin(READ, WRITE) ; }
+
+    @Test 
+    public void transaction_err_05()    { testCommitCommit(READ) ; }
+
+    @Test 
+    public void transaction_err_06()    { testCommitCommit(WRITE) ; }
+
+    @Test 
+    public void transaction_err_07()    { testCommitAbort(READ) ; }
+
+    @Test 
+    public void transaction_err_08()    { testCommitAbort(WRITE) ; }
+
+    @Test 
+    public void transaction_err_09()    { testAbortAbort(READ) ; }
+
+    @Test 
+    public void transaction_err_10()    { testAbortAbort(WRITE) ; }
+
+    @Test 
+    public void transaction_err_11()    { testAbortCommit(READ) ; }
+
+    @Test 
+    public void transaction_err_12()    { testAbortCommit(WRITE) ; }
+
+    
+    
+    private void read1(Dataset ds) {
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+    }
+
+    private void read2(Dataset ds) {
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
+    private void write(Dataset ds) {
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ;
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+    }
+
+    private static void safeEnd(Dataset ds) {
+        try { ds.end() ; } catch (JenaTransactionException ex) {}
+    }
+    
+    // Error conditions that should be detected.
+
+    private void testBeginBegin(ReadWrite mode1, ReadWrite mode2) {
+        Dataset ds = create() ;
+        ds.begin(mode1) ;
+        try {
+            ds.begin(mode2) ;
+            fail("Expected transaction exception - begin-begin (" + mode1 + ", " + mode2
+ ")") ;
+        }
+        catch (JenaTransactionException ex) {
+            safeEnd(ds) ;
+        }
+    }
+    
+    private void testCommitCommit(ReadWrite mode) {
+        Dataset ds = create() ;
+        ds.begin(mode) ;
+        ds.commit() ;
+        try {
+            ds.commit() ;
+            fail("Expected transaction exception - commit-commit(" + mode + ")") ;
+        }
+        catch (JenaTransactionException ex) {
+            safeEnd(ds) ;
+        }
+    }
+
+    private void testCommitAbort(ReadWrite mode) {
+        Dataset ds = create() ;
+        ds.begin(mode) ;
+        ds.commit() ;
+        try {
+            ds.abort() ;
+            fail("Expected transaction exception - commit-abort(" + mode + ")") ;
+        }
+        catch (JenaTransactionException ex) {
+            safeEnd(ds) ;
+        }
+    }
+
+    private void testAbortAbort(ReadWrite mode) {
+        Dataset ds = create() ;
+        ds.begin(mode) ;
+        ds.abort() ;
+        try {
+            ds.abort() ;
+            fail("Expected transaction exception - abort-abort(" + mode + ")") ;
+        }
+        catch (JenaTransactionException ex) {
+            ds.end() ;
+        }
+    }
+
+    private void testAbortCommit(ReadWrite mode) {
+        Dataset ds = create() ;
+        ds.begin(mode) ;
+        ds.abort() ;
+        try {
+            ds.commit() ;
+            fail("Expected transaction exception - abort-commit(" + mode + ")") ;
+        }
+        catch (JenaTransactionException ex) {
+            safeEnd(ds) ;
+        }
+    }
+
+    // ---- Concurrency tests.
+    @Test
+    public synchronized void transaction_concurrency_writer() throws InterruptedException,
ExecutionException, TimeoutException {
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        AtomicLong counter = new AtomicLong(0) ;
+        try {
+            final Dataset ds = create() ;
+
+            Callable<Boolean> callable = new Callable<Boolean>() {
+
+                @Override
+                public Boolean call() {
+                    ds.begin(ReadWrite.WRITE);
+                    long x = counter.incrementAndGet() ;
+                    // Hold the lock for a short while.
+                    // The W threads will take the sleep serially.
+                    Lib.sleep(500) ;
+                    long x1 = counter.get() ;
+                    Assert.assertEquals("Two writers in the transaction", x, x1);
+                    ds.commit();
+                    return true;
+                }
+            };
+
+            // Fire off two threads
+            Future<Boolean> f1 = executor.submit(callable);
+            Future<Boolean> f2 = executor.submit(callable);
+            // Wait longer than the cumulative threads sleep
+            Assert.assertTrue(f1.get(4, TimeUnit.SECONDS));
+            Assert.assertTrue(f2.get(1, TimeUnit.SECONDS));
+        } finally {
+            executor.shutdownNow();
+        }
+    }
+
+    @Test
+    public synchronized void transaction_concurrency_reader() throws InterruptedException,
ExecutionException, TimeoutException {
+        ExecutorService executor = Executors.newCachedThreadPool();
+        AtomicLong counter = new AtomicLong(0) ;
+        
+        try {
+            final Dataset ds = create() ;
+
+            Callable<Boolean> callable = new Callable<Boolean>() {
+                @Override
+                public Boolean call() {
+                    ds.begin(ReadWrite.READ);
+                    long x = counter.incrementAndGet() ;
+                    // Hold the lock for a few seconds - these should be in parallel.
+                    Lib.sleep(1000) ;
+                    ds.commit();
+                    return true;
+                }
+            };
+
+            // Run the callable a bunch of times
+            List<Future<Boolean>> futures = new ArrayList<>();
+            for (int i = 0; i < 25; i++) {
+                futures.add(executor.submit(callable));
+            }
+
+            // Check all the futures come back OK
+            // Wait shorter than sum total of all sleep by thread
+            // which proves concurrent access.
+            for (Future<Boolean> f : futures) {
+                Assert.assertTrue(f.get(4, TimeUnit.SECONDS));
+            }
+        } finally {
+            executor.shutdownNow();
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java
b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java
index 63c99c1..98bb374 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TS_Transaction.java
@@ -24,7 +24,8 @@ import org.junit.runners.Suite.SuiteClasses ;
 
 @RunWith(Suite.class)
 @SuiteClasses( {
-    TestTransactionMem.class
+    TestTransactionDSGWithLock.class,
+    TestTransactionDSGWithLockWithAbort.class,
 })
 
 public class TS_Transaction

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLock.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLock.java
b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLock.java
new file mode 100644
index 0000000..67d53f1
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLock.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.transaction;
+
+import org.apache.jena.query.Dataset ;
+import org.apache.jena.query.DatasetFactory ;
+import org.apache.jena.sparql.core.DatasetGraph ;
+import org.apache.jena.sparql.core.DatasetGraphFactory ;
+import org.apache.jena.sparql.core.DatasetGraphWithLock ;
+import org.junit.Ignore ;
+import org.junit.Test ;
+
+/** Version with abortImplemented == false (the default). */
+public class TestTransactionDSGWithLock extends AbstractTestTransactionLifecycle
+{
+    @Override
+    protected Dataset create()
+    { 
+        DatasetGraph dsg = DatasetGraphFactory.create() ;
+        DatasetGraphWithLock dsgl = new  DatasetGraphWithLock(dsg) ;
+        return DatasetFactory.wrap(dsgl) ;
+    }
+    
+    // Tests that don't make sense because they abort a write transaction.
+    // (Using org.junit.Assume would be better?)
+    @Test @Override @Ignore public void transaction_err_10() {} 
+    @Test @Override @Ignore public void transaction_err_12() {} 
+    
+    @Test @Override @Ignore public void transaction_w02() {}
+    @Test @Override @Ignore public void transaction_w04() {}
+    @Test @Override @Ignore public void transaction_w05() {}
+ }
+

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java
b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java
new file mode 100644
index 0000000..6226b2b
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionDSGWithLockWithAbort.java
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.transaction;
+
+import org.apache.jena.query.Dataset ;
+import org.apache.jena.query.DatasetFactory ;
+import org.apache.jena.sparql.core.DatasetGraph ;
+import org.apache.jena.sparql.core.DatasetGraphFactory ;
+import org.apache.jena.sparql.core.DatasetGraphWithLock ;
+
+/** Version with abortImplemented == true */
+public class TestTransactionDSGWithLockWithAbort extends AbstractTestTransactionLifecycle
+{
+    @Override
+    protected Dataset create() { 
+        // The tests don't actuall add/delete data.
+        DatasetGraph dsg = DatasetGraphFactory.create() ;
+        DatasetGraphWithLock dsgl = new  DatasetGraphWithLock(dsg) {
+            @Override
+            protected boolean abortImplemented() { return true ; }
+        } ;
+        return DatasetFactory.wrap(dsgl) ;
+    }
+ }
+

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionMem.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionMem.java
b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionMem.java
deleted file mode 100644
index 3ae4411..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/TestTransactionMem.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.jena.sparql.transaction;
-
-import org.apache.jena.query.Dataset ;
-import org.apache.jena.query.DatasetFactory ;
-import org.apache.jena.sparql.core.DatasetGraph ;
-import org.apache.jena.sparql.core.DatasetGraphFactory ;
-import org.apache.jena.sparql.core.DatasetGraphWithLock ;
-import org.junit.Ignore ;
-import org.junit.Test ;
-
-public class TestTransactionMem extends AbstractTestTransaction
-{
-    @Override
-    protected Dataset create()
-    { 
-        DatasetGraph dsg = DatasetGraphFactory.create() ;
-        DatasetGraphWithLock dsgl = new  DatasetGraphWithLock(dsg) ;
-        return DatasetFactory.wrap(dsgl) ;
-    }
-    
-    // Tests that don't make sense because they abort a write transaction.
-    // (Using org.junit.Assume would be better?)
-    @Test @Override @Ignore public void transaction_err_10() {} 
-    @Test @Override @Ignore public void transaction_err_12() {} 
-    @Test @Override @Ignore public void transaction_03() {} 
-    @Test @Override @Ignore public void transaction_05() {} 
-    @Test @Override @Ignore public void transaction_06() {} 
-    
- }
-

http://git-wip-us.apache.org/repos/asf/jena/blob/03ec3e97/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionTDB.java
----------------------------------------------------------------------
diff --git a/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionTDB.java
b/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionTDB.java
index e81074e..bb0a1b8 100644
--- a/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionTDB.java
+++ b/jena-tdb/src/test/java/org/apache/jena/tdb/transaction/TestTransactionTDB.java
@@ -25,7 +25,7 @@ import org.apache.jena.atlas.logging.LogCtl ;
 import org.apache.jena.graph.Triple ;
 import org.apache.jena.query.Dataset ;
 import org.apache.jena.sparql.sse.SSE ;
-import org.apache.jena.sparql.transaction.AbstractTestTransaction ;
+import org.apache.jena.sparql.transaction.AbstractTestTransactionLifecycle ;
 import org.apache.jena.tdb.ConfigTest ;
 import org.apache.jena.tdb.StoreConnection ;
 import org.apache.jena.tdb.TDBFactory ;
@@ -33,7 +33,7 @@ import org.apache.jena.tdb.base.file.Location ;
 import org.apache.jena.tdb.sys.SystemTDB ;
 import org.junit.* ;
 
-public class TestTransactionTDB extends AbstractTestTransaction
+public class TestTransactionTDB extends AbstractTestTransactionLifecycle
 {
     private String DIR = null ; 
     


Mime
View raw message