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,
"**/Thumbs.db": true,
"**/*.class": true
}
},
"java.configuration.updateBuildConfiguration": "automatic"
}

View file

@ -1,7 +1,6 @@
plugins {
id 'java'
id 'eclipse' // optional (to generate Eclipse project files)
id 'idea' // optional (to generate IntelliJ IDEA project files)
id 'jacoco'
}
repositories {
@ -15,4 +14,9 @@ dependencies {
test {
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.ReentrantLock;
class Reveil implements Callback {
class Reveil {
Lock lock = new ReentrantLock();
@ -26,10 +26,6 @@ class Reveil implements Callback {
this.condition = lock.newCondition();
}
public void call(Tuple t) {
return;
}
void sleep() {
try {
lock.lock();
@ -52,7 +48,7 @@ class Reveil implements Callback {
/** Shared memory implementation of Linda. */
public class CentralizedLinda implements Linda {
protected List<Tuple> tuples;
List<Tuple> tuples;
List<Reveil> reveils;
public CentralizedLinda() {
@ -116,14 +112,39 @@ public class CentralizedLinda implements Linda {
* @param template the Tuple template your looking for
*/
public Tuple tryTake(Tuple template) {
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
iterator.remove();
return next;
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
iterator.remove();
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;
@ -135,33 +156,59 @@ public class CentralizedLinda implements Linda {
* @param template the Tuple template your looking for
*/
public Tuple tryRead(Tuple template) {
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
synchronized (tuples) {
Tuple next = null;
Iterator<Tuple> iterator = tuples.iterator();
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
break;
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
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
*/
public Collection<Tuple> takeAll(Tuple template) {
List<Tuple> results = new ArrayList<Tuple>();
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
results.add(next);
iterator.remove();
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
results.add(next);
iterator.remove();
}
}
}
return results;
@ -173,14 +220,16 @@ public class CentralizedLinda implements Linda {
* @param template the Tuple template your looking for
*/
public Collection<Tuple> readAll(Tuple template) {
List<Tuple> results = new ArrayList<Tuple>();
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
Collection<Tuple> results = new ArrayList<Tuple>();
synchronized (tuples) {
Iterator<Tuple> iterator = tuples.iterator();
Tuple next = null;
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
results.add(next);
while (iterator.hasNext()) {
next = iterator.next();
if (next.matches(template)) {
results.add(next);
}
}
}
return results;
@ -189,40 +238,32 @@ public class CentralizedLinda implements Linda {
public void eventRegister(eventMode mode, eventTiming timing, Tuple template, Callback callback) {
new Thread() {
public void run() {
switch (timing) {
case IMMEDIATE:
callback.call(mode == eventMode.READ ? read(template) : take(template));
return;
case FUTURE:
List<Tuple> knownTuples = (List<Tuple>) readAll(template);
callback.call(tryRTknown(template, knownTuples, mode));
Collection<Tuple> knownTuples = new ArrayList<Tuple>();
for (Tuple t : tuples) {
knownTuples.add((Tuple) t.clone());
}
callback.call(future_search(template, knownTuples, mode));
return;
}
}
}.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);
reveils.add(reveil);
Tuple result = null;
for (int i = 0; i < tuples.size(); i++) {
result = mode == eventMode.READ ? tuples.get(i) : tuples.remove(i);
if (result.matches(template)) {
return result;
}
}
result = mode == eventMode.READ ? tryRead(template, knownTuples) : tryTake(template, knownTuples);
while (result == null) {
reveil.sleep();
for (int i = 0; i < tuples.size(); i++) {
result = mode == eventMode.READ ? tuples.get(i) : tuples.remove(i);
if (result.matches(template)) {
return result;
}
}
result = mode == eventMode.READ ? tryRead(template, knownTuples) : tryTake(template, knownTuples);
}
return result;
}

View file

@ -5,13 +5,17 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
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 linda.Callback;
import linda.Linda;
import linda.Tuple;
import linda.Linda.eventMode;
import linda.Linda.eventTiming;
import linda.shm.CentralizedLinda;
public class CentralizedLindaTests {
@ -23,159 +27,380 @@ public class CentralizedLindaTests {
linda = new CentralizedLinda();
}
@Test
void testTryRead() {
Tuple tuple_write, tuple_template, tuple_read;
@Nested
@DisplayName("read related tests")
class ReadTests {
tuple_template = new Tuple(0);
tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, null);
@Test
void testTryRead() {
Tuple tuple_write, tuple_template, tuple_read;
tuple_template = new Tuple(Integer.class);
tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, null);
tuple_template = new Tuple(0);
tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, null);
tuple_write = new Tuple(0);
linda.write(tuple_write);
linda.write(tuple_write);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, null);
tuple_template = new Tuple(0);
tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, tuple_write);
tuple_write = new Tuple(0);
linda.write(tuple_write);
linda.write(tuple_write);
tuple_template = new Tuple(Integer.class);
tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, tuple_write);
}
tuple_template = new Tuple(0);
tuple_read = linda.tryRead(tuple_template);
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
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);
tuple_read = linda.tryRead(tuple_template);
assertEquals(tuple_read, tuple_write);
}
tuple_template = new Tuple(Integer.class);
tuples_read = linda.readAll(tuple_template);
assertEquals(tuples_read, tuples_expected);
@Test
void testRead() {
Tuple tuple_write, tuple_template, tuple_read;
assertNotEquals(linda.tryRead(tuple_template), null);
assertNotEquals(linda.tryRead(new Tuple(String.class)), null);
}
tuple_write = new Tuple(0);
linda.write(tuple_write);
@Test
void testTakeAll() {
Tuple tuple_template;
Collection<Tuple> tuples_write, tuples_read, tuples_expected;
tuple_template = new Tuple(0);
tuple_read = linda.read(tuple_template);
assertEquals(tuple_read, tuple_write);
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);
tuple_read = linda.read(tuple_template);
assertEquals(tuple_read, tuple_write);
}
tuple_template = new Tuple(Integer.class);
tuples_read = linda.takeAll(tuple_template);
assertEquals(tuples_read, tuples_expected);
@Test
void testEmptyRead() {
Thread mainRunner = new Thread(() -> {
Tuple tuple_template;
tuple_template = new Tuple(Integer.class);
linda.read(tuple_template);
});
assertEquals(linda.tryTake(tuple_template), null);
assertNotEquals(linda.tryTake(new Tuple(String.class)), null);
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);
});
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);
}
}
}