Archived
0

LockObserveList implementation, tests for Lock and List

This commit is contained in:
Daniil
2018-08-05 13:40:02 +07:00
parent b5a7942b67
commit 6ab8658399
3 changed files with 150 additions and 9 deletions

View File

@@ -6,17 +6,23 @@ package mc.core;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import mc.core.world.Chunk;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.io.Serializable; import java.io.Serializable;
@AllArgsConstructor @AllArgsConstructor
@Data @Data
public class Location implements Serializable{ public class Location implements Serializable {
private double x, y, z; private double x, y, z;
public Location(long compactValue) {
set(compactValue);
}
private static int floor_double(double value) { private static int floor_double(double value) {
int i = (int)value; int i = (int) value;
return value < (double)i ? i - 1 : i; return value < (double) i ? i - 1 : i;
} }
public static Location copyOf(Location location) { public static Location copyOf(Location location) {
@@ -27,12 +33,8 @@ public class Location implements Serializable{
); );
} }
public static Location startPointLocation () { public static Location startPointLocation() {
return new Location(0,10,0); return new Location(0, 10, 0);
}
public Location(long compactValue) {
set(compactValue);
} }
public void set(Location location) { public void set(Location location) {
@@ -55,6 +57,11 @@ public class Location implements Serializable{
); );
} }
public Chunk getChunk() {
// TODO: Implement
throw new NotImplementedException();
}
public int getBlockX() { public int getBlockX() {
return (int) x; return (int) x;
} }

View File

@@ -0,0 +1,44 @@
package mc.core.events.lock;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class LockObserveList implements Consumer<PoorMansLock> {
private List<PoorMansLock> locks = new ArrayList<>();
private Runnable callback;
public void setCallback(Runnable callback) {
this.callback = callback;
}
public void add(PoorMansLock lock) {
locks.add(lock);
lock.addCallback(this);
}
public void release() {
for (PoorMansLock lock : locks) {
lock.removeCallback(this);
}
locks.clear();
}
public boolean isReady() {
for (PoorMansLock lock : locks) {
if (lock.isLocked())
return false;
}
return true;
}
@Override
public void accept(PoorMansLock lock) {
if (!lock.isLocked()) {
if (isReady()) {
if (callback != null)
callback.run();
}
}
}
}

View File

@@ -0,0 +1,90 @@
package mc.core.events;
import mc.core.events.lock.LockObserveList;
import mc.core.events.lock.PoorMansLock;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
public class LockTest {
@Test
public void basicTest() throws InterruptedException {
AtomicBoolean engageCallbackCalled = new AtomicBoolean(false);
AtomicBoolean disengageCallbackCalled = new AtomicBoolean(false);
PoorMansLock lock = new PoorMansLock();
lock.addCallback(lock1 -> {
if (lock1.isLocked())
engageCallbackCalled.set(true);
else
disengageCallbackCalled.set(true);
});
lock.lock();
Assert.assertTrue("Lock is not locked", lock.isLocked());
Assert.assertTrue("Engage callback was not called", engageCallbackCalled.get());
engageCallbackCalled.set(false);
try {
lock.lock();
Assert.assertFalse("Engage callback was called from attempt to block from the same thread", engageCallbackCalled.get());
} catch (Exception ex) {
Assert.fail("Exception fired while attempting to lock from the same thread");
return;
}
Assert.assertFalse("Disengage callback was called while not actually disengaging [x1]", disengageCallbackCalled.get());
AtomicBoolean lockExceptionFired = new AtomicBoolean(false);
AtomicBoolean unlockExceptionFired = new AtomicBoolean(false);
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
try {
lock.lock();
} catch (Exception ex) {
lockExceptionFired.set(true);
}
try {
lock.unlock();
} catch (Exception ex) {
unlockExceptionFired.set(true);
}
latch.countDown();
}).start();
latch.await();
Assert.assertTrue("Exception was not fired on concurrent lock attempt", lockExceptionFired.get());
Assert.assertTrue("Exception was not fired on non-owner unlock attempt", unlockExceptionFired.get());
Assert.assertFalse("Disengage callback was called while not actually disengaging [x2]", disengageCallbackCalled.get());
lock.unlock();
Assert.assertTrue("Disengage callback was on called on lock disengage", disengageCallbackCalled.get());
}
@Test
public void observeListTest() {
PoorMansLock lock1 = new PoorMansLock();
PoorMansLock lock2 = new PoorMansLock();
LockObserveList list = new LockObserveList();
list.add(lock1);
list.add(lock2);
Assert.assertTrue("LockObserveList was no able to correctly identify lock states for unlocked locks", list.isReady());
lock1.lock();
Assert.assertFalse("LockObserveList was no able to correctly identify lock states for list with one locked lock", list.isReady());
AtomicBoolean listReadyCallbackCalled = new AtomicBoolean(false);
list.setCallback(() -> listReadyCallbackCalled.set(true));
lock2.lock();
Assert.assertFalse("Callback was called when another lock got engaged", listReadyCallbackCalled.get());
lock1.unlock();
Assert.assertFalse("Callback was called while one lock is still locked", listReadyCallbackCalled.get());
lock2.unlock();
Assert.assertTrue("Callback was not called when both locks are actually free", listReadyCallbackCalled.get());
}
}