diff options
author | eutarass | 2010-09-29 20:27:41 +0000 |
---|---|---|
committer | eutarass | 2010-09-29 20:27:41 +0000 |
commit | 0290356a43a87ba2501f35898279ce564930504c (patch) | |
tree | 512b8e29cd03456722a8407d9d7568303a015c9a | |
parent | 84606950a10da514015060198b4886276a8e1c17 (diff) | |
download | org.eclipse.tcf-0290356a43a87ba2501f35898279ce564930504c.tar.gz org.eclipse.tcf-0290356a43a87ba2501f35898279ce564930504c.tar.xz org.eclipse.tcf-0290356a43a87ba2501f35898279ce564930504c.zip |
1. Added terminal property: ProcessID - TCF process ID of the login process of the terminal.
2. Implemented diagnostic tests for Terminals service.
3. Fixed few bugs in Terminals service implementation that were found by the tests.
4 files changed, 211 insertions, 19 deletions
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/TerminalsProxy.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/TerminalsProxy.java index dcb15b4c6..fddbf0547 100644 --- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/TerminalsProxy.java +++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/internal/tcf/services/remote/TerminalsProxy.java @@ -40,6 +40,10 @@ public class TerminalsProxy implements ITerminals { return (String) props.get(PROP_ID); } + public String getProcessID() { + return (String) props.get(PROP_PROCESS_ID); + } + public String getPtyType() { return (String) props.get(PROP_PTY_TYPE); } diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ITerminals.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ITerminals.java index 5382e3266..0fcf12e6c 100644 --- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ITerminals.java +++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/ITerminals.java @@ -57,29 +57,32 @@ public interface ITerminals extends IService { * Context property names. */ static final String - /** The TCF context ID */ - PROP_ID = "ID", + /** The TCF context ID */ + PROP_ID = "ID", - /** The pty type */ - PROP_PTY_TYPE = "PtyType", + /** The process ID of the login process of the terminal */ + PROP_PROCESS_ID = "ProcessID", - /** terminal encoding */ - PROP_ENCODING = "Encoding", + /** The PTY type */ + PROP_PTY_TYPE = "PtyType", - /** window width size */ - PROP_WIDTH = "Width", + /** terminal encoding */ + PROP_ENCODING = "Encoding", - /** window height size */ - PROP_HEIGHT = "Height", + /** window width size */ + PROP_WIDTH = "Width", - /** Process standard input stream ID */ - PROP_STDIN_ID = "StdInID", + /** window height size */ + PROP_HEIGHT = "Height", - /** Process standard output stream ID */ - PROP_STDOUT_ID = "StdOutID", + /** Process standard input stream ID */ + PROP_STDIN_ID = "StdInID", - /** Process standard error stream ID */ - PROP_STDERR_ID = "StdErrID"; + /** Process standard output stream ID */ + PROP_STDOUT_ID = "StdOutID", + + /** Process standard error stream ID */ + PROP_STDERR_ID = "StdErrID"; interface TerminalContext { @@ -90,6 +93,12 @@ public interface ITerminals extends IService { String getID(); /** + * Get process ID of the login process of the terminal. + * Same as getProperties().get(“ProcessID”) + */ + String getProcessID(); + + /** * Get terminal type. * Same as getProperties().get(“PtyType”) */ @@ -132,7 +141,7 @@ public interface ITerminals extends IService { } /** - * Launch a new terminal toremote machine. + * Launch a new terminal to remote machine. * @param type - requested terminal type for the new terminal. * @param encoding - requested encoding for the new terminal. * @param environment - Array of environment variable strings. @@ -140,8 +149,7 @@ public interface ITerminals extends IService { * @param done - call back interface called when operation is completed. * @return pending command handle, can be used to cancel the command. */ - IToken launch(String type, String encoding, String[] environment, - DoneLaunch done); + IToken launch(String type, String encoding, String[] environment, DoneLaunch done); /** * Call-back interface to be called when "start" command is complete. diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TCFTestSuite.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TCFTestSuite.java index c1ff11189..af43e7419 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TCFTestSuite.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TCFTestSuite.java @@ -119,6 +119,14 @@ public class TCFTestSuite { }); pending_tests.add(new Runnable() { public void run() { + listener.progress("Running Terminals Test...", ++count_done, count_total); + for (IChannel channel : channels) { + active_tests.put(new TestTerminals(TCFTestSuite.this, channel), channel); + } + } + }); + pending_tests.add(new Runnable() { + public void run() { int i = 0; listener.progress("Running Run Control Test...", ++count_done, count_total); for (IChannel channel : channels) { 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 new file mode 100644 index 000000000..45e7cdb15 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/tests/TestTerminals.java @@ -0,0 +1,172 @@ +package org.eclipse.tm.internal.tcf.debug.tests; + +import java.util.Collection; +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.services.IProcesses; +import org.eclipse.tm.tcf.services.ITerminals; +import org.eclipse.tm.tcf.services.ITerminals.TerminalContext; + +class TestTerminals implements ITCFTest { + + private final TCFTestSuite test_suite; + private final ITerminals terminals; + private final IProcesses processes; + private final Random rnd = new Random(); + + private TerminalContext terminal; + private TerminalContext get_ctx; + private Map<String,String> environment; + private Collection<Map<String,Object>> signal_list; + private boolean signal_sent; + + 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)); + } + } + + public void winSizeChanged(String id, int w, int h) { + } + }; + + TestTerminals(TCFTestSuite test_suite, IChannel channel) { + this.test_suite = test_suite; + terminals = channel.getRemoteService(ITerminals.class); + processes = channel.getRemoteService(IProcesses.class); + } + + public void start() { + if (terminals == null) { + test_suite.done(this, null); + } + else { + terminals.addListener(listener); + run(); + } + } + + private void run() { + if (environment == null && processes != null) { + processes.getEnvironment(new IProcesses.DoneGetEnvironment() { + public void doneGetEnvironment(IToken token, Exception error, Map<String, String> environment) { + if (error != null) { + exit(error); + } + else if (environment == null) { + exit(new Exception("Default process environment must not be null")); + } + else { + TestTerminals.this.environment = environment; + run(); + } + } + }); + return; + } + if (terminal == null) { + String[] types = { "ansi", "vt100", null }; + String[] langs = { "en_US", "en_US.UTF-8", null }; + String[] env = null; + if (environment != null && rnd.nextBoolean()) { + int i = 0; + env = new String[environment.size() + 1]; + for (String s : environment.keySet()) { + env[i++] = s + "=" + environment.get(s); + } + 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) { + if (error != null) { + exit(error); + } + else if (terminal == null) { + exit(new Exception("Terminal context must not be null")); + } + else if (terminal.getID() == null) { + exit(new Exception("Terminal context ID must not be null")); + } + else { + TestTerminals.this.terminal = terminal; + run(); + } + } + }); + return; + } + if (get_ctx == null) { + terminals.getContext(terminal.getID(), new ITerminals.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, TerminalContext terminal) { + if (error != null) { + exit(error); + } + else if (terminal == null) { + exit(new Exception("Terminal context must not be null")); + } + else if (terminal.getID() == null) { + exit(new Exception("Terminal context ID must not be null")); + } + else if (!TestTerminals.this.terminal.getProperties().equals(terminal.getProperties())) { + exit(new Exception("Invalid result of Terminal.getContext")); + } + else { + TestTerminals.this.get_ctx = terminal; + run(); + } + } + }); + return; + } + if (signal_list == null && processes != null && terminal.getProcessID() != null) { + processes.getSignalList(terminal.getProcessID(), new IProcesses.DoneGetSignalList() { + public void doneGetSignalList(IToken token, Exception error, Collection<Map<String,Object>> list) { + if (error != null) { + exit(error); + } + else if (list == null) { + exit(new Exception("Signal list must not be null")); + } + else { + TestTerminals.this.signal_list = list; + run(); + } + } + }); + } + if (signal_list != null && !signal_sent) { + 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); + } + else { + signal_sent = true; + run(); + } + } + }); + return; + } + exit(null); + } + + private void exit(Throwable x) { + if (!test_suite.isActive(this)) return; + if (terminals != null) terminals.removeListener(listener); + test_suite.done(this, x); + } +} |