diff --git a/gclc-process/pom.xml b/gclc-process/pom.xml
index feeab46..d192386 100644
--- a/gclc-process/pom.xml
+++ b/gclc-process/pom.xml
@@ -51,6 +51,12 @@
gclc
2.0.11
+
+ net.bigeon.test
+ junitmt
+ 1.0.2
+ test
+
diff --git a/gclc-process/src/main/java/net/bigeon/gclc/process/io/ConnectingConsoleInput.java b/gclc-process/src/main/java/net/bigeon/gclc/process/io/ConnectingConsoleInput.java
index cf83ab3..04a5e97 100644
--- a/gclc-process/src/main/java/net/bigeon/gclc/process/io/ConnectingConsoleInput.java
+++ b/gclc-process/src/main/java/net/bigeon/gclc/process/io/ConnectingConsoleInput.java
@@ -120,15 +120,18 @@ public final class ConnectingConsoleInput implements ConsoleInput {
public void connect(final ConsoleInput input) {
disconnect();
synchronized (promptLock) {
- connected = input;
promptLock.notifyAll();
+ synchronized (connectionLock) {
+ connected = input;
+ connectionLock.notifyAll();
+ }
}
}
/** Disconnect the current input. */
public void disconnect() {
- synchronized (promptLock) {
- synchronized (connectionLock) {
+ synchronized (connectionLock) {
+ synchronized (promptLock) {
if (connected != null) {
disconnection = true;
connected.interruptPrompt();
@@ -149,12 +152,15 @@ public final class ConnectingConsoleInput implements ConsoleInput {
* @see fr.bigeon.gclc.manager.ConsoleInput#interruptPrompt() */
@Override
public void interruptPrompt() {
- synchronized (promptLock) {
- prompting = false;
- if (connected != null) {
- connected.interruptPrompt();
+ synchronized (connectionLock) {
+ synchronized (promptLock) {
+ connectionLock.notifyAll();
+ if (connected != null) {
+ connected.interruptPrompt();
+ }
+ prompting = false;
+ promptLock.notifyAll();
}
- promptLock.notifyAll();
}
}
@@ -191,27 +197,34 @@ public final class ConnectingConsoleInput implements ConsoleInput {
if (!prompting) {
return null;
}
- boolean connect;
- synchronized (connectionLock) {
- connect = connected != null;
- }
+ }
+ boolean connect;
+ synchronized (connectionLock) {
+ connect = connected != null;
if (!connect) {
try {
- promptLock.wait();
+ connectionLock.wait();
} catch (final InterruptedException e) {
LOGGER.log(Level.WARNING, "Inerruption of console thread", e);
Thread.currentThread().interrupt();
}
- } else {
- synchronized (connectionLock) {
- final String res = connected.prompt(message);
- if (disconnection) {
- disconnection = false;
- } else if (prompting) {
- return res;
- } else {
- // prompt interrupted, lose the result.
- }
+ }
+ }
+
+ ConsoleInput actualConnected;
+ synchronized (connectionLock) {
+ connect = connected != null;
+ actualConnected = connected;
+ }
+ if (connect) {
+ final String res = actualConnected.prompt(message);
+ synchronized (promptLock) {
+ if (disconnection) {
+ disconnection = false;
+ } else if (prompting) {
+ return res;
+ } else {
+ // prompt interrupted, lose the result.
}
}
}
@@ -234,33 +247,39 @@ public final class ConnectingConsoleInput implements ConsoleInput {
if (!prompting) {
return null;
}
- boolean connect;
- synchronized (connectionLock) {
- connect = connected != null;
- }
+ }
+ boolean connect;
+ synchronized (connectionLock) {
+ connect = connected != null;
if (!connect) {
try {
- promptLock.wait(timeout);
+ connectionLock.wait(timeout);
} catch (final InterruptedException e) {
- LOGGER.log(Level.WARNING, "Inerruption of console thread", e);
Thread.currentThread().interrupt();
}
- } else {
- synchronized (connectionLock) {
- final String res = connected.prompt(message,
- end - System.currentTimeMillis());
- if (disconnection) {
- disconnection = false;
- } else if (prompting) {
- return res;
- } else {
- // prompt interrupted, lose the result.
- }
+ }
+ }
+ ConsoleInput actualConnected;
+ synchronized (connectionLock) {
+ connect = connected != null;
+ actualConnected = connected;
+ }
+ if (connect) {
+ synchronized (promptLock) {
+ final String res = actualConnected.prompt(message,
+ end - System.currentTimeMillis());
+ if (disconnection) {
+ disconnection = false;
+ } else if (prompting) {
+ return res;
+ } else {
+ // prompt interrupted, lose the result.
}
}
}
} while (System.currentTimeMillis() < end);
return null;
+
}
/* (non-Javadoc)
diff --git a/gclc-process/src/test/java/net/bigeon/gclc/process/io/ConnectingConsoleInputTest.java b/gclc-process/src/test/java/net/bigeon/gclc/process/io/ConnectingConsoleInputTest.java
index 548a89d..632db2f 100644
--- a/gclc-process/src/test/java/net/bigeon/gclc/process/io/ConnectingConsoleInputTest.java
+++ b/gclc-process/src/test/java/net/bigeon/gclc/process/io/ConnectingConsoleInputTest.java
@@ -6,11 +6,20 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import net.bigeon.gclc.tools.ConstantString;
import net.bigeon.gclc.utils.PipedConsoleInput;
+import net.bigeon.gclc.utils.StreamConsoleInput;
+import net.bigeon.test.junitmt.ATestRunnable;
+import net.bigeon.test.junitmt.FunctionalTestRunnable;
+import net.bigeon.test.junitmt.TestFunction;
+import net.bigeon.test.junitmt.ThreadTest;
public class ConnectingConsoleInputTest {
@@ -62,4 +71,67 @@ public class ConnectingConsoleInputTest {
in.setPrompt(prompt);
assertEquals("Prompt should be set correctly", prompt, in.getPrompt());
}
+
+ @Test
+ public void testPromptSequence() throws IOException, InterruptedException {
+ final ConnectingConsoleInput in = new ConnectingConsoleInput();
+ // Unconnected
+ final AtomicBoolean ended = new AtomicBoolean(false);
+ final TestFunction one = new TestFunction() {
+
+ @Override
+ public void apply() throws Exception {
+ assertNull(in.prompt("m1", -1));
+ assertNull(in.prompt("m2", 5000));
+ ended.set(true);
+ assertNull(in.prompt("m3", 200));
+ }
+ };
+ final ATestRunnable runnable = new FunctionalTestRunnable(one);
+ final Thread th = new Thread(runnable);
+ final Thread inter = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ while (!ended.get()) {
+ try {
+ th.join(500);
+ } catch (final InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ in.interruptPrompt();
+ }
+ }
+ });
+ th.start();
+ inter.start();
+ ThreadTest.assertRuns(th, runnable);
+ inter.join();
+ ended.set(false);
+
+ final PipedOutputStream os = new PipedOutputStream();
+ final PipedInputStream pis = new PipedInputStream(os);
+ in.connect(new StreamConsoleInput(System.out, pis, StandardCharsets.UTF_8));
+ final ATestRunnable runnable2 = new FunctionalTestRunnable(one);
+ final Thread th2 = new Thread(runnable2);
+ final Thread inter2 = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ while (!ended.get()) {
+ try {
+ th2.join(500);
+ } catch (final InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ in.interruptPrompt();
+ }
+ }
+ });
+ th2.start();
+ inter2.start();
+ ThreadTest.assertRuns(th2, runnable2);
+ }
}