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 org.multiverse.stms.gamma.transactionalobjects.GammaTxnInteger;
import static org.junit.Assert.*;
import static org.multiverse.TestUtils.*;
import static org.multiverse.api.TxnThreadLocal.clearThreadLocalTxn;
public class CountDownCommitBarrier_joinCommitTest {
private CountDownCommitBarrier barrier;
private GammaStm stm;
@Before
public void setUp() {
stm = new GammaStm();
clearThreadLocalTxn();
clearCurrentThreadInterruptedStatus();
}
@After
public void tearDown() {
clearCurrentThreadInterruptedStatus();
}
@Test
public void whenNullTransaction() throws InterruptedException {
barrier = new CountDownCommitBarrier(1);
try {
barrier.joinCommit(null);
fail();
} catch (NullPointerException expected) {
}
assertTrue(barrier.isClosed());
assertEquals(0, barrier.getNumberWaiting());
}
@Test
public void whenLastOneEntering() throws InterruptedException {
barrier = new CountDownCommitBarrier(1);
Txn tx = stm.newTxnFactoryBuilder()
.setSpeculative(false)
.newTransactionFactory()
.newTxn();
barrier.joinCommit(tx);
assertIsCommitted(tx);
assertTrue(barrier.isCommitted());
assertEquals(0, barrier.getNumberWaiting());
}
@Test
public void whenAbortedWhileWaiting() throws InterruptedException {
barrier = new CountDownCommitBarrier(2);
final GammaTxnInteger ref = stm.getDefaultRefFactory().newTxnInteger(0);
TestThread t = new TestThread() {
@Override
public void doRun() throws Exception {
stm.getDefaultTxnExecutor().execute(new TxnVoidCallable() {
@Override
public void call(Txn tx) throws Exception {
ref.set(tx, 10);
barrier.joinCommit(tx);
}
});
}
};
t.setPrintStackTrace(false);
t.start();
sleepMs(1000);
assertAlive(t);
assertTrue(barrier.isClosed());
barrier.abort();
t.join();
t.assertFailedWithException(IllegalStateException.class);
assertTrue(barrier.isAborted());
assertEquals(0, ref.atomicGet());
}
@Test
public void whenCommittedWhileWaiting() {
barrier = new CountDownCommitBarrier(3);
JoinCommitThread t1 = new JoinCommitThread(stm, barrier);
JoinCommitThread t2 = new JoinCommitThread(stm, barrier);
startAll(t1, t2);
sleepMs(500);
barrier.countDown();
joinAll(t1, t2);
assertTrue(barrier.isCommitted());
}
@Test
public void whenInterruptedWhileWaiting() throws InterruptedException {
barrier = new CountDownCommitBarrier(2);
final GammaTxnInteger ref = stm.getDefaultRefFactory().newTxnInteger(0);
TestThread t = new TestThread() {
@Override
public void doRun() throws Exception {
stm.getDefaultTxnExecutor().executeChecked(new TxnVoidCallable() {
@Override
public void call(Txn tx) throws Exception {
ref.set(tx, 10);
barrier.joinCommit(tx);
}
});
}
};
t.setPrintStackTrace(false);
t.start();
sleepMs(500);
t.interrupt();
t.join();
t.assertFailedWithException(InterruptedException.class);
assertEquals(0, ref.atomicGet());
assertTrue(barrier.isAborted());
}
@Test
public void whenTransactionAlreadyCommitted() throws InterruptedException {
barrier = new CountDownCommitBarrier(1);
Txn tx = stm.newDefaultTxn();
tx.commit();
try {
barrier.joinCommit(tx);
fail();
} catch (DeadTxnException expected) {
}
assertIsCommitted(tx);
assertTrue(barrier.isClosed());
}
@Test
public void whenTransactionAlreadyAborted_thenDeadTxnException() throws InterruptedException {
barrier = new CountDownCommitBarrier(1);
Txn tx = stm.newDefaultTxn();
tx.abort();
try {
barrier.joinCommit(tx);
fail();
} catch (DeadTxnException expected) {
}
assertIsAborted(tx);
assertTrue(barrier.isClosed());
}
@Test
public void whenAborted_thenCommitBarrierOpenException() throws InterruptedException {
barrier = new CountDownCommitBarrier(1);
barrier.abort();
Txn tx = stm.newDefaultTxn();
try {
barrier.joinCommit(tx);
fail();
} catch (CommitBarrierOpenException expected) {
}
assertTrue(barrier.isAborted());
assertEquals(0, barrier.getNumberWaiting());
}
@Test
public void whenCommitted_thenCommitBarrierOpenException() throws InterruptedException {
barrier = new CountDownCommitBarrier(0);
Txn tx = stm.newDefaultTxn();
try {
barrier.joinCommit(tx);
fail();
} catch (CommitBarrierOpenException expected) {
}
assertTrue(barrier.isCommitted());
assertEquals(0, barrier.getNumberWaiting());
}
}