package org.multiverse.commitbarriers;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.multiverse.TestThread;
import org.multiverse.api.Txn;
import org.multiverse.api.callables.TxnVoidCallable;
import org.multiverse.api.exceptions.DeadTxnException;
import org.multiverse.api.exceptions.ReadWriteConflict;
import org.multiverse.stms.gamma.GammaConstants;
import org.multiverse.stms.gamma.GammaStm;
import org.multiverse.stms.gamma.transactionalobjects.GammaTxnInteger;
import org.multiverse.stms.gamma.transactions.GammaTxn;
import static org.junit.Assert.*;
import static org.multiverse.TestUtils.*;
import static org.multiverse.api.TxnThreadLocal.clearThreadLocalTxn;
public class VetoCommitBarrier_vetoCommitWithTransactionTest implements GammaConstants {
private GammaStm stm;
@Before
public void setUp() {
stm = new GammaStm();
clearThreadLocalTxn();
clearCurrentThreadInterruptedStatus();
}
@After
public void tearDown() {
clearCurrentThreadInterruptedStatus();
}
@Test
public void whenNullTx_thenNullPointerException() {
VetoCommitBarrier barrier = new VetoCommitBarrier();
try {
barrier.vetoCommit(null);
fail();
} catch (NullPointerException expected) {
}
assertTrue(barrier.isClosed());
}
@Test
public void whenNoPendingTransactions() {
VetoCommitBarrier barrier = new VetoCommitBarrier();
Txn tx = stm.newDefaultTxn();
barrier.vetoCommit(tx);
assertTrue(barrier.isCommitted());
assertIsCommitted(tx);
}
@Test
@Ignore
public void whenPendingTransaction() throws InterruptedException {
final VetoCommitBarrier barrier = new VetoCommitBarrier();
final GammaTxnInteger ref = new GammaTxnInteger(stm);
TestThread t = new TestThread() {
@Override
public void doRun() throws Exception {
stm.getDefaultTxnExecutor().execute(new TxnVoidCallable() {
@Override
public void call(Txn tx) throws Exception {
ref.incrementAndGet(tx, 1);
barrier.joinCommit(tx);
}
});
}
};
t.start();
sleepMs(500);
assertAlive(t);
assertTrue(barrier.isClosed());
barrier.atomicVetoCommit();
t.join();
assertNothingThrown(t);
assertTrue(barrier.isCommitted());
assertEquals(1, ref.atomicGet());
assertEquals(0, barrier.getNumberWaiting());
}
@Test
public void whenTransactionFailedToPrepare_thenBarrierNotAbortedOrCommitted() {
final GammaTxnInteger ref = new GammaTxnInteger(stm);
GammaTxn tx = stm.newDefaultTxn();
ref.get(tx);
//conflicting write
ref.atomicIncrementAndGet(1);
ref.incrementAndGet(tx, 1);
VetoCommitBarrier barrier = new VetoCommitBarrier();
try {
barrier.vetoCommit(tx);
fail();
} catch (ReadWriteConflict expected) {
}
assertTrue(barrier.isClosed());
}
@Test
public void whenTransactionAborted_thenDeadTxnException() {
VetoCommitBarrier barrier = new VetoCommitBarrier();
Txn tx = stm.newDefaultTxn();
tx.abort();
try {
barrier.vetoCommit(tx);
fail();
} catch (DeadTxnException expected) {
}
assertIsAborted(tx);
assertTrue(barrier.isClosed());
}
@Test
public void whenTransactionCommitted_thenDeadTxnException() {
VetoCommitBarrier barrier = new VetoCommitBarrier();
Txn tx = stm.newDefaultTxn();
tx.commit();
try {
barrier.vetoCommit(tx);
fail();
} catch (DeadTxnException expected) {
}
assertIsCommitted(tx);
assertTrue(barrier.isClosed());
}
@Test
public void whenBarrierCommitted_thenCommitBarrierOpenException() {
VetoCommitBarrier barrier = new VetoCommitBarrier();
barrier.atomicVetoCommit();
Txn tx = stm.newDefaultTxn();
try {
barrier.vetoCommit(tx);
fail();
} catch (CommitBarrierOpenException expected) {
}
assertTrue(barrier.isCommitted());
assertIsActive(tx);
}
@Test
public void whenBarrierAborted_thenCommitBarrierOpenException() {
VetoCommitBarrier barrier = new VetoCommitBarrier();
barrier.abort();
Txn tx = stm.newDefaultTxn();
try {
barrier.vetoCommit(tx);
fail();
} catch (CommitBarrierOpenException expected) {
}
assertTrue(barrier.isAborted());
assertIsActive(tx);
}
}