package org.multiverse.stms.gamma; import org.junit.Assert; import org.multiverse.TestUtils; import org.multiverse.api.LockMode; import org.multiverse.api.blocking.RetryLatch; import org.multiverse.api.functions.Function; import org.multiverse.stms.gamma.transactionalobjects.*; import org.multiverse.stms.gamma.transactions.GammaTxn; import org.multiverse.stms.gamma.transactions.GammaTxnConfig; import org.multiverse.stms.gamma.transactions.fat.FatVariableLengthGammaTxn; import java.util.*; import static java.lang.String.format; import static java.util.Arrays.asList; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.*; import static org.multiverse.TestUtils.getField; public class GammaTestUtils implements GammaConstants { public static GammaTxn newArrivingTransaction(GammaStm stm){ GammaTxnConfig config = new GammaTxnConfig(stm) .setMaximumPoorMansConflictScanLength(0) .setSpeculative(false); return new FatVariableLengthGammaTxn(config); } public static void assertGlobalConflictCount(GammaStm stm, long expected){ assertEquals(expected, stm.globalConflictCounter.count()); } public static void causeLotsOfConflicts(GammaStm stm) { for (int k = 0; k < 100; k++) { stm.getGlobalConflictCounter().signalConflict(); } } public static void assertHasCommutingFunctions(Tranlocal tranlocal, Function... expected) { CallableNode current = tranlocal.headCallable; List<Function> functions = new LinkedList<Function>(); while (current != null) { functions.add(current.function); current = current.next; } Assert.assertEquals(asList(expected), functions); } public static void assertSpeculativeConfigurationNonRefTypeRequired(GammaTxn tx) { assertTrue(tx.config.speculativeConfiguration.get().nonRefTypeDetected); } public static void assertHasListeners(AbstractGammaObject ref, RetryLatch... listeners) { Set<RetryLatch> expected = new HashSet<RetryLatch>(Arrays.asList(listeners)); Set<RetryLatch> found = new HashSet<RetryLatch>(); Listeners l = (Listeners) getField(ref, "listeners"); while (l != null) { found.add(l.listener); l = l.next; } Assert.assertEquals(expected, found); } public static void assertHasNoListeners(AbstractGammaObject ref) { assertHasListeners(ref); } public static void assertRefHasNoLocks(AbstractGammaObject ref) { assertLockMode(ref, LOCKMODE_NONE); assertReadLockCount(ref, 0); } public static void assertRefHasReadLock(BaseGammaTxnRef ref, GammaTxn tx) { Tranlocal tranlocal = tx.getRefTranlocal(ref); if (tranlocal == null) { fail("A Tranlocal should have been available for a ref that has the read lock"); } Assert.assertEquals(LOCKMODE_READ, tranlocal.getLockMode()); assertLockMode(ref, LOCKMODE_READ); } public static void assertRefHasNoLocks(BaseGammaTxnRef ref, GammaTxn tx) { Tranlocal tranlocal = tx.getRefTranlocal(ref); if (tranlocal != null) { Assert.assertEquals(LOCKMODE_NONE, tranlocal.getLockMode()); } assertLockMode(ref, LOCKMODE_NONE); assertReadLockCount(ref, 0); } public static void assertRefHasWriteLock(BaseGammaTxnRef ref, GammaTxn lockOwner) { Tranlocal tranlocal = lockOwner.getRefTranlocal(ref); if (tranlocal == null) { fail("A Tranlocal should have been available for a ref that has the write lock"); } Assert.assertEquals(LOCKMODE_WRITE, tranlocal.getLockMode()); assertLockMode(ref, LOCKMODE_WRITE); assertReadLockCount(ref, 0); } public static void assertRefHasExclusiveLock(BaseGammaTxnRef ref, GammaTxn lockOwner) { Tranlocal tranlocal = lockOwner.getRefTranlocal(ref); if (tranlocal == null) { fail("A tranlocal should have been stored in the transaction for the ref"); } Assert.assertEquals(LOCKMODE_EXCLUSIVE, tranlocal.getLockMode()); assertLockMode(ref, LOCKMODE_EXCLUSIVE); assertReadLockCount(ref, 0); } public static void assertRefHasLockMode(BaseGammaTxnRef ref, GammaTxn lockOwner, int lockMode) { switch (lockMode) { case LOCKMODE_NONE: assertRefHasNoLocks(ref, lockOwner); break; case LOCKMODE_READ: assertRefHasReadLock(ref, lockOwner); break; case LOCKMODE_WRITE: assertRefHasWriteLock(ref, lockOwner); break; case LOCKMODE_EXCLUSIVE: assertRefHasExclusiveLock(ref, lockOwner); break; default: throw new IllegalArgumentException(); } } public static void assertVersionAndValue(GammaTxnLong ref, long version, long value) { Assert.assertEquals("version doesn't match", version, ref.getVersion()); Assert.assertEquals("value doesn't match", value, ref.atomicWeakGet()); } public static void assertVersionAndValue(GammaTxnBoolean ref, long version, boolean value) { Assert.assertEquals("version doesn't match", version, ref.getVersion()); Assert.assertEquals("value doesn't match", value, ref.atomicWeakGet()); } public static void assertVersionAndValue(GammaTxnInteger ref, long version, int value) { Assert.assertEquals("version doesn't match", version, ref.getVersion()); Assert.assertEquals("value doesn't match", value, ref.atomicWeakGet()); } public static void assertVersionAndValue(GammaTxnDouble ref, long version, double value) { Assert.assertEquals("version doesn't match", version, ref.getVersion()); TestUtils.assertEqualsDouble(format("value doesn't match, expected %s found %s", value, ref.atomicWeakGet()),value, ref.atomicWeakGet()); } public static <E> void assertVersionAndValue(GammaTxnRef<E> ref, long version, E value) { Assert.assertEquals("version doesn't match", version, ref.getVersion()); Assert.assertSame("value doesn't match", value, ref.atomicWeakGet()); } public static void assertReadLockCount(AbstractGammaObject orec, int readLockCount) { if (readLockCount > 0) { assertEquals(LOCKMODE_READ, orec.atomicGetLockModeAsInt()); } assertEquals(readLockCount, orec.getReadLockCount()); } public static void assertLockMode(GammaObject orec, LockMode lockMode) { assertEquals(lockMode, orec.getLock().atomicGetLockMode()); } public static void assertLockMode(AbstractGammaObject orec, int lockMode) { assertEquals(lockMode, orec.atomicGetLockModeAsInt()); if (lockMode != LOCKMODE_READ) { assertEquals(0, orec.getReadLockCount()); } } public static void assertSurplus(AbstractGammaObject orec, int expectedSurplus) { assertEquals(expectedSurplus, orec.getSurplus()); } public static void assertReadBiased(AbstractGammaObject orec, boolean readBiased) { if (readBiased) { assertReadBiased(orec); } else { assertWriteBiased(orec); } } public static void assertReadBiased(AbstractGammaObject orec) { assertTrue(orec.isReadBiased()); } public static void assertWriteBiased(AbstractGammaObject orec) { assertFalse(orec.isReadBiased()); } public static void assertReadonlyCount(AbstractGammaObject orec, int expectedReadonlyCount) { assertEquals(expectedReadonlyCount, orec.getReadonlyCount()); } public static <O extends AbstractGammaObject> O makeReadBiased(O orec) { if (orec.isReadBiased()) { return orec; } int x = orec.getReadonlyCount(); for (int k = x; k < orec.getReadBiasedThreshold(); k++) { orec.arrive(1); orec.departAfterReading(); } assertReadBiased(orec); assertLockMode(orec, LOCKMODE_NONE); return orec; } }