feat: des beaux tests sur CentralizedLinda, avec un beau code coverage

This commit is contained in:
Laureηt 2021-12-29 15:51:53 +01:00
parent 717964daca
commit 24810c2250
No known key found for this signature in database
GPG key ID: D88C6B294FD40994
4 changed files with 467 additions and 196 deletions

View file

@ -7,5 +7,6 @@
"**/.DS_Store": true, "**/.DS_Store": true,
"**/Thumbs.db": true, "**/Thumbs.db": true,
"**/*.class": true "**/*.class": true
} },
"java.configuration.updateBuildConfiguration": "automatic"
} }

View file

@ -1,7 +1,6 @@
plugins { plugins {
id 'java' id 'java'
id 'eclipse' // optional (to generate Eclipse project files) id 'jacoco'
id 'idea' // optional (to generate IntelliJ IDEA project files)
} }
repositories { repositories {
@ -15,4 +14,9 @@ dependencies {
test { test {
useJUnitPlatform() useJUnitPlatform()
finalizedBy jacocoTestReport
}
jacocoTestReport {
dependsOn test
} }

View file

@ -14,7 +14,7 @@ import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
class Reveil implements Callback { class Reveil {
Lock lock = new ReentrantLock(); Lock lock = new ReentrantLock();
@ -26,10 +26,6 @@ class Reveil implements Callback {
this.condition = lock.newCondition(); this.condition = lock.newCondition();
} }
public void call(Tuple t) {
return;
}
void sleep() { void sleep() {
try { try {
lock.lock(); lock.lock();
@ -52,7 +48,7 @@ class Reveil implements Callback {
/** Shared memory implementation of Linda. */ /** Shared memory implementation of Linda. */
public class CentralizedLinda implements Linda { public class CentralizedLinda implements Linda {
protected List<Tuple> tuples; List<Tuple> tuples;
List<Reveil> reveils; List<Reveil> reveils;
public CentralizedLinda() { public CentralizedLinda() {
@ -116,6 +112,7 @@ public class CentralizedLinda implements Linda {
* @param template the Tuple template your looking for * @param template the Tuple template your looking for
*/ */
public Tuple tryTake(Tuple template) { public Tuple tryTake(Tuple template) {
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator(); Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null; Tuple next = null;
@ -126,6 +123,30 @@ public class CentralizedLinda implements Linda {
return next; return next;
} }
} }
}
return null;
}
/**
* Extract the tuple from the symetric difference of the Tuple-Space and the
* given tuple list. (non-blocking)
*
* @param template the Tuple template your looking for
* @param excluded the list of Tuples to exclude from the search
*/
private Tuple tryTake(Tuple template, Collection<Tuple> excluded) {
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template) && !excluded.contains(next)) {
iterator.remove();
return next;
}
}
}
return null; return null;
} }
@ -135,25 +156,50 @@ public class CentralizedLinda implements Linda {
* @param template the Tuple template your looking for * @param template the Tuple template your looking for
*/ */
public Tuple tryRead(Tuple template) { public Tuple tryRead(Tuple template) {
synchronized (tuples) {
Tuple next = null;
Iterator<Tuple> iterator = tuples.iterator();
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
return next;
}
}
}
return null;
}
/**
* Get the tuple from the symetric difference of the Tuple-Space and the given
* tuple list. (non-blocking)
*
* @param template the Tuple template your looking for
* @param excluded the list of Tuples to exclude from the search
*/
private Tuple tryRead(Tuple template, Collection<Tuple> excluded) {
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator(); Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null; Tuple next = null;
while (iterator.hasNext()) { while (iterator.hasNext()) {
next = iterator.next(); next = iterator.next();
if (next.matches(template)) { if (next.matches(template) && !excluded.contains(next)) {
break;
}
}
return next; return next;
} }
}
}
return null;
}
/** /**
* Extract the tuples in the tuple list. (blocking) * Extract the tuples in the tuple list. (non-blocking)
* *
* @param template the Tuple template your looking for * @param template the Tuple template your looking for
*/ */
public Collection<Tuple> takeAll(Tuple template) { public Collection<Tuple> takeAll(Tuple template) {
List<Tuple> results = new ArrayList<Tuple>(); List<Tuple> results = new ArrayList<Tuple>();
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator(); Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null; Tuple next = null;
@ -164,6 +210,7 @@ public class CentralizedLinda implements Linda {
iterator.remove(); iterator.remove();
} }
} }
}
return results; return results;
} }
@ -173,7 +220,8 @@ public class CentralizedLinda implements Linda {
* @param template the Tuple template your looking for * @param template the Tuple template your looking for
*/ */
public Collection<Tuple> readAll(Tuple template) { public Collection<Tuple> readAll(Tuple template) {
List<Tuple> results = new ArrayList<Tuple>(); Collection<Tuple> results = new ArrayList<Tuple>();
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator(); Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null; Tuple next = null;
@ -183,46 +231,39 @@ public class CentralizedLinda implements Linda {
results.add(next); results.add(next);
} }
} }
}
return results; return results;
} }
public void eventRegister(eventMode mode, eventTiming timing, Tuple template, Callback callback) { public void eventRegister(eventMode mode, eventTiming timing, Tuple template, Callback callback) {
new Thread() { new Thread() {
public void run() { public void run() {
switch (timing) { switch (timing) {
case IMMEDIATE: case IMMEDIATE:
callback.call(mode == eventMode.READ ? read(template) : take(template)); callback.call(mode == eventMode.READ ? read(template) : take(template));
return; return;
case FUTURE: case FUTURE:
List<Tuple> knownTuples = (List<Tuple>) readAll(template); Collection<Tuple> knownTuples = new ArrayList<Tuple>();
callback.call(tryRTknown(template, knownTuples, mode)); for (Tuple t : tuples) {
knownTuples.add((Tuple) t.clone());
}
callback.call(future_search(template, knownTuples, mode));
return; return;
} }
} }
}.start(); }.start();
} }
private Tuple tryRTknown(Tuple template, List<Tuple> knownTuples, eventMode mode) { private Tuple future_search(Tuple template, Collection<Tuple> knownTuples, eventMode mode) {
Tuple result = null;
Reveil reveil = new Reveil(template); Reveil reveil = new Reveil(template);
reveils.add(reveil); reveils.add(reveil);
Tuple result = null; result = mode == eventMode.READ ? tryRead(template, knownTuples) : tryTake(template, knownTuples);
for (int i = 0; i < tuples.size(); i++) {
result = mode == eventMode.READ ? tuples.get(i) : tuples.remove(i);
if (result.matches(template)) {
return result;
}
}
while (result == null) { while (result == null) {
reveil.sleep(); reveil.sleep();
for (int i = 0; i < tuples.size(); i++) { result = mode == eventMode.READ ? tryRead(template, knownTuples) : tryTake(template, knownTuples);
result = mode == eventMode.READ ? tuples.get(i) : tuples.remove(i);
if (result.matches(template)) {
return result;
}
}
} }
return result; return result;
} }

