package org.multiverse.stms.gamma.transactions.fat;
import org.junit.Before;
import org.junit.Test;
import org.multiverse.api.exceptions.*;
import org.multiverse.stms.gamma.GammaStm;
import org.multiverse.stms.gamma.transactionalobjects.GammaTxnLong;
import org.multiverse.stms.gamma.transactionalobjects.Tranlocal;
import org.multiverse.stms.gamma.transactions.GammaTxn;
import org.multiverse.stms.gamma.transactions.GammaTxnConfig;
import static org.junit.Assert.*;
import static org.multiverse.TestUtils.assertIsAborted;
import static org.multiverse.TestUtils.assertIsCommitted;
import static org.multiverse.stms.gamma.GammaTestUtils.*;
public abstract class FatGammaTxn_openForConstructionTest<T extends GammaTxn> {
protected GammaStm stm;
@Before
public void setUp() {
stm = new GammaStm();
}
protected abstract T newTransaction();
protected abstract T newTransaction(GammaTxnConfig config);
@Test
public void whenReadonlyTransaction() {
GammaTxnLong ref = new GammaTxnLong(stm);
GammaTxnConfig config = new GammaTxnConfig(stm)
.setReadonly(true);
GammaTxn tx = newTransaction(config);
try {
ref.openForConstruction(tx);
fail();
} catch (ReadonlyException expected) {
}
assertIsAborted(tx);
}
@Test
public void whenSuccess() {
T tx = newTransaction();
long initialVersion = 10;
GammaTxnLong ref = new GammaTxnLong(tx, initialVersion);
Tranlocal tranlocal = tx.locate(ref);
assertNotNull(tranlocal);
assertRefHasExclusiveLock(ref, tx);
assertTrue(tx.hasWrites);
assertSame(ref, tranlocal.owner);
assertEquals(LOCKMODE_EXCLUSIVE, tranlocal.getLockMode());
assertEquals(TRANLOCAL_CONSTRUCTING, tranlocal.getMode());
assertTrue(tranlocal.isDirty);
assertRefHasExclusiveLock(ref, tx);
}
@Test
public void whenAlreadyOpenedForConstruction() {
T tx = newTransaction();
long initialVersion = 10;
GammaTxnLong ref = new GammaTxnLong(tx, initialVersion);
Tranlocal tranlocal = ref.openForConstruction(tx);
assertNotNull(tranlocal);
assertRefHasExclusiveLock(ref, tx);
assertTrue(tx.hasWrites);
assertSame(ref, tranlocal.owner);
assertEquals(LOCKMODE_EXCLUSIVE, tranlocal.getLockMode());
assertEquals(TRANLOCAL_CONSTRUCTING, tranlocal.getMode());
assertTrue(tranlocal.isDirty);
assertRefHasExclusiveLock(ref, tx);
}
@Test
public void whenStmMismatch() {
GammaStm otherStm = new GammaStm();
GammaTxnLong ref = new GammaTxnLong(otherStm);
GammaTxn tx = newTransaction();
try {
ref.openForConstruction(tx);
fail();
} catch (StmMismatchException expected) {
}
assertIsAborted(tx);
}
// ==========================================
@Test
public void commuting_whenCommuting_thenFailure() {
long initialValue = 10;
T tx = newTransaction();
tx.evaluatingCommute = true;
try{
new GammaTxnLong(tx, initialValue);
fail();
}catch(IllegalCommuteException expected){
}
assertIsAborted(tx);
}
@Test
public void whenTransactionAlreadyPrepared() {
GammaTxn tx = newTransaction();
tx.prepare();
try {
new GammaTxnLong(tx);
fail();
} catch (PreparedTxnException expected) {
}
assertIsAborted(tx);
}
@Test
public void whenTransactionAlreadyAborted() {
GammaTxn tx = newTransaction();
tx.abort();
GammaTxnLong ref = new GammaTxnLong(stm);
try {
ref.openForConstruction(tx);
fail();
} catch (DeadTxnException expected) {
}
assertIsAborted(tx);
}
@Test
public void whenTransactionAlreadyCommitted() {
GammaTxn tx = newTransaction();
tx.commit();
GammaTxnLong ref = new GammaTxnLong(stm);
try {
ref.openForConstruction(tx);
fail();
} catch (DeadTxnException expected) {
}
assertIsCommitted(tx);
}
}