package org.multiverse.stms.gamma.transactionalobjects.txnref; import org.junit.Before; import org.junit.Test; import org.multiverse.api.LockMode; import org.multiverse.api.exceptions.DeadTxnException; import org.multiverse.api.exceptions.PreparedTxnException; import org.multiverse.api.exceptions.ReadWriteConflict; import org.multiverse.api.exceptions.RetryError; import org.multiverse.stms.gamma.GammaConstants; import org.multiverse.stms.gamma.GammaStm; import org.multiverse.stms.gamma.transactionalobjects.GammaTxnRef; import org.multiverse.stms.gamma.transactionalobjects.Tranlocal; import org.multiverse.stms.gamma.transactions.GammaTxn; import static org.junit.Assert.*; import static org.multiverse.TestUtils.assertIsAborted; import static org.multiverse.TestUtils.assertIsCommitted; import static org.multiverse.api.TxnThreadLocal.clearThreadLocalTxn; import static org.multiverse.stms.gamma.GammaTestUtils.*; public class GammaTxnRef_awaitNotNullAndGet1Test implements GammaConstants { private GammaStm stm; @Before public void setUp() { stm = new GammaStm(); clearThreadLocalTxn(); } @Test public void whenNotNull_thenReturnImmediately() { String initialValue = "foo"; GammaTxnRef<String> ref = new GammaTxnRef<String>(stm, initialValue); long initialVersion = ref.getVersion(); GammaTxn tx = stm.newDefaultTxn(); String result = ref.awaitNotNullAndGet(tx); assertSame(initialValue, result); Tranlocal tranlocal = tx.locate(ref); assertTrue(tranlocal.isRead()); assertEquals(LOCKMODE_NONE, tranlocal.getLockMode()); assertRefHasNoLocks(ref); tx.commit(); assertIsCommitted(tx); assertVersionAndValue(ref, initialVersion, initialValue); assertRefHasNoLocks(ref); } @Test public void whenPrivatizedByOther_thenReadWriteConflict() { GammaTxnRef<String> ref = new GammaTxnRef<String>(stm); long initialVersion = ref.getVersion(); GammaTxn otherTx = stm.newDefaultTxn(); ref.getLock().acquire(otherTx, LockMode.Exclusive); GammaTxn tx = stm.newDefaultTxn(); try { ref.awaitNotNullAndGet(tx); fail(); } catch (ReadWriteConflict expected) { } assertIsAborted(tx); assertVersionAndValue(ref, initialVersion, null); assertRefHasExclusiveLock(ref, otherTx); } @Test public void whenEnsuredByOther_thenSuccess() { String initialValue = "foo"; GammaTxnRef<String> ref = new GammaTxnRef<String>(stm, initialValue); long initialVersion = ref.getVersion(); GammaTxn otherTx = stm.newDefaultTxn(); ref.getLock().acquire(otherTx, LockMode.Write); GammaTxn tx = stm.newDefaultTxn(); String result = ref.awaitNotNullAndGet(tx); assertSame(initialValue, result); Tranlocal tranlocal = tx.locate(ref); assertTrue(tranlocal.isRead()); assertEquals(LOCKMODE_NONE, tranlocal.getLockMode()); assertRefHasWriteLock(ref, otherTx); tx.commit(); assertIsCommitted(tx); assertVersionAndValue(ref, initialVersion, initialValue); assertRefHasWriteLock(ref, otherTx); } @Test public void whenNull_thenWait() { GammaTxnRef<String> ref = new GammaTxnRef<String>(stm); long initialVersion = ref.getVersion(); GammaTxn tx = stm.newTxnFactoryBuilder() .newTransactionFactory() .newTxn(); try { ref.awaitNotNullAndGet(tx); fail(); } catch (RetryError expected) { } assertIsAborted(tx); assertVersionAndValue(ref, initialVersion, null); assertRefHasNoLocks(ref); } @Test public void whenNullTransaction_thenNullPointerException() { GammaTxnRef<String> ref = new GammaTxnRef<String>(stm); long initialVersion = ref.getVersion(); try { ref.awaitNotNullAndGet(null); fail(); } catch (NullPointerException expected) { } assertVersionAndValue(ref, initialVersion, null); } @Test public void whenPreparedTransaction_thenPreparedTxnException() { GammaTxnRef<String> ref = new GammaTxnRef<String>(stm); long initialVersion = ref.getVersion(); GammaTxn tx = stm.newDefaultTxn(); tx.prepare(); try { ref.awaitNotNullAndGet(tx); fail(); } catch (PreparedTxnException expected) { } assertIsAborted(tx); assertVersionAndValue(ref, initialVersion, null); } @Test public void whenAbortedTransaction_thenDeadTxnException() { GammaTxnRef<String> ref = new GammaTxnRef<String>(stm); long initialVersion = ref.getVersion(); GammaTxn tx = stm.newDefaultTxn(); tx.abort(); try { ref.awaitNotNullAndGet(tx); fail(); } catch (DeadTxnException expected) { } assertIsAborted(tx); assertVersionAndValue(ref, initialVersion, null); } @Test public void whenCommittedTransaction_thenDeadTxnException() { GammaTxnRef<String> ref = new GammaTxnRef<String>(stm); long initialVersion = ref.getVersion(); GammaTxn tx = stm.newDefaultTxn(); tx.commit(); try { ref.awaitNotNullAndGet(tx); fail(); } catch (DeadTxnException expected) { } assertIsCommitted(tx); assertVersionAndValue(ref, initialVersion, null); } }