View file

@ -5,13 +5,17 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import linda.Callback;
import linda.Linda; import linda.Linda;
import linda.Tuple; import linda.Tuple;
import linda.Linda.eventMode;
import linda.Linda.eventTiming;
import linda.shm.CentralizedLinda; import linda.shm.CentralizedLinda;
public class CentralizedLindaTests { public class CentralizedLindaTests {
@ -23,6 +27,10 @@ public class CentralizedLindaTests {
linda = new CentralizedLinda(); linda = new CentralizedLinda();
} }
@Nested
@DisplayName("read related tests")
class ReadTests {
@Test @Test
void testTryRead() { void testTryRead() {
Tuple tuple_write, tuple_template, tuple_read; Tuple tuple_write, tuple_template, tuple_read;
@ -48,31 +56,6 @@ public class CentralizedLindaTests {
assertEquals(tuple_read, tuple_write); assertEquals(tuple_read, tuple_write);
} }
@Test
void testTryTake() {
Tuple tuple_write, tuple_template, tuple_read;
tuple_template = new Tuple(0);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, null);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, null);
tuple_write = new Tuple(0);
linda.write(tuple_write);
linda.write(tuple_write);
tuple_template = new Tuple(0);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, tuple_write);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, tuple_write);
}
@Test @Test
void testRead() { void testRead() {
Tuple tuple_write, tuple_template, tuple_read; Tuple tuple_write, tuple_template, tuple_read;
@ -90,20 +73,43 @@ public class CentralizedLindaTests {
} }
@Test @Test
void testTake() { void testEmptyRead() {
Tuple tuple_write, tuple_template, tuple_read; Thread mainRunner = new Thread(() -> {
Tuple tuple_template;
tuple_write = new Tuple(0);
linda.write(tuple_write);
linda.write(tuple_write);
tuple_template = new Tuple(0);
tuple_read = linda.take(tuple_template);
assertEquals(tuple_read, tuple_write);
tuple_template = new Tuple(Integer.class); tuple_template = new Tuple(Integer.class);
tuple_read = linda.take(tuple_template); linda.read(tuple_template);
});
mainRunner.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
assertEquals(Thread.State.WAITING, mainRunner.getState());
mainRunner.interrupt();
}
}
@Test
void testWaitingRead() throws InterruptedException {
Tuple tuple_write = new Tuple(0);
Thread runnerExact = new Thread(() -> {
Tuple tuple_template = new Tuple(Integer.class);
Tuple tuple_read = linda.read(tuple_template);
assertEquals(tuple_read, tuple_write); assertEquals(tuple_read, tuple_write);
});
runnerExact.start();
Thread runnerType = new Thread(() -> {
Tuple tuple_template = new Tuple(Integer.class);
Tuple tuple_read = linda.read(tuple_template);
assertEquals(tuple_read, tuple_write);
});
runnerType.start();
Thread.sleep(1000);
linda.write(tuple_write);
} }
@Test @Test
@ -141,6 +147,95 @@ public class CentralizedLindaTests {
assertNotEquals(linda.tryRead(tuple_template), null); assertNotEquals(linda.tryRead(tuple_template), null);
assertNotEquals(linda.tryRead(new Tuple(String.class)), null); assertNotEquals(linda.tryRead(new Tuple(String.class)), null);
} }
}
@Nested
@DisplayName("Take related tests")
class TakeTests {
@Test
void testTryTake() {
Tuple tuple_write, tuple_template, tuple_read;
tuple_template = new Tuple(0);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, null);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, null);
tuple_write = new Tuple(0);
linda.write(tuple_write);
linda.write(tuple_write);
tuple_template = new Tuple(0);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, tuple_write);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.tryTake(tuple_template);
assertEquals(tuple_read, tuple_write);
}
@Test
void testWaitingTake() throws InterruptedException {
Tuple tuple_write = new Tuple(0);
Thread runnerExact = new Thread(() -> {
Tuple tuple_template = new Tuple(Integer.class);
Tuple tuple_read = linda.take(tuple_template);
assertEquals(tuple_read, tuple_write);
});
runnerExact.start();
Thread runnerType = new Thread(() -> {
Tuple tuple_template = new Tuple(Integer.class);
Tuple tuple_read = linda.take(tuple_template);
assertEquals(tuple_read, tuple_write);
});
runnerType.start();
Thread.sleep(500);
linda.write(tuple_write);
Thread.sleep(500);
linda.write(tuple_write);
}
@Test
void testEmptyTake() {
Thread mainRunner = new Thread(() -> {
Tuple tuple_template;
tuple_template = new Tuple(Integer.class);
linda.take(tuple_template);
});
mainRunner.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
assertEquals(Thread.State.WAITING, mainRunner.getState());
mainRunner.interrupt();
}
}
@Test
void testTake() {
Tuple tuple_write, tuple_template, tuple_read;
tuple_write = new Tuple(0);
linda.write(tuple_write);
linda.write(tuple_write);
tuple_template = new Tuple(0);
tuple_read = linda.take(tuple_template);
assertEquals(tuple_read, tuple_write);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.take(tuple_template);
assertEquals(tuple_read, tuple_write);
}
@Test @Test
void testTakeAll() { void testTakeAll() {
@ -177,5 +272,135 @@ public class CentralizedLindaTests {
assertEquals(linda.tryTake(tuple_template), null); assertEquals(linda.tryTake(tuple_template), null);
assertNotEquals(linda.tryTake(new Tuple(String.class)), null); assertNotEquals(linda.tryTake(new Tuple(String.class)), null);
} }
}
@Nested
@DisplayName("eventRegister related tests")
class EventRegisterTests {
final Tuple tuple_write = new Tuple(0);
Callback assertCallback = new Callback() {
@Override
public void call(Tuple t) {
assertEquals(t, tuple_write);
}
};
@Test
void IMMEDIATE_READ_test() throws InterruptedException {
Thread runnerExact = new Thread(() -> {
Tuple tuple_template = new Tuple(0);
linda.eventRegister(
eventMode.READ,
eventTiming.IMMEDIATE,
tuple_template,
assertCallback);
});
runnerExact.start();
Thread runnerType = new Thread(() -> {
Tuple tuple_template = new Tuple(Integer.class);
linda.eventRegister(
eventMode.READ,
eventTiming.IMMEDIATE,
tuple_template,
assertCallback);
});
runnerType.start();
Thread.sleep(1000);
linda.write(tuple_write);
}
@Test
void IMMEDIATE_TAKE_test() throws InterruptedException {
linda.write(new Tuple("999"));
Thread runnerExact = new Thread(() -> {
Tuple tuple_template = new Tuple(0);
linda.eventRegister(
eventMode.TAKE,
eventTiming.IMMEDIATE,
tuple_template,
assertCallback);
});
runnerExact.start();
Thread runnerType = new Thread(() -> {
Tuple tuple_template = new Tuple(Integer.class);
linda.eventRegister(
eventMode.TAKE,
eventTiming.IMMEDIATE,
tuple_template,
assertCallback);
});
runnerType.start();
Thread.sleep(500);
linda.write(tuple_write);
Thread.sleep(500);
linda.write(tuple_write);
}
@Test
void FUTURE_READ_test() throws InterruptedException {
linda.write(new Tuple(999));
linda.write(new Tuple("999"));
Thread runnerExact = new Thread(() -> {
Tuple tuple_template = new Tuple(0);
linda.eventRegister(
eventMode.READ,
eventTiming.FUTURE,
tuple_template,
assertCallback);
});
runnerExact.start();
// Thread runnerType = new Thread(() -> {
// Tuple tuple_template = new Tuple(Integer.class);
// linda.eventRegister(
// eventMode.READ,
// eventTiming.FUTURE,
// tuple_template,
// assertCallback);
// });
// runnerType.start();
Thread.sleep(1000);
linda.write(tuple_write);
}
@Test
void FUTURE_TAKE_test() throws InterruptedException {
linda.write(new Tuple(999));
linda.write(new Tuple("999"));
Thread runnerExact = new Thread(() -> {
Tuple tuple_template = new Tuple(0);
linda.eventRegister(
eventMode.TAKE,
eventTiming.FUTURE,
tuple_template,
assertCallback);
});
runnerExact.start();
Thread runnerType = new Thread(() -> {
Tuple tuple_template = new Tuple(Integer.class);
linda.eventRegister(
eventMode.TAKE,
eventTiming.FUTURE,
tuple_template,
assertCallback);
});
runnerType.start();
Thread.sleep(500);
linda.write(tuple_write);
Thread.sleep(500);
linda.write(tuple_write);
}
}
} }