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,14 +112,39 @@ 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) {
Iterator<Tuple> iterator = tuples.iterator(); synchronized (tuples) {
Tuple next = null; Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
while (iterator.hasNext()) { while (iterator.hasNext()) {
next = iterator.next(); next = iterator.next();
if (next.matches(template)) { if (next.matches(template)) {
iterator.remove(); iterator.remove();
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,33 +156,59 @@ 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) {
Iterator<Tuple> iterator = tuples.iterator(); synchronized (tuples) {
Tuple next = null; Tuple next = null;
Iterator<Tuple> iterator = tuples.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
next = iterator.next(); next = iterator.next();
if (next.matches(template)) { if (next.matches(template)) {
break; return next;
}
} }
} }
return next; return null;
} }
/** /**
* Extract the tuples in the tuple list. (blocking) * 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();
Tuple next = null;
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template) && !excluded.contains(next)) {
return next;
}
}
}
return null;
}
/**
* 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>();
Iterator<Tuple> iterator = tuples.iterator(); synchronized (tuples) {
Tuple next = null; Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
while (iterator.hasNext()) { while (iterator.hasNext()) {
next = iterator.next(); next = iterator.next();
if (next.matches(template)) { if (next.matches(template)) {
results.add(next); results.add(next);
iterator.remove(); iterator.remove();
}
} }
} }
return results; return results;
@ -173,14 +220,16 @@ 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>();
Iterator<Tuple> iterator = tuples.iterator(); synchronized (tuples) {
Tuple next = null; Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
while (iterator.hasNext()) { while (iterator.hasNext()) {
next = iterator.next(); next = iterator.next();
if (next.matches(template)) { if (next.matches(template)) {
results.add(next); results.add(next);
}
} }
} }
return results; return results;
@ -189,40 +238,32 @@ public class CentralizedLinda implements Linda {
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,159 +27,380 @@ public class CentralizedLindaTests {
linda = new CentralizedLinda(); linda = new CentralizedLinda();
} }
@Test @Nested
void testTryRead() { @DisplayName("read related tests")
Tuple tuple_write, tuple_template, tuple_read; class ReadTests {
tuple_template = new Tuple(0); @Test
tuple_read = linda.tryRead(tuple_template); void testTryRead() {
assertEquals(tuple_read, null); Tuple tuple_write, tuple_template, tuple_read;
tuple_template = new Tuple(Integer.class); tuple_template = new Tuple(0);
tuple_read = linda.tryRead(tuple_template); tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, null); assertEquals(tuple_read, null);
tuple_write = new Tuple(0); tuple_template = new Tuple(Integer.class);
linda.write(tuple_write); tuple_read = linda.tryRead(tuple_template);
linda.write(tuple_write); assertEquals(tuple_read, null);
tuple_template = new Tuple(0); tuple_write = new Tuple(0);
tuple_read = linda.tryRead(tuple_template); linda.write(tuple_write);
assertEquals(tuple_read, tuple_write); linda.write(tuple_write);
tuple_template = new Tuple(Integer.class); tuple_template = new Tuple(0);
tuple_read = linda.tryRead(tuple_template); tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, tuple_write); assertEquals(tuple_read, tuple_write);
}
@Test tuple_template = new Tuple(Integer.class);
void testTryTake() { tuple_read = linda.tryRead(tuple_template);
Tuple tuple_write, tuple_template, tuple_read; assertEquals(tuple_read, tuple_write);
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 testRead() {
Tuple tuple_write, tuple_template, tuple_read;
tuple_write = new Tuple(0);
linda.write(tuple_write);
tuple_template = new Tuple(0);
tuple_read = linda.read(tuple_template);
assertEquals(tuple_read, tuple_write);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.read(tuple_template);
assertEquals(tuple_read, tuple_write);
}
@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
void testReadAll() {
Tuple tuple_template;
Collection<Tuple> tuples_write, tuples_read, tuples_expected;
tuples_write = new ArrayList<Tuple>();
tuples_expected = new ArrayList<Tuple>();
tuples_write.add(new Tuple(0));
tuples_expected.add(new Tuple(0));
tuples_write.add(new Tuple(1));
tuples_expected.add(new Tuple(1));
tuples_write.add(new Tuple(2));
tuples_expected.add(new Tuple(2));
tuples_write.add(new Tuple("3"));
tuples_write.add(new Tuple("4"));
tuples_write.add(new Tuple(5));
tuples_expected.add(new Tuple(5));
for (Tuple tuple : tuples_write) {
linda.write(tuple);
} }
tuple_template = new Tuple(Integer.class); @Test
tuples_read = linda.readAll(tuple_template); void testRead() {
assertEquals(tuples_read, tuples_expected); Tuple tuple_write, tuple_template, tuple_read;
assertNotEquals(linda.tryRead(tuple_template), null); tuple_write = new Tuple(0);
assertNotEquals(linda.tryRead(new Tuple(String.class)), null); linda.write(tuple_write);
}
@Test tuple_template = new Tuple(0);
void testTakeAll() { tuple_read = linda.read(tuple_template);
Tuple tuple_template; assertEquals(tuple_read, tuple_write);
Collection<Tuple> tuples_write, tuples_read, tuples_expected;
tuples_write = new ArrayList<Tuple>(); tuple_template = new Tuple(Integer.class);
tuples_expected = new ArrayList<Tuple>(); tuple_read = linda.read(tuple_template);
assertEquals(tuple_read, tuple_write);
tuples_write.add(new Tuple(0));
tuples_expected.add(new Tuple(0));
tuples_write.add(new Tuple(1));
tuples_expected.add(new Tuple(1));
tuples_write.add(new Tuple(2));
tuples_expected.add(new Tuple(2));
tuples_write.add(new Tuple("3"));
tuples_write.add(new Tuple("4"));
tuples_write.add(new Tuple(5));
tuples_expected.add(new Tuple(5));
for (Tuple tuple : tuples_write) {
linda.write(tuple);
} }
tuple_template = new Tuple(Integer.class); @Test
tuples_read = linda.takeAll(tuple_template); void testEmptyRead() {
assertEquals(tuples_read, tuples_expected); Thread mainRunner = new Thread(() -> {
Tuple tuple_template;
tuple_template = new Tuple(Integer.class);
linda.read(tuple_template);
});
assertEquals(linda.tryTake(tuple_template), null); mainRunner.start();
assertNotEquals(linda.tryTake(new Tuple(String.class)), null);
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);
});
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
void testReadAll() {
Tuple tuple_template;
Collection<Tuple> tuples_write, tuples_read, tuples_expected;
tuples_write = new ArrayList<Tuple>();
tuples_expected = new ArrayList<Tuple>();
tuples_write.add(new Tuple(0));
tuples_expected.add(new Tuple(0));
tuples_write.add(new Tuple(1));
tuples_expected.add(new Tuple(1));
tuples_write.add(new Tuple(2));
tuples_expected.add(new Tuple(2));
tuples_write.add(new Tuple("3"));
tuples_write.add(new Tuple("4"));
tuples_write.add(new Tuple(5));
tuples_expected.add(new Tuple(5));
for (Tuple tuple : tuples_write) {
linda.write(tuple);
}
tuple_template = new Tuple(Integer.class);
tuples_read = linda.readAll(tuple_template);
assertEquals(tuples_read, tuples_expected);
assertNotEquals(linda.tryRead(tuple_template), 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
void testTakeAll() {
Tuple tuple_template;
Collection<Tuple> tuples_write, tuples_read, tuples_expected;
tuples_write = new ArrayList<Tuple>();
tuples_expected = new ArrayList<Tuple>();
tuples_write.add(new Tuple(0));
tuples_expected.add(new Tuple(0));
tuples_write.add(new Tuple(1));
tuples_expected.add(new Tuple(1));
tuples_write.add(new Tuple(2));
tuples_expected.add(new Tuple(2));
tuples_write.add(new Tuple("3"));
tuples_write.add(new Tuple("4"));
tuples_write.add(new Tuple(5));
tuples_expected.add(new Tuple(5));
for (Tuple tuple : tuples_write) {
linda.write(tuple);
}
tuple_template = new Tuple(Integer.class);
tuples_read = linda.takeAll(tuple_template);
assertEquals(tuples_read, tuples_expected);
assertEquals(linda.tryTake(tuple_template), 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);
}
}
} }