/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.github.geophile.erdo.transaction;
import com.github.geophile.erdo.TestFactory;
import com.github.geophile.erdo.TestKey;
import org.junit.*;
import java.util.Set;
import static org.junit.Assert.*;
@Ignore // LockManagerBucket flag to turn off waiting has been discontinued
public class DeadlockDetectorTest
{
@BeforeClass
public static void beforeClass()
{
Transaction.initialize(FACTORY);
}
@Before
public void before()
{
lockManager = new LockManager();
lockManager.waitOnConflict(false);
a = new TestThread(lockManager);
b = new TestThread(lockManager);
c = new TestThread(lockManager);
d = new TestThread(lockManager);
}
@After
public void after()
{
FACTORY.reset();
}
@Test
public void testEmpty()
{
DeadlockDetector deadlockDetector = new DeadlockDetector(lockManager);
assertTrue(deadlockDetector.victims().isEmpty());
}
@Test
public void testOneWaiter() throws Exception
{
a.lock(key(0));
DeadlockDetector deadlockDetector = new DeadlockDetector(lockManager);
assertTrue(deadlockDetector.victims().isEmpty());
}
@Test
public void testDeadlockOf2() throws Exception
{
TestKey k0 = key(0);
TestKey k1 = key(1);
a.lock(k0);
b.lock(k1);
a.lock(k1);
b.lock(k0);
DeadlockDetector deadlockDetector = new DeadlockDetector(lockManager);
Set<Transaction> victims = deadlockDetector.victims();
assertEquals(1, victims.size());
assertEquals(latestStart(a, b).transaction(), victims.iterator().next());
}
@Test
public void testDeadlockOf3() throws Exception
{
TestKey k0 = key(0);
TestKey k1 = key(1);
TestKey k2 = key(2);
a.lock(k0);
b.lock(k1);
c.lock(k2);
a.lock(k1);
b.lock(k2);
c.lock(k0);
DeadlockDetector deadlockDetector = new DeadlockDetector(lockManager);
Set<Transaction> victims = deadlockDetector.victims();
assertEquals(1, victims.size());
assertEquals(latestStart(a, b, c).transaction(), victims.iterator().next());
}
@Test
public void testDeadlockWithPileup() throws Exception
{
TestKey k1 = key(1);
TestKey k2 = key(2);
b.lock(k1);
c.lock(k2);
b.lock(k2);
c.lock(k1);
a.lock(k1);
DeadlockDetector deadlockDetector = new DeadlockDetector(lockManager);
Set<Transaction> victims = deadlockDetector.victims();
assertEquals(1, victims.size());
assertEquals(latestStart(b, c).transaction(), victims.iterator().next());
}
@Test
public void testTwoDeadlocks() throws Exception
{
TestKey k0 = key(0);
TestKey k1 = key(1);
TestKey k2 = key(2);
TestKey k3 = key(3);
a.lock(k0);
b.lock(k1);
a.lock(k1);
b.lock(k0);
c.lock(k2);
d.lock(k3);
c.lock(k3);
d.lock(k2);
DeadlockDetector deadlockDetector = new DeadlockDetector(lockManager);
Set<Transaction> victims = deadlockDetector.victims();
int count = 0;
for (Transaction victim : victims) {
if (victim == latestStart(a, b).transaction() || victim == latestStart(c, d).transaction()) {
count++;
} else {
fail();
}
}
assertEquals(2, count);
}
private TestThread latestStart(TestThread... threads)
{
TestThread earliest = null;
for (TestThread thread : threads) {
if (earliest == null ||
thread.transaction().startTime() > earliest.transaction().startTime()) {
earliest = thread;
}
}
return earliest;
}
private TestKey key(int key)
{
return new TestKey(key);
}
private static final TestFactory FACTORY = new TestFactory();
private LockManager lockManager;
private TestThread a;
private TestThread b;
private TestThread c;
private TestThread d;
}