package org.multiverse.stms.gamma.transactionalobjects.baseGammaTxnRef;
import org.junit.Before;
import org.junit.Test;
import org.multiverse.api.LockMode;
import org.multiverse.api.functions.LongFunction;
import org.multiverse.stms.gamma.GammaConstants;
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 static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.multiverse.stms.gamma.GammaTestUtils.*;
public class ReleaseAfterFailureTest implements GammaConstants {
private GammaStm stm;
@Before
public void setUp() {
stm = new GammaStm();
}
// ================================ misc ==========================
@Test
public void writeBiased_whenCommuting() {
long initialValue = 10;
GammaTxnLong ref = new GammaTxnLong(stm, initialValue);
long initialVersion = ref.getVersion();
GammaTxn tx = stm.newDefaultTxn();
LongFunction function = mock(LongFunction.class);
ref.commute(tx, function);
Tranlocal tranlocal = tx.getRefTranlocal(ref);
ref.releaseAfterFailure(tranlocal, tx.pool);
assertRefHasNoLocks(ref);
assertNull(tranlocal.owner);
assertEquals(LOCKMODE_NONE, tranlocal.getLockMode());
assertNull(tranlocal.headCallable);
assertVersionAndValue(ref, initialVersion, initialValue);
}
@Test
public void writeBiased_whenRead() {
writeBiased_whenRead(LockMode.None);
writeBiased_whenRead(LockMode.Read);
writeBiased_whenRead(LockMode.Write);
writeBiased_whenRead(LockMode.Exclusive);
}
public void writeBiased_whenRead(LockMode lockMode) {
GammaTxnLong ref = new GammaTxnLong(stm);
GammaTxn tx = stm.newDefaultTxn();
Tranlocal tranlocal = ref.openForRead(tx, lockMode.asInt());
ref.releaseAfterFailure(tranlocal, tx.pool);
assertNull(tranlocal.owner);
assertFalse(tranlocal.hasDepartObligation);
assertEquals(LOCKMODE_NONE, tranlocal.lockMode);
assertSurplus(ref, 0);
assertLockMode(ref, LockMode.None);
assertWriteBiased(ref);
assertReadonlyCount(ref, 0);
}
@Test
public void writeBiased_whenWrite() {
writeBiased_whenWrite(LockMode.None);
writeBiased_whenWrite(LockMode.Read);
writeBiased_whenWrite(LockMode.Write);
writeBiased_whenWrite(LockMode.Exclusive);
}
public void writeBiased_whenWrite(LockMode lockMode) {
GammaTxnLong ref = new GammaTxnLong(stm);
GammaTxn tx = stm.newDefaultTxn();
Tranlocal tranlocal = ref.openForWrite(tx, lockMode.asInt());
tranlocal.isDirty = true;
ref.releaseAfterFailure(tranlocal, tx.pool);
assertNull(tranlocal.owner);
assertFalse(tranlocal.hasDepartObligation);
assertEquals(LOCKMODE_NONE, tranlocal.lockMode);
assertSurplus(ref, 0);
assertLockMode(ref, LockMode.None);
assertWriteBiased(ref);
assertReadonlyCount(ref, 0);
}
// ========================= read biased ================================
@Test
public void readBiased_whenCommuting() {
long initialValue = 10;
GammaTxnLong ref = new GammaTxnLong(stm, initialValue);
long initialVersion = ref.getVersion();
GammaTxn tx = stm.newDefaultTxn();
LongFunction function = mock(LongFunction.class);
ref.commute(tx, function);
Tranlocal tranlocal = tx.getRefTranlocal(ref);
ref.releaseAfterFailure(tranlocal, tx.pool);
assertRefHasNoLocks(ref);
assertNull(tranlocal.owner);
assertEquals(LOCKMODE_NONE, tranlocal.getLockMode());
assertNull(tranlocal.headCallable);
assertVersionAndValue(ref, initialVersion, initialValue);
}
@Test
public void readBiased_whenRead() {
readBiased_whenRead(true,LockMode.None);
readBiased_whenRead(true,LockMode.Read);
readBiased_whenRead(true,LockMode.Write);
readBiased_whenRead(true,LockMode.Exclusive);
readBiased_whenRead(false,LockMode.None);
readBiased_whenRead(false,LockMode.Read);
readBiased_whenRead(false,LockMode.Write);
readBiased_whenRead(false,LockMode.Exclusive);
}
public void readBiased_whenRead(boolean additionalSurplus, LockMode lockMode) {
GammaTxnLong ref = makeReadBiased(new GammaTxnLong(stm));
if(additionalSurplus){
ref.arrive(1);
}
GammaTxn tx = newArrivingTransaction(stm);
Tranlocal tranlocal = ref.openForRead(tx, lockMode.asInt());
ref.releaseAfterFailure(tranlocal, tx.pool);
assertNull(tranlocal.owner);
assertFalse(tranlocal.hasDepartObligation);
assertEquals(LOCKMODE_NONE, tranlocal.lockMode);
assertSurplus(ref, 1);
assertLockMode(ref, LockMode.None);
assertReadBiased(ref);
assertReadonlyCount(ref, 0);
}
@Test
public void readBiased_whenWrite() {
readBiased_whenWrite(false,LockMode.None);
readBiased_whenWrite(false,LockMode.Read);
readBiased_whenWrite(false,LockMode.Write);
readBiased_whenWrite(false,LockMode.Exclusive);
readBiased_whenWrite(true,LockMode.None);
readBiased_whenWrite(true,LockMode.Read);
readBiased_whenWrite(true,LockMode.Write);
readBiased_whenWrite(true,LockMode.Exclusive);
}
public void readBiased_whenWrite(boolean additionalSurplus, LockMode lockMode) {
GammaTxnLong ref = makeReadBiased(new GammaTxnLong(stm));
if(additionalSurplus){
ref.arrive(1);
}
GammaTxn tx = newArrivingTransaction(stm);
Tranlocal tranlocal = ref.openForWrite(tx, lockMode.asInt());
tranlocal.isDirty = true;
ref.releaseAfterFailure(tranlocal, tx.pool);
assertNull(tranlocal.owner);
assertFalse(tranlocal.hasDepartObligation);
assertEquals(LOCKMODE_NONE, tranlocal.lockMode);
assertSurplus(ref, 1);
assertLockMode(ref, LockMode.None);
assertReadBiased(ref);
assertReadonlyCount(ref, 0);
}
// ================================ misc ==========================
@Test
public void whenConstructing() {
GammaTxn tx = stm.newDefaultTxn();
GammaTxnLong ref = new GammaTxnLong(tx, 0);
Tranlocal tranlocal = tx.locate(ref);
ref.releaseAfterFailure(tranlocal, tx.pool);
assertNull(tranlocal.owner);
assertFalse(tranlocal.hasDepartObligation);
assertEquals(LOCKMODE_NONE, tranlocal.lockMode);
assertSurplus(ref, 1);
assertLockMode(ref, LockMode.Exclusive);
assertWriteBiased(ref);
assertReadonlyCount(ref, 0);
}
}