package games.strategy.thread; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public final class LockUtilTest { private final LockUtil lockUtil = LockUtil.INSTANCE; @Mock private LockUtil.ErrorReporter errorReporter; private LockUtil.ErrorReporter oldErrorReporter; @Before public void setUp() { oldErrorReporter = lockUtil.setErrorReporter(errorReporter); } @After public void tearDown() { lockUtil.setErrorReporter(oldErrorReporter); } @Test public void testEmpty() { assertFalse(lockUtil.isLockHeld(new ReentrantLock())); } @Test public void testMultipleLocks() { final List<Lock> locks = new ArrayList<>(); for (int i = 0; i < 10; i++) { locks.add(new ReentrantLock()); } for (final Lock l : locks) { lockUtil.acquireLock(l); assertTrue(lockUtil.isLockHeld(l)); } for (final Lock l : locks) { lockUtil.releaseLock(l); assertFalse(lockUtil.isLockHeld(l)); } assertNoErrorOccurred(); // repeat the sequence, make sure no errors for (final Lock l : locks) { lockUtil.acquireLock(l); } assertNoErrorOccurred(); } @Test public void testFail() { final Lock l1 = new ReentrantLock(); final Lock l2 = new ReentrantLock(); // acquire in the correct order lockUtil.acquireLock(l1); lockUtil.acquireLock(l2); // release lockUtil.releaseLock(l2); lockUtil.releaseLock(l1); assertNoErrorOccurred(); // acquire locks in the wrong order lockUtil.acquireLock(l2); lockUtil.acquireLock(l1); assertErrorOccurred(); } @Test public void testAcquireTwice() { final ReentrantLock l1 = new ReentrantLock(); lockUtil.acquireLock(l1); lockUtil.acquireLock(l1); lockUtil.releaseLock(l1); lockUtil.releaseLock(l1); assertEquals(0, l1.getHoldCount()); assertFalse(lockUtil.isLockHeld(l1)); } private void assertErrorOccurred() { verify(errorReporter).reportError(isA(Lock.class), isA(Lock.class)); } private void assertNoErrorOccurred() { verify(errorReporter, never()).reportError(isA(Lock.class), isA(Lock.class)); } }