From 24810c2250b3565fc3ba84f576b738e549c6f120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laure=CE=B7t?= Date: Wed, 29 Dec 2021 15:51:53 +0100 Subject: [PATCH] feat: des beaux tests sur CentralizedLinda, avec un beau code coverage --- .vscode/settings.json | 3 +- build.gradle | 8 +- src/main/java/linda/shm/CentralizedLinda.java | 147 +++-- .../linda/test/CentralizedLindaTests.java | 505 +++++++++++++----- 4 files changed, 467 insertions(+), 196 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b1bba8a..54620aa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,6 @@ "**/.DS_Store": true, "**/Thumbs.db": true, "**/*.class": true - } + }, + "java.configuration.updateBuildConfiguration": "automatic" } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 6aa0d68..2dd4dd3 100644 --- a/build.gradle +++ b/build.gradle @@ -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 } \ No newline at end of file diff --git a/src/main/java/linda/shm/CentralizedLinda.java b/src/main/java/linda/shm/CentralizedLinda.java index 706a9c3..78eae3b 100644 --- a/src/main/java/linda/shm/CentralizedLinda.java +++ b/src/main/java/linda/shm/CentralizedLinda.java @@ -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 tuples; + List tuples; List 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 iterator = tuples.iterator(); - Tuple next = null; + synchronized (tuples) { + Iterator 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 excluded) { + synchronized (tuples) { + Iterator 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 iterator = tuples.iterator(); - Tuple next = null; + synchronized (tuples) { + Tuple next = null; + Iterator 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 excluded) { + synchronized (tuples) { + Iterator 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 takeAll(Tuple template) { List results = new ArrayList(); - Iterator iterator = tuples.iterator(); - Tuple next = null; + synchronized (tuples) { + Iterator 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 readAll(Tuple template) { - List results = new ArrayList(); - Iterator iterator = tuples.iterator(); - Tuple next = null; + Collection results = new ArrayList(); + synchronized (tuples) { + Iterator 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 knownTuples = (List) readAll(template); - callback.call(tryRTknown(template, knownTuples, mode)); + Collection knownTuples = new ArrayList(); + for (Tuple t : tuples) { + knownTuples.add((Tuple) t.clone()); + } + callback.call(future_search(template, knownTuples, mode)); return; } } }.start(); } - private Tuple tryRTknown(Tuple template, List knownTuples, eventMode mode) { + private Tuple future_search(Tuple template, Collection 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; } diff --git a/src/test/java/linda/test/CentralizedLindaTests.java b/src/test/java/linda/test/CentralizedLindaTests.java index 671f190..6741271 100644 --- a/src/test/java/linda/test/CentralizedLindaTests.java +++ b/src/test/java/linda/test/CentralizedLindaTests.java @@ -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 tuples_write, tuples_read, tuples_expected; - - tuples_write = new ArrayList(); - tuples_expected = new ArrayList(); - - 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 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(); - tuples_expected = new ArrayList(); - - 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 tuples_write, tuples_read, tuples_expected; + + tuples_write = new ArrayList(); + tuples_expected = new ArrayList(); + + 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 tuples_write, tuples_read, tuples_expected; + + tuples_write = new ArrayList(); + tuples_expected = new ArrayList(); + + 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); + } + } } \ No newline at end of file