package org.multiverse.commitbarriers;
import org.junit.After;
import org.junit.Before;
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.stms.gamma.GammaStm;
import static org.junit.Assert.*;
import static org.multiverse.TestUtils.*;
import static org.multiverse.api.TxnThreadLocal.clearThreadLocalTxn;
public class CountDownCommitBarrier_joinCommitUninterruptiblyTest {
private CountDownCommitBarrier barrier;
private GammaStm stm;
@Before
public void setUp() {
stm = new GammaStm();
clearThreadLocalTxn();
clearCurrentThreadInterruptedStatus();
}
@After
public void tearDown() {
clearCurrentThreadInterruptedStatus();
}
@Test
public void whenOpenAndNullTransaction_thenNullPointerException() {
barrier = new CountDownCommitBarrier(1);
try {
barrier.joinCommitUninterruptibly(null);
fail();
} catch (NullPointerException expected) {
}
assertTrue(barrier.isClosed());
assertEquals(0, barrier.getNumberWaiting());
}
@Test
public void whenOpenAndThreadAlreadyInterrupted_thenNotInterruptedButInterruptStatusIsSet() {
barrier = new CountDownCommitBarrier(1);
Thread.currentThread().interrupt();
Txn tx = stm.newDefaultTxn();
barrier.joinCommitUninterruptibly(tx);
assertTrue(barrier.isCommitted());
assertEquals(0, barrier.getNumberWaiting());
assertTrue(Thread.currentThread().isInterrupted());
}
@Test
public void whenOpenAndTransactionActive() {
Txn tx = stm.newDefaultTxn();
tx.prepare();
barrier = new CountDownCommitBarrier(1);
barrier.joinCommitUninterruptibly(tx);
assertIsCommitted(tx);
assertTrue(barrier.isCommitted());
}
@Test
public void whenOpenAndTransactionPrepared() {
Txn tx = stm.newDefaultTxn();
tx.prepare();
barrier = new CountDownCommitBarrier(1);
barrier.joinCommitUninterruptibly(tx);
assertIsCommitted(tx);
assertTrue(barrier.isCommitted());
}
@Test
public void whenOpenAndLastTransaction_thenAllTransactionsCommitted() {
barrier = new CountDownCommitBarrier(3);
AwaitThread t1 = new AwaitThread();
AwaitThread t2 = new AwaitThread();
startAll(t1, t2);
sleepMs(500);
assertAlive(t1, t2);
assertTrue(barrier.isClosed());
Txn tx = stm.newDefaultTxn();
barrier.joinCommitUninterruptibly(tx);
joinAll(t1, t2);
assertIsCommitted(tx, t1.txn, t2.txn);
}
@Test
public void whenOpenAndTransactionAborted_thenDeadTxnException() {
Txn tx = stm.newDefaultTxn();
tx.abort();
barrier = new CountDownCommitBarrier(1);
try {
barrier.joinCommitUninterruptibly(tx);
fail();
} catch (DeadTxnException ex) {
}
assertTrue(barrier.isClosed());
assertEquals(0, barrier.getNumberWaiting());
}
@Test
public void whenOpenAndTransactionCommitted_thenDeadTxnException() {
Txn tx = stm.newDefaultTxn();
tx.commit();
barrier = new CountDownCommitBarrier(1);
try {
barrier.joinCommitUninterruptibly(tx);
fail();
} catch (DeadTxnException ex) {
}
assertTrue(barrier.isClosed());
assertEquals(0, barrier.getNumberWaiting());
}
@Test
public void whenAborted_thenCommitBarrierOpenException() {
barrier = new CountDownCommitBarrier(1);
barrier.abort();
Txn tx = stm.newDefaultTxn();
try {
barrier.joinCommitUninterruptibly(tx);
fail();
} catch (CommitBarrierOpenException expected) {
}
assertTrue(barrier.isAborted());
}
@Test
public void whenCommitted_thenCommitBarrierOpenException() {
barrier = new CountDownCommitBarrier(1);
barrier.joinCommitUninterruptibly(stm.newDefaultTxn());
Txn tx = stm.newDefaultTxn();
try {
barrier.joinCommitUninterruptibly(tx);
fail();
} catch (CommitBarrierOpenException expected) {
}
assertIsAborted(tx);
}
class AwaitThread extends TestThread {
private Txn txn;
@Override
public void doRun() throws Exception {
stm.getDefaultTxnExecutor().execute(new TxnVoidCallable() {
@Override
public void call(Txn txn) throws Exception {
AwaitThread.this.txn = txn;
barrier.joinCommitUninterruptibly(txn);
}
});
}
}
}