package org.multiverse.stms.gamma.integration.locking;
import org.junit.Before;
import org.junit.Test;
import org.multiverse.api.exceptions.ReadWriteConflict;
import org.multiverse.stms.gamma.GammaStm;
import org.multiverse.stms.gamma.transactionalobjects.GammaTxnLong;
import org.multiverse.stms.gamma.transactions.GammaTxn;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.multiverse.TestUtils.assertIsAborted;
import static org.multiverse.TestUtils.assertIsCommitted;
import static org.multiverse.api.GlobalStmInstance.getGlobalStmInstance;
import static org.multiverse.api.TxnThreadLocal.clearThreadLocalTxn;
import static org.multiverse.stms.gamma.GammaTestUtils.assertRefHasNoLocks;
public class EnsureTest {
private GammaStm stm;
@Before
public void setUp() {
stm = (GammaStm) getGlobalStmInstance();
clearThreadLocalTxn();
}
@Test
public void whenOnlyReadsThenIgnored() {
GammaTxnLong ref = new GammaTxnLong(stm);
GammaTxn tx = stm.newDefaultTxn();
ref.get(tx);
ref.ensure(tx);
ref.atomicIncrementAndGet(1);
tx.commit();
assertIsCommitted(tx);
assertRefHasNoLocks(ref);
}
@Test
public void whenUpdateTransactionButNoConflictOnRead_thenSuccess() {
long initialValue = 10;
GammaTxnLong ref1 = new GammaTxnLong(stm, initialValue);
GammaTxnLong ref2 = new GammaTxnLong(stm, initialValue);
GammaTxn tx = stm.newDefaultTxn();
ref1.get(tx);
ref1.ensure(tx);
ref2.increment(tx);
tx.commit();
assertIsCommitted(tx);
assertEquals(initialValue, ref1.atomicGet());
assertEquals(initialValue + 1, ref2.atomicGet());
}
@Test
public void whenUpdateTransactionAndConflictOnRead_thenReadWriteConflict() {
long initialValue = 10;
GammaTxnLong ref1 = new GammaTxnLong(stm, initialValue);
GammaTxnLong ref2 = new GammaTxnLong(stm, initialValue);
GammaTxn tx = stm.newDefaultTxn();
ref1.get(tx);
ref1.ensure(tx);
ref2.increment(tx);
ref1.atomicIncrementAndGet(1);
try {
tx.commit();
fail();
} catch (ReadWriteConflict expected) {
}
assertIsAborted(tx);
assertEquals(initialValue + 1, ref1.atomicGet());
assertEquals(initialValue, ref2.atomicGet());
}
}