Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2011-07-13 18:49:14 +0000
committereutarass2011-07-13 18:49:14 +0000
commit75d739ca91f387c7d9bbfc783621a46d26883199 (patch)
treedd1a0fb81c109e443777d73a1cad11e1cf876170 /plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm
parent1c52efa855d08c5084bc7e008a8e34c19efa2202 (diff)
downloadorg.eclipse.tcf-75d739ca91f387c7d9bbfc783621a46d26883199.tar.gz
org.eclipse.tcf-75d739ca91f387c7d9bbfc783621a46d26883199.tar.xz
org.eclipse.tcf-75d739ca91f387c7d9bbfc783621a46d26883199.zip
TCF Tests: better tests for Terminals service.
Diffstat (limited to 'plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm')
-rw-r--r--plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TestTerminals.java308
1 files changed, 273 insertions, 35 deletions
diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TestTerminals.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TestTerminals.java
index 055990468..9ce85e5ef 100644
--- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TestTerminals.java
+++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TestTerminals.java
@@ -1,13 +1,17 @@
package org.eclipse.tm.internal.tcf.debug.tests;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import org.eclipse.tm.tcf.protocol.IChannel;
import org.eclipse.tm.tcf.protocol.IToken;
+import org.eclipse.tm.tcf.protocol.Protocol;
import org.eclipse.tm.tcf.services.IProcesses;
import org.eclipse.tm.tcf.services.IRunControl;
+import org.eclipse.tm.tcf.services.IStreams;
import org.eclipse.tm.tcf.services.ITerminals;
import org.eclipse.tm.tcf.services.ITerminals.TerminalContext;
@@ -16,19 +20,41 @@ class TestTerminals implements ITCFTest {
private final TCFTestSuite test_suite;
private final ITerminals terminals;
private final IProcesses processes;
+ private final IStreams streams;
private final Random rnd = new Random();
+ private final HashSet<String> stream_ids = new HashSet<String>();
+ private final StringBuffer stdout_buf = new StringBuffer();
+ private final StringBuffer stderr_buf = new StringBuffer();
+ private final HashSet<IToken> disconnect_cmds = new HashSet<IToken>();
+ private IStreams.StreamsListener streams_listener;
+ private IStreams.DoneRead stdout_read;
+ private IStreams.DoneRead stderr_read;
+ private String encoding;
private TerminalContext terminal;
private TerminalContext get_ctx;
private Map<String,String> environment;
+ private boolean delay_done;
private Collection<Map<String,Object>> signal_list;
+ private IToken get_signals_cmd;
+ private IToken signal_cmd;
private boolean signal_sent;
+ private IToken unsubscribe_cmd;
+ private boolean unsubscribe_done;
+ private boolean exited;
+ private boolean stdout_eos;
private final ITerminals.TerminalsListener listener = new ITerminals.TerminalsListener() {
public void exited(String id, int exit_code) {
- if (terminal != null && id.equals(terminal.getID()) && !signal_sent) {
- exit(new Exception("Terminal exited with code " + exit_code));
+ if (terminal != null && id.equals(terminal.getID())) {
+ exited = true;
+ if (!signal_sent) {
+ exit(new Exception("Terminal exited with code " + exit_code));
+ }
+ else {
+ run();
+ }
}
}
@@ -36,14 +62,24 @@ class TestTerminals implements ITCFTest {
}
};
+ private final IStreams.DoneDisconnect disconnect_done = new IStreams.DoneDisconnect() {
+ public void doneDisconnect(IToken token, Exception error) {
+ assert disconnect_cmds.contains(token);
+ disconnect_cmds.remove(token);
+ if (error != null) exit(error);
+ if (disconnect_cmds.size() == 0 && unsubscribe_done) exit(null);
+ }
+ };
+
TestTerminals(TCFTestSuite test_suite, IChannel channel) {
this.test_suite = test_suite;
terminals = channel.getRemoteService(ITerminals.class);
processes = channel.getRemoteService(IProcesses.class);
+ streams = channel.getRemoteService(IStreams.class);
}
public void start() {
- if (terminals == null) {
+ if (terminals == null || streams == null) {
test_suite.done(this, null);
}
else {
@@ -70,6 +106,45 @@ class TestTerminals implements ITCFTest {
});
return;
}
+ if (streams_listener == null) {
+ final IStreams.StreamsListener l = new IStreams.StreamsListener() {
+ public void created(String stream_type, String stream_id, String context_id) {
+ if (!terminals.getName().equals(stream_type)) {
+ exit(new Exception("Invalid stream type in Streams.created event: " + stream_type));
+ }
+ else if (stream_id == null || stream_id.length() == 0 || stream_ids.contains(stream_id)) {
+ exit(new Exception("Invalid stream ID in Streams.created event: " + stream_id));
+ }
+ else if (terminal != null) {
+ if (stream_id.equals(terminal.getStdInID()) ||
+ stream_id.equals(terminal.getStdOutID()) ||
+ stream_id.equals(terminal.getStdErrID())) {
+ exit(new Exception("Invalid stream ID in Streams.created event: " + stream_id));
+ }
+ else {
+ disconnect_cmds.add(streams.disconnect(stream_id, disconnect_done));
+ }
+ }
+ else {
+ stream_ids.add(stream_id);
+ }
+ }
+ public void disposed(String stream_type, String stream_id) {
+ }
+ };
+ streams.subscribe(terminals.getName(), l, new IStreams.DoneSubscribe() {
+ public void doneSubscribe(IToken token, Exception error) {
+ if (error != null) {
+ exit(error);
+ }
+ else {
+ streams_listener = l;
+ run();
+ }
+ }
+ });
+ return;
+ }
if (terminal == null) {
String[] types = { "ansi", "vt100", null };
String[] langs = { "en_US", "en_US.UTF-8", null };
@@ -83,7 +158,7 @@ class TestTerminals implements ITCFTest {
env[i++] = "TCF_FOO=BAR";
}
terminals.launch(types[rnd.nextInt(types.length)], langs[rnd.nextInt(langs.length)], env, new ITerminals.DoneLaunch() {
- public void doneLaunch(IToken token, Exception error, TerminalContext terminal) {
+ public void doneLaunch(IToken token, Exception error, final TerminalContext terminal) {
if (error != null) {
exit(error);
}
@@ -95,6 +170,37 @@ class TestTerminals implements ITCFTest {
}
else {
TestTerminals.this.terminal = terminal;
+ for (Iterator<String> i = stream_ids.iterator(); i.hasNext();) {
+ String stream_id = i.next();
+ if (stream_id.equals(terminal.getStdInID()) ||
+ stream_id.equals(terminal.getStdOutID()) ||
+ stream_id.equals(terminal.getStdErrID())) {
+ // keep connected
+ }
+ else {
+ i.remove();
+ disconnect_cmds.add(streams.disconnect(stream_id, disconnect_done));
+ }
+ }
+ Protocol.invokeLater(100, new Runnable() {
+ int cnt = 0;
+ public void run() {
+ if (!test_suite.isActive(TestTerminals.this)) return;
+ cnt++;
+ if (test_suite.cancel) {
+ exit(null);
+ }
+ else if (cnt < 300) {
+ Protocol.invokeLater(100, this);
+ }
+ else if (!exited) {
+ exit(new Error("Timeout waiting for 'Terminals.exited' event. Context: " + terminal.getID()));
+ }
+ else {
+ exit(new Error("Timeout waiting for end-of-stream. Context: " + terminal.getID()));
+ }
+ }
+ });
run();
}
}
@@ -125,8 +231,11 @@ class TestTerminals implements ITCFTest {
return;
}
if (signal_list == null && processes != null && terminal.getProcessID() != null) {
- processes.getSignalList(terminal.getProcessID(), new IProcesses.DoneGetSignalList() {
+ assert get_signals_cmd == null;
+ get_signals_cmd = processes.getSignalList(terminal.getProcessID(), new IProcesses.DoneGetSignalList() {
public void doneGetSignalList(IToken token, Exception error, Collection<Map<String,Object>> list) {
+ assert get_signals_cmd == token;
+ get_signals_cmd = null;
if (error != null) {
exit(error);
}
@@ -134,50 +243,179 @@ class TestTerminals implements ITCFTest {
exit(new Exception("Signal list must not be null"));
}
else {
- TestTerminals.this.signal_list = list;
+ signal_list = list;
run();
}
}
});
+ return;
}
- if (!signal_sent) {
- if (signal_list != null && rnd.nextBoolean()) {
- int code = 15;
- for (Map<String,Object> m : signal_list) {
- String nm = (String)m.get(IProcesses.SIG_NAME);
- if (nm != null && nm.equals("SIGTERM")) {
- Number n = (Number)m.get(IProcesses.SIG_CODE);
- if (n != null) code = n.intValue();
- }
- }
- processes.signal(terminal.getProcessID(), code, new IProcesses.DoneCommand() {
- public void doneCommand(IToken token, Exception error) {
- if (error != null) {
- exit(error);
+ if (encoding == null) {
+ String lang = terminal.getEncoding();
+ if (lang == null && environment != null) lang = environment.get("LC_ALL");
+ if (lang == null && environment != null) lang = environment.get("LANG");
+ if (lang == null) lang = "en_US.UTF-8";
+ int i = lang.indexOf('.');
+ int j = lang.indexOf('@');
+ if (i < 0) {
+ encoding = "UTF-8";
+ }
+ else if (j < i) {
+ encoding = lang.substring(i + 1);
+ }
+ else {
+ encoding = lang.substring(i + 1, j);
+ }
+ }
+ if (stdout_read == null) {
+ final String id = terminal.getStdOutID();
+ if (id == null) {
+ exit(new Exception("stdout stream ID is null"));
+ return;
+ }
+ stdout_read = new IStreams.DoneRead() {
+ public void doneRead(IToken token, Exception error, int lost_size, byte[] data, boolean eos) {
+ if (error != null) {
+ exit(error);
+ }
+ else if (lost_size > 0) {
+ exit(new Exception("Lost bytes in terminal stream"));
+ }
+ else {
+ try {
+ if (data != null) stdout_buf.append(new String(data, encoding));
+ if (!eos) {
+ streams.read(id, 0x1000, this);
+ }
+ else {
+ stdout_eos = true;
+ run();
+ }
}
- else {
- signal_sent = true;
- run();
+ catch (Exception x) {
+ exit(x);
}
}
- });
- }
- else {
- terminals.exit(terminal.getID(), new ITerminals.DoneCommand() {
- public void doneCommand(IToken token, Exception error) {
- if (error != null) {
- exit(error);
+ }
+ };
+ streams.read(id, 0x1000, stdout_read);
+ }
+ if (stderr_read == null && terminal.getStdErrID() != null) {
+ final String id = terminal.getStdErrID();
+ stderr_read = new IStreams.DoneRead() {
+ public void doneRead(IToken token, Exception error, int lost_size, byte[] data, boolean eos) {
+ if (error != null) {
+ exit(error);
+ }
+ else if (lost_size > 0) {
+ exit(new Exception("Lost bytes in terminal stream"));
+ }
+ else {
+ try {
+ if (data != null) stderr_buf.append(new String(data, encoding));
+ if (!eos) streams.read(id, 0x1000, this);
}
- else {
- signal_sent = true;
- run();
+ catch (Exception x) {
+ exit(x);
+ }
+ }
+ }
+ };
+ streams.read(id, 0x1000, stderr_read);
+ }
+ if (!delay_done) {
+ Protocol.invokeLater(rnd.nextInt(500), new Runnable() {
+ public void run() {
+ delay_done = true;
+ TestTerminals.this.run();
+ }
+ });
+ return;
+ }
+ if (!signal_sent) {
+ assert !exited;
+ if (signal_cmd == null) {
+ int code = 0;
+ if (signal_list != null && rnd.nextBoolean()) {
+ for (Map<String,Object> m : signal_list) {
+ String nm = (String)m.get(IProcesses.SIG_NAME);
+ if (nm != null && nm.equals("SIGKILL")) {
+ Number n = (Number)m.get(IProcesses.SIG_CODE);
+ if (n != null) code = n.intValue();
}
}
- });
+ if (code == 0) {
+ for (Map<String,Object> m : signal_list) {
+ String nm = (String)m.get(IProcesses.SIG_NAME);
+ if (nm != null && nm.equals("SIGTERM")) {
+ Number n = (Number)m.get(IProcesses.SIG_CODE);
+ if (n != null) code = n.intValue();
+ }
+ }
+ }
+ }
+ if (code > 0) {
+ signal_cmd = processes.signal(terminal.getProcessID(), code, new IProcesses.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ assert signal_cmd == token;
+ signal_cmd = null;
+ if (error != null) {
+ exit(error);
+ }
+ else {
+ signal_sent = true;
+ run();
+ }
+ }
+ });
+ }
+ else {
+ signal_cmd = terminals.exit(terminal.getID(), new ITerminals.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ assert signal_cmd == token;
+ signal_cmd = null;
+ if (error != null) {
+ exit(error);
+ }
+ else {
+ signal_sent = true;
+ run();
+ }
+ }
+ });
+ }
}
return;
}
- exit(null);
+ if (exited && stdout_eos) {
+ if (!unsubscribe_done) {
+ if (unsubscribe_cmd == null) {
+ unsubscribe_cmd = streams.unsubscribe(terminals.getName(), streams_listener, new IStreams.DoneUnsubscribe() {
+ public void doneUnsubscribe(IToken token, Exception error) {
+ unsubscribe_done = true;
+ if (error != null) exit(error);
+ else run();
+ }
+ });
+ }
+ return;
+ }
+ else {
+ for (String stream_id : stream_ids) {
+ disconnect_cmds.add(streams.disconnect(stream_id, disconnect_done));
+ }
+ stream_ids.clear();
+ checkTerminalOutput(stdout_buf);
+ checkTerminalOutput(stderr_buf);
+ }
+ }
+ }
+
+ private void checkTerminalOutput(StringBuffer bf) {
+ String s = bf.toString();
+ if (s.indexOf("Cannot start") >= 0) {
+ exit(new Exception("Unexpected terminal output:\n" + s));
+ }
}
private void exit(Throwable x) {

Back to the top