Fixed console input
Signed-off-by: Emmanuel Bigeon <emmanuel@bigeon.fr>
This commit is contained in:
parent
ad79e3ccb6
commit
b24b72f3e2
@ -51,6 +51,12 @@
|
|||||||
<artifactId>gclc</artifactId>
|
<artifactId>gclc</artifactId>
|
||||||
<version>2.0.11</version>
|
<version>2.0.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.bigeon.test</groupId>
|
||||||
|
<artifactId>junitmt</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<reporting>
|
<reporting>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
@ -120,15 +120,18 @@ public final class ConnectingConsoleInput implements ConsoleInput {
|
|||||||
public void connect(final ConsoleInput input) {
|
public void connect(final ConsoleInput input) {
|
||||||
disconnect();
|
disconnect();
|
||||||
synchronized (promptLock) {
|
synchronized (promptLock) {
|
||||||
connected = input;
|
|
||||||
promptLock.notifyAll();
|
promptLock.notifyAll();
|
||||||
|
synchronized (connectionLock) {
|
||||||
|
connected = input;
|
||||||
|
connectionLock.notifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Disconnect the current input. */
|
/** Disconnect the current input. */
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
synchronized (promptLock) {
|
synchronized (connectionLock) {
|
||||||
synchronized (connectionLock) {
|
synchronized (promptLock) {
|
||||||
if (connected != null) {
|
if (connected != null) {
|
||||||
disconnection = true;
|
disconnection = true;
|
||||||
connected.interruptPrompt();
|
connected.interruptPrompt();
|
||||||
@ -149,12 +152,15 @@ public final class ConnectingConsoleInput implements ConsoleInput {
|
|||||||
* @see fr.bigeon.gclc.manager.ConsoleInput#interruptPrompt() */
|
* @see fr.bigeon.gclc.manager.ConsoleInput#interruptPrompt() */
|
||||||
@Override
|
@Override
|
||||||
public void interruptPrompt() {
|
public void interruptPrompt() {
|
||||||
synchronized (promptLock) {
|
synchronized (connectionLock) {
|
||||||
prompting = false;
|
synchronized (promptLock) {
|
||||||
if (connected != null) {
|
connectionLock.notifyAll();
|
||||||
connected.interruptPrompt();
|
if (connected != null) {
|
||||||
|
connected.interruptPrompt();
|
||||||
|
}
|
||||||
|
prompting = false;
|
||||||
|
promptLock.notifyAll();
|
||||||
}
|
}
|
||||||
promptLock.notifyAll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,27 +197,34 @@ public final class ConnectingConsoleInput implements ConsoleInput {
|
|||||||
if (!prompting) {
|
if (!prompting) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
boolean connect;
|
}
|
||||||
synchronized (connectionLock) {
|
boolean connect;
|
||||||
connect = connected != null;
|
synchronized (connectionLock) {
|
||||||
}
|
connect = connected != null;
|
||||||
if (!connect) {
|
if (!connect) {
|
||||||
try {
|
try {
|
||||||
promptLock.wait();
|
connectionLock.wait();
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
LOGGER.log(Level.WARNING, "Inerruption of console thread", e);
|
LOGGER.log(Level.WARNING, "Inerruption of console thread", e);
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
synchronized (connectionLock) {
|
}
|
||||||
final String res = connected.prompt(message);
|
|
||||||
if (disconnection) {
|
ConsoleInput actualConnected;
|
||||||
disconnection = false;
|
synchronized (connectionLock) {
|
||||||
} else if (prompting) {
|
connect = connected != null;
|
||||||
return res;
|
actualConnected = connected;
|
||||||
} else {
|
}
|
||||||
// prompt interrupted, lose the result.
|
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) {
|
if (!prompting) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
boolean connect;
|
}
|
||||||
synchronized (connectionLock) {
|
boolean connect;
|
||||||
connect = connected != null;
|
synchronized (connectionLock) {
|
||||||
}
|
connect = connected != null;
|
||||||
if (!connect) {
|
if (!connect) {
|
||||||
try {
|
try {
|
||||||
promptLock.wait(timeout);
|
connectionLock.wait(timeout);
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
LOGGER.log(Level.WARNING, "Inerruption of console thread", e);
|
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
synchronized (connectionLock) {
|
}
|
||||||
final String res = connected.prompt(message,
|
ConsoleInput actualConnected;
|
||||||
end - System.currentTimeMillis());
|
synchronized (connectionLock) {
|
||||||
if (disconnection) {
|
connect = connected != null;
|
||||||
disconnection = false;
|
actualConnected = connected;
|
||||||
} else if (prompting) {
|
}
|
||||||
return res;
|
if (connect) {
|
||||||
} else {
|
synchronized (promptLock) {
|
||||||
// prompt interrupted, lose the result.
|
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);
|
} while (System.currentTimeMillis() < end);
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -6,11 +6,20 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.IOException;
|
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 org.junit.Test;
|
||||||
|
|
||||||
import net.bigeon.gclc.tools.ConstantString;
|
import net.bigeon.gclc.tools.ConstantString;
|
||||||
import net.bigeon.gclc.utils.PipedConsoleInput;
|
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 {
|
public class ConnectingConsoleInputTest {
|
||||||
|
|
||||||
@ -62,4 +71,67 @@ public class ConnectingConsoleInputTest {
|
|||||||
in.setPrompt(prompt);
|
in.setPrompt(prompt);
|
||||||
assertEquals("Prompt should be set correctly", prompt, in.getPrompt());
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user