/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.bigdata.rdf.sail.webapp; import java.util.Properties; import junit.framework.Test; import com.bigdata.journal.IIndexManager; import com.bigdata.rdf.sail.BigdataSail; import com.bigdata.rdf.sail.webapp.client.IRemoteTx; import com.bigdata.rdf.sail.webapp.client.RemoteTransactionManager; /** * Proxied test suite for testing the transaction management API. The outer * class provides a test suite for behaviors that are consistent without regard * to whether or not isolatable indices have been enabled. There are then two * inner classes that provide tests where we are controlling the configuration * and verifying behaviors that are specific to when isolatable indices are / * are not enabled. * * @param <S> * * @see <a href="http://trac.bigdata.com/ticket/1156"> Support read/write * transactions in the REST API</a> * * FIXME (***) Test operations isolated by transactions. * * FIXME Test that a sequence of queries may be isolated by a read-only * transaction and that the queries have snapshot isolation across the * transaction that is preserved even when there are new commit points that * write on the namespace. * * FIXME Write tests in which we force operations where the transaction is * not active and make sure that the API is behaving itself in terms of the * error messages. * * FIXME Write HA tests for transaction coordination. See #1189 * * FIXME Modify the multi-tenancy API stress test to obtain a stress test * that also operations against namespaces that are configured with * isolatable index support. * * TODO Test that a transaction may be created without regard to the end * point. The transaction is about the transaction manager, not a given * namespace. Isolation of a namespace is obtained by having the * transaction pin the commit point associated with its start time (its * readsOnCommitTime). Thus we can actually use a single transaction to * coordinate an operation on more than one namespace in the same database. * * TODO Write unit test that is federation specific and which verifies that * read/write transactions are correctly rejected since they are not * supported for scale-out (we do not support distributed 2-phase * transactions). * * FIXME Write a test suite that uses a mixture of unisolated and * read/write transactions. Verify that we can use unisolated transactions * for bulk load and isolated transactions for smaller mutations and that * the indices are consistent (especially, this is concerned with the * revision timestamps on the indices that are used to detect write-write * conflicts in read/write transactions - the unisolated updates need to be * touching those timestamps if the index supports isolation in order for * the read/write transactions to detect a conflict created by an * unisolated update since the read/write transaction was created.) */ public class Test_REST_TX_API<S extends IIndexManager> extends AbstractTestNanoSparqlClient<S> { public Test_REST_TX_API() { } public Test_REST_TX_API(final String name) { super(name); } public static Test suite() { return ProxySuiteHelper.suiteWhenStandalone(Test_REST_TX_API.class, "test.*", TestMode.quads // , TestMode.sids // , TestMode.triples ); // return ProxySuiteHelper.suiteWhenStandalone(Test_REST_TX_API.NoReadWriteTx.class, // "test.*", TestMode.quads // // , TestMode.sids // // , TestMode.triples // ); // // return ProxySuiteHelper.suiteWhenStandalone(Test_REST_TX_API.ReadWriteTx.class, // "test.*", TestMode.quads // // , TestMode.sids // // , TestMode.triples // ); } /** * Create an unisolated transaction, verify its metadata, and abort it. */ public void test_CREATE_TX_UNISOLATED_01() throws Exception { assertNotNull(m_mgr); assertNotNull(m_mgr.getTransactionManager()); final IRemoteTx tx = m_mgr.getTransactionManager().createTx( RemoteTransactionManager.UNISOLATED); try { assertTrue(tx.isActive()); assertFalse(tx.isReadOnly()); } finally { tx.abort(); } assertFalse(tx.isActive()); assertFalse(tx.isReadOnly()); } /** * Create an unisolated transaction and commit it. This should be a NOP since * nothing is written on the database. * * TODO Create an unisolated transaction, write on the transaction, commit * the transaction and verify that we can read back the write set after the * commit. Note that we can only write on the resulting transaction if the * namespace supports isolatable indices. */ public void test_CREATE_TX_UNISOLATED_02() throws Exception { assertNotNull(m_mgr); assertNotNull(m_mgr.getTransactionManager()); final IRemoteTx tx = m_mgr.getTransactionManager().createTx( RemoteTransactionManager.UNISOLATED); try { } finally { tx.commit(); } assertFalse(tx.isActive()); } /** * Create an read-only transaction, verify its metadata, and abort it. */ public void test_CREATE_TX_READ_ONLY_01() throws Exception { assertNotNull(m_mgr); assertNotNull(m_mgr.getTransactionManager()); final IRemoteTx tx = m_mgr.getTransactionManager().createTx( RemoteTransactionManager.READ_COMMITTED); try { assertTrue(tx.isActive()); assertTrue(tx.isReadOnly()); } finally { tx.abort(); } assertFalse(tx.isActive()); assertTrue(tx.isReadOnly()); } /** * Create an read-only transaction and commit it. This should be a NOP since * nothing is written on the database. * * TODO Actually read on the transaction. Verify that we do not see concurrent * updates. * * TODO Do something similar with read-historical transactions. Verify that * we do not see concurrent updates and that we do not see updates for commit * points after the transaction start (this is nearly the same thing, but we * also should create the read-only tx only once we know that a commit point * has been pinned and that subsequent commits have been applied and verify * that the new tx is also reading from the correct commit point.) */ public void test_CREATE_TX_READ_ONLY_02() throws Exception { assertNotNull(m_mgr); assertNotNull(m_mgr.getTransactionManager()); final IRemoteTx tx = m_mgr.getTransactionManager().createTx( RemoteTransactionManager.READ_COMMITTED); try { } finally { tx.commit(); } assertFalse(tx.isActive()); } // public void test_TX_STUFF() { // // fail("write lots of tests"); // // } /** * An *extension* of the test suite that uses a namespace that is NOT * configured to support read/write transactions. This extension is used to * verify that certain operations are NOT permitted when the namespace does * not support isolatable indices. * <p> * Note: This does not change whether or not a transaction may be created, * just whether or not the namespace will allow an operation that is isolated * by a read/write transaction. */ public static class NoReadWriteTx<S extends IIndexManager> extends Test_REST_TX_API<S> { @Override public Properties getProperties() { final Properties p = new Properties(super.getProperties()); p.setProperty(BigdataSail.Options.ISOLATABLE_INDICES, "false"); return p; } public NoReadWriteTx() { } public NoReadWriteTx(final String name) { super(name); } // FIXME Write tests. public void test_TX_STUFF() { } } /** * An *extension* of the test suite that uses a namespace that is configured * to support read/write transactions. * <p> * Note: This does not change whether or not a transaction may be created, * just whether or not the namespace will allow an operation that is isolated * by a read/write transaction. */ public static class ReadWriteTx<S extends IIndexManager> extends Test_REST_TX_API<S> { @Override public Properties getProperties() { final Properties p = new Properties(super.getProperties()); p.setProperty(BigdataSail.Options.ISOLATABLE_INDICES, "true"); return p; } public ReadWriteTx() { } public ReadWriteTx(final String name) { super(name); } // FIXME Write tests. public void test_TX_STUFF() { } } }