summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@nokia.com>2011-11-15 17:13:02 +0100
committerChristian Kandeler <christian.kandeler@nokia.com>2011-11-15 17:32:55 +0100
commit4c76e40617d22d3578bb95973b54b0e266591e7c (patch)
tree8b89776bde4cd291fd54db988ca5e79939ac191f
parentd9dde0d5e8eedde5b82c441700babc4f2a394ce4 (diff)
downloadqt-creator-4c76e40617d22d3578bb95973b54b0e266591e7c.tar.gz
SSH: Derive SshRemoteProcess from QIODevice.
Now it looks even more like QProcess. Things like process channels are still missing. Change-Id: I3f30cd00ed4a054d02e83add9a6f4162b48f8345 Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
-rw-r--r--src/libs/utils/ssh/sftpchannel.cpp4
-rw-r--r--src/libs/utils/ssh/sftpchannel_p.h2
-rw-r--r--src/libs/utils/ssh/sshchannel.cpp7
-rw-r--r--src/libs/utils/ssh/sshchannel_p.h6
-rw-r--r--src/libs/utils/ssh/sshremoteprocess.cpp103
-rw-r--r--src/libs/utils/ssh/sshremoteprocess.h20
-rw-r--r--src/libs/utils/ssh/sshremoteprocess_p.h7
-rw-r--r--src/plugins/debugger/gdb/remotegdbprocess.cpp2
-rw-r--r--src/plugins/debugger/lldb/lldbenginehost.cpp4
-rw-r--r--src/plugins/madde/maddedevicetester.cpp2
-rw-r--r--src/plugins/madde/maemopublisherfremantlefree.cpp6
-rw-r--r--src/plugins/madde/maemoremotemounter.cpp4
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.cpp2
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp2
-rw-r--r--tests/manual/ssh/remoteprocess/remoteprocesstest.cpp74
-rw-r--r--tests/manual/ssh/remoteprocess/remoteprocesstest.h15
-rw-r--r--tests/manual/ssh/shell/shell.cpp2
17 files changed, 171 insertions, 91 deletions
diff --git a/src/libs/utils/ssh/sftpchannel.cpp b/src/libs/utils/ssh/sftpchannel.cpp
index c17ce21d19..79e1f3f2ef 100644
--- a/src/libs/utils/ssh/sftpchannel.cpp
+++ b/src/libs/utils/ssh/sftpchannel.cpp
@@ -821,13 +821,13 @@ void SftpChannelPrivate::handleOpenSuccessInternal()
m_sftpState = SubsystemRequested;
}
-void SftpChannelPrivate::handleOpenFailureInternal()
+void SftpChannelPrivate::handleOpenFailureInternal(const QString &reason)
{
if (channelState() != SessionRequested) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
}
- emit initializationFailed(tr("Server could not start session."));
+ emit initializationFailed(tr("Server could not start session: %1").arg(reason));
}
void SftpChannelPrivate::sendReadRequest(const SftpDownload::Ptr &job,
diff --git a/src/libs/utils/ssh/sftpchannel_p.h b/src/libs/utils/ssh/sftpchannel_p.h
index 241cbb77a7..e2efd89afd 100644
--- a/src/libs/utils/ssh/sftpchannel_p.h
+++ b/src/libs/utils/ssh/sftpchannel_p.h
@@ -74,7 +74,7 @@ private:
SftpJobId createJob(const AbstractSftpOperation::Ptr &job);
virtual void handleOpenSuccessInternal();
- virtual void handleOpenFailureInternal();
+ virtual void handleOpenFailureInternal(const QString &reason);
virtual void handleChannelDataInternal(const QByteArray &data);
virtual void handleChannelExtendedDataInternal(quint32 type,
const QByteArray &data);
diff --git a/src/libs/utils/ssh/sshchannel.cpp b/src/libs/utils/ssh/sshchannel.cpp
index b6965da5b1..4fa68dc89e 100644
--- a/src/libs/utils/ssh/sshchannel.cpp
+++ b/src/libs/utils/ssh/sshchannel.cpp
@@ -84,7 +84,7 @@ void AbstractSshChannel::requestSessionStart()
setChannelState(SessionRequested);
m_timeoutTimer->start(ReplyTimeout);
} catch (Botan::Exception &e) {
- m_errorString = QString::fromAscii(e.what());
+ qDebug("Botan error: %s", e.what());
closeChannel();
}
}
@@ -95,7 +95,7 @@ void AbstractSshChannel::sendData(const QByteArray &data)
m_sendBuffer += data;
flushSendBuffer();
} catch (Botan::Exception &e) {
- m_errorString = QString::fromAscii(e.what());
+ qDebug("Botan error: %s", e.what());
closeChannel();
}
}
@@ -163,8 +163,7 @@ void AbstractSshChannel::handleOpenFailure(const QString &reason)
#ifdef CREATOR_SSH_DEBUG
qDebug("Channel open request failed for channel %u", m_localChannel);
#endif
- m_errorString = reason;
- handleOpenFailureInternal();
+ handleOpenFailureInternal(reason);
}
void AbstractSshChannel::handleChannelEof()
diff --git a/src/libs/utils/ssh/sshchannel_p.h b/src/libs/utils/ssh/sshchannel_p.h
index 201b77b970..c6c81f5abf 100644
--- a/src/libs/utils/ssh/sshchannel_p.h
+++ b/src/libs/utils/ssh/sshchannel_p.h
@@ -58,9 +58,6 @@ public:
ChannelState channelState() const { return m_state; }
void setChannelState(ChannelState state);
- void setError(const QString &error) { m_errorString = error; }
- QString errorString() const { return m_errorString; }
-
quint32 localChannelId() const { return m_localChannel; }
quint32 remoteChannel() const { return m_remoteChannel; }
@@ -101,7 +98,7 @@ protected:
private:
virtual void handleOpenSuccessInternal() = 0;
- virtual void handleOpenFailureInternal() = 0;
+ virtual void handleOpenFailureInternal(const QString &reason) = 0;
virtual void handleChannelDataInternal(const QByteArray &data) = 0;
virtual void handleChannelExtendedDataInternal(quint32 type,
const QByteArray &data) = 0;
@@ -119,7 +116,6 @@ private:
quint32 m_remoteMaxPacketSize;
ChannelState m_state;
QByteArray m_sendBuffer;
- QString m_errorString;
};
} // namespace Internal
diff --git a/src/libs/utils/ssh/sshremoteprocess.cpp b/src/libs/utils/ssh/sshremoteprocess.cpp
index 90ab74735f..52068ba869 100644
--- a/src/libs/utils/ssh/sshremoteprocess.cpp
+++ b/src/libs/utils/ssh/sshremoteprocess.cpp
@@ -42,6 +42,8 @@
#include <QtCore/QTimer>
+#include <cstring>
+
/*!
\class Utils::SshRemoteProcess
@@ -49,17 +51,10 @@
Objects are created via SshConnection::createRemoteProcess.
The process is started via the start() member function.
- A closeChannel() function is provided, but rarely useful, because
-
- \list
- \i a) when the process ends, the channel is closed automatically, and
- \i b) closing a channel will not necessarily kill the remote process.
- \endlist
-
- Therefore, the only sensible use case for calling closeChannel() is to
- get rid of an SshRemoteProces object before the process is actually started.
If the process needs a pseudo terminal, you can request one
via requestTerminal() before calling start().
+ Note that this class does not support QIODevice's waitFor*() functions, i.e. it has
+ no synchronous mode.
*/
namespace Utils {
@@ -99,12 +94,63 @@ SshRemoteProcess::~SshRemoteProcess()
delete d;
}
+bool SshRemoteProcess::atEnd() const
+{
+ return QIODevice::atEnd() && d->m_stdout.isEmpty();
+}
+
+qint64 SshRemoteProcess::bytesAvailable() const
+{
+ return QIODevice::bytesAvailable() + d->m_stdout.count();
+}
+
+bool SshRemoteProcess::canReadLine() const
+{
+ return QIODevice::canReadLine() || d->m_stdout.contains('\n'); // TODO: Not cross-platform?
+}
+
+QByteArray SshRemoteProcess::readAllStandardOutput()
+{
+ return readAll();
+}
+
+QByteArray SshRemoteProcess::readAllStandardError()
+{
+ const QByteArray data = d->m_stderr;
+ d->m_stderr.clear();
+ return data;
+}
+
+void SshRemoteProcess::close()
+{
+ d->closeChannel();
+ QIODevice::close();
+}
+
+qint64 SshRemoteProcess::readData(char *data, qint64 maxlen)
+{
+ const qint64 bytesRead = qMin(qint64(d->m_stdout.count()), maxlen);
+ memcpy(data, d->m_stdout.constData(), bytesRead);
+ d->m_stdout.remove(0, bytesRead);
+ return bytesRead;
+}
+
+qint64 SshRemoteProcess::writeData(const char *data, qint64 len)
+{
+ if (isRunning()) {
+ d->sendData(QByteArray(data, len));
+ return len;
+ }
+ return 0;
+}
+
void SshRemoteProcess::init()
{
connect(d, SIGNAL(started()), this, SIGNAL(started()),
Qt::QueuedConnection);
connect(d, SIGNAL(readyReadStandardOutput()), this, SIGNAL(readyReadStandardOutput()),
Qt::QueuedConnection);
+ connect(d, SIGNAL(readyReadStandardOutput()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
connect(d, SIGNAL(readyReadStandardError()), this,
SIGNAL(readyReadStandardError()), Qt::QueuedConnection);
connect(d, SIGNAL(closed(int)), this, SIGNAL(closed(int)), Qt::QueuedConnection);
@@ -129,6 +175,7 @@ void SshRemoteProcess::start()
#ifdef CREATOR_SSH_DEBUG
qDebug("process start requested, channel id = %u", d->localChannelId());
#endif
+ QIODevice::open(QIODevice::ReadWrite);
d->requestSessionStart();
}
}
@@ -140,36 +187,19 @@ void SshRemoteProcess::sendSignal(const QByteArray &signal)
d->m_sendFacility.sendChannelSignalPacket(d->remoteChannel(),
signal);
} catch (Botan::Exception &e) {
- d->setError(QString::fromAscii(e.what()));
+ setErrorString(QString::fromAscii(e.what()));
d->closeChannel();
}
}
-void SshRemoteProcess::closeChannel()
-{
- d->closeChannel();
-}
-
-void SshRemoteProcess::sendInput(const QByteArray &data)
-{
- if (isRunning())
- d->sendData(data);
-}
-
bool SshRemoteProcess::isRunning() const
{
return d->m_procState == Internal::SshRemoteProcessPrivate::Running;
}
-QString SshRemoteProcess::errorString() const { return d->errorString(); }
-
int SshRemoteProcess::exitCode() const { return d->m_exitCode; }
-
QByteArray SshRemoteProcess::exitSignal() const { return d->m_signal; }
-QByteArray SshRemoteProcess::readAllStandardOutput() { return d->readAllStandardOutput(); }
-QByteArray SshRemoteProcess::readAllStandardError() { return d->readAllStandardError(); }
-
namespace Internal {
SshRemoteProcessPrivate::SshRemoteProcessPrivate(const QByteArray &command,
@@ -214,20 +244,6 @@ void SshRemoteProcessPrivate::setProcState(ProcessState newState)
}
}
-QByteArray SshRemoteProcessPrivate::readAllStandardOutput()
-{
- const QByteArray data = m_stdout;
- m_stdout.clear();
- return data;
-}
-
-QByteArray SshRemoteProcessPrivate::readAllStandardError()
-{
- const QByteArray data = m_stderr;
- m_stderr.clear();
- return data;
-}
-
void SshRemoteProcessPrivate::closeHook()
{
if (m_wasRunning) {
@@ -256,9 +272,10 @@ void SshRemoteProcessPrivate::handleOpenSuccessInternal()
m_timeoutTimer->start(ReplyTimeout);
}
-void SshRemoteProcessPrivate::handleOpenFailureInternal()
+void SshRemoteProcessPrivate::handleOpenFailureInternal(const QString &reason)
{
setProcState(StartFailed);
+ m_proc->setErrorString(reason);
}
void SshRemoteProcessPrivate::handleChannelSuccess()
@@ -313,9 +330,9 @@ void SshRemoteProcessPrivate::handleExitSignal(const SshChannelExitSignal &signa
#ifdef CREATOR_SSH_DEBUG
qDebug("Exit due to signal %s", signal.signal.data());
#endif
- setError(signal.error);
m_signal = signal.signal;
m_procState = Exited;
+ m_proc->setErrorString(tr("Process killed by signal"));
}
} // namespace Internal
diff --git a/src/libs/utils/ssh/sshremoteprocess.h b/src/libs/utils/ssh/sshremoteprocess.h
index 59f61385c2..fcd3f0edd5 100644
--- a/src/libs/utils/ssh/sshremoteprocess.h
+++ b/src/libs/utils/ssh/sshremoteprocess.h
@@ -35,7 +35,7 @@
#include <utils/utils_global.h>
-#include <QtCore/QObject>
+#include <QtCore/QProcess>
#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -50,7 +50,8 @@ class SshRemoteProcessPrivate;
class SshSendFacility;
} // namespace Internal
-class QTCREATOR_UTILS_EXPORT SshRemoteProcess : public QObject
+// TODO: ProcessChannel
+class QTCREATOR_UTILS_EXPORT SshRemoteProcess : public QIODevice
{
Q_OBJECT
@@ -77,6 +78,13 @@ public:
~SshRemoteProcess();
+ // QIODevice stuff
+ bool atEnd() const;
+ qint64 bytesAvailable() const;
+ bool canReadLine() const;
+ void close();
+ bool isSequential() const { return true; }
+
/*
* Note that this is of limited value in practice, because servers are
* usually configured to ignore such requests for security reasons.
@@ -85,10 +93,8 @@ public:
void requestTerminal(const SshPseudoTerminal &terminal);
void start();
- void closeChannel();
bool isRunning() const;
- QString errorString() const;
int exitCode() const;
QByteArray exitSignal() const;
@@ -99,8 +105,6 @@ public:
void sendSignal(const QByteArray &signal);
void kill() { sendSignal(KillSignal); }
- void sendInput(const QByteArray &data); // Should usually have a trailing newline.
-
signals:
void started();
@@ -118,6 +122,10 @@ private:
Internal::SshSendFacility &sendFacility);
SshRemoteProcess(quint32 channelId, Internal::SshSendFacility &sendFacility);
+ // QIODevice stuff
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+
void init();
Internal::SshRemoteProcessPrivate *d;
diff --git a/src/libs/utils/ssh/sshremoteprocess_p.h b/src/libs/utils/ssh/sshremoteprocess_p.h
index da47927f3a..32564ef9cb 100644
--- a/src/libs/utils/ssh/sshremoteprocess_p.h
+++ b/src/libs/utils/ssh/sshremoteprocess_p.h
@@ -52,7 +52,7 @@ class SshRemoteProcessPrivate : public AbstractSshChannel
friend class Utils::SshRemoteProcess;
public:
enum ProcessState {
- NotYetStarted, ExecRequested, StartFailed,Running, Exited
+ NotYetStarted, ExecRequested, StartFailed, Running, Exited
};
virtual void handleChannelSuccess();
@@ -60,9 +60,6 @@ public:
virtual void closeHook();
- QByteArray readAllStandardOutput();
- QByteArray readAllStandardError();
-
signals:
void started();
void readyReadStandardOutput();
@@ -76,7 +73,7 @@ private:
SshRemoteProcess *proc);
virtual void handleOpenSuccessInternal();
- virtual void handleOpenFailureInternal();
+ virtual void handleOpenFailureInternal(const QString &reason);
virtual void handleChannelDataInternal(const QByteArray &data);
virtual void handleChannelExtendedDataInternal(quint32 type,
const QByteArray &data);
diff --git a/src/plugins/debugger/gdb/remotegdbprocess.cpp b/src/plugins/debugger/gdb/remotegdbprocess.cpp
index 80a1dd5837..e9bb37aefe 100644
--- a/src/plugins/debugger/gdb/remotegdbprocess.cpp
+++ b/src/plugins/debugger/gdb/remotegdbprocess.cpp
@@ -341,7 +341,7 @@ void RemoteGdbProcess::sendInput(const QByteArray &data)
if (!isdigit(data.at(pos)))
break;
m_lastSeqNr = data.left(pos);
- m_gdbProc->sendInput(data);
+ m_gdbProc->write(data);
}
void RemoteGdbProcess::handleAppOutput()
diff --git a/src/plugins/debugger/lldb/lldbenginehost.cpp b/src/plugins/debugger/lldb/lldbenginehost.cpp
index 70189a5139..d5115bbd6a 100644
--- a/src/plugins/debugger/lldb/lldbenginehost.cpp
+++ b/src/plugins/debugger/lldb/lldbenginehost.cpp
@@ -95,7 +95,7 @@ qint64 SshIODevice::writeData (const char * data, qint64 maxSize)
startupbuffer += QByteArray::fromRawData(data, maxSize);
return maxSize;
}
- proc->sendInput(QByteArray::fromRawData(data, maxSize));
+ proc->write(data, maxSize);
return maxSize;
}
qint64 SshIODevice::readData (char * data, qint64 maxSize)
@@ -128,7 +128,7 @@ qint64 SshIODevice::readData (char * data, qint64 maxSize)
void SshIODevice::processStarted()
{
proc = runner->process();
- proc->sendInput(startupbuffer);
+ proc->write(startupbuffer);
}
void SshIODevice::outputAvailable(const QByteArray &output)
diff --git a/src/plugins/madde/maddedevicetester.cpp b/src/plugins/madde/maddedevicetester.cpp
index a275971f4e..80090f07d6 100644
--- a/src/plugins/madde/maddedevicetester.cpp
+++ b/src/plugins/madde/maddedevicetester.cpp
@@ -89,7 +89,7 @@ void MaddeDeviceTester::stopTest()
case QtTest:
case MadDeveloperTest:
case QmlToolingTest:
- m_processRunner->process()->closeChannel();
+ m_processRunner->process()->close();
break;
}
diff --git a/src/plugins/madde/maemopublisherfremantlefree.cpp b/src/plugins/madde/maemopublisherfremantlefree.cpp
index aa85f8138b..e0cf2f7043 100644
--- a/src/plugins/madde/maemopublisherfremantlefree.cpp
+++ b/src/plugins/madde/maemopublisherfremantlefree.cpp
@@ -447,7 +447,7 @@ void MaemoPublisherFremantleFree::prepareToSendFile()
emit progressReport(tr("Uploading file %1 ...")
.arg(QDir::toNativeSeparators(nextFilePath)));
QFileInfo info(nextFilePath);
- m_uploader->process()->sendInput("C0644 " + QByteArray::number(info.size())
+ m_uploader->process()->write("C0644 " + QByteArray::number(info.size())
+ ' ' + info.fileName().toUtf8() + '\n');
}
@@ -473,13 +473,13 @@ void MaemoPublisherFremantleFree::sendFile()
tr("Upload failed."));
return;
}
- m_uploader->process()->sendInput(data);
+ m_uploader->process()->write(data);
bytesToSend -= data.size();
QCoreApplication::processEvents();
if (m_state == Inactive)
return;
}
- m_uploader->process()->sendInput(QByteArray(1, '\0'));
+ m_uploader->process()->write(QByteArray(1, '\0'));
}
void MaemoPublisherFremantleFree::handleScpStdOut(const QByteArray &output)
diff --git a/src/plugins/madde/maemoremotemounter.cpp b/src/plugins/madde/maemoremotemounter.cpp
index a151feaf3d..6144036243 100644
--- a/src/plugins/madde/maemoremotemounter.cpp
+++ b/src/plugins/madde/maemoremotemounter.cpp
@@ -380,11 +380,11 @@ void MaemoRemoteMounter::setState(State newState)
m_utfsServerTimer->stop();
if (m_mountProcess) {
disconnect(m_mountProcess.data(), 0, this, 0);
- m_mountProcess->closeChannel();
+ m_mountProcess->close();
}
if (m_unmountProcess) {
disconnect(m_unmountProcess.data(), 0, this, 0);
- m_unmountProcess->closeChannel();
+ m_unmountProcess->close();
}
}
m_state = newState;
diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp
index 8c9e1cd2b9..cd9c465174 100644
--- a/src/plugins/remotelinux/linuxdevicetester.cpp
+++ b/src/plugins/remotelinux/linuxdevicetester.cpp
@@ -106,7 +106,7 @@ void GenericLinuxDeviceTester::stopTest()
d->portsGatherer.stop();
break;
case RunningUname:
- d->process->closeChannel();
+ d->process->close();
break;
case Inactive:
break;
diff --git a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
index 9f393b8924..d489d55030 100644
--- a/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
+++ b/src/plugins/remotelinux/remotelinuxcustomcommanddeployservice.cpp
@@ -115,7 +115,7 @@ void RemoteLinuxCustomCommandDeployService::stopDeployment()
QTC_ASSERT(d->state == Running, return);
disconnect(d->runner, 0, this, 0);
- d->runner->process()->closeChannel();
+ d->runner->process()->close();
d->state = Inactive;
handleDeploymentDone();
}
diff --git a/tests/manual/ssh/remoteprocess/remoteprocesstest.cpp b/tests/manual/ssh/remoteprocess/remoteprocesstest.cpp
index d4a52340c7..dd8cfafdef 100644
--- a/tests/manual/ssh/remoteprocess/remoteprocesstest.cpp
+++ b/tests/manual/ssh/remoteprocess/remoteprocesstest.cpp
@@ -35,6 +35,7 @@
#include <utils/ssh/sshpseudoterminal.h>
#include <QtCore/QCoreApplication>
+#include <QtCore/QTextStream>
#include <QtCore/QTimer>
#include <iostream>
@@ -75,9 +76,10 @@ void RemoteProcessTest::run()
void RemoteProcessTest::handleConnectionError()
{
- std::cerr << "Error: Connection failure ("
- << qPrintable(m_remoteRunner->lastConnectionErrorString()) << ")."
- << std::endl;
+ const QString error = m_state == TestingIoDevice
+ ? m_sshConnection->errorString() : m_remoteRunner->lastConnectionErrorString();
+
+ std::cerr << "Error: Connection failure (" << qPrintable(error) << ")." << std::endl;
qApp->quit();
}
@@ -92,6 +94,11 @@ void RemoteProcessTest::handleProcessStarted()
Utils::SshRemoteProcessRunner * const killer
= new Utils::SshRemoteProcessRunner(this);
killer->run("pkill -9 sleep", m_sshParams);
+ } else if (m_state == TestingIoDevice) {
+ connect(m_catProcess.data(), SIGNAL(readyRead()), SLOT(handleReadyRead()));
+ m_textStream = new QTextStream(m_catProcess.data());
+ *m_textStream << testString();
+ m_textStream->flush();
}
}
}
@@ -198,10 +205,16 @@ void RemoteProcessTest::handleProcessClosed(int exitStatus)
qApp->quit();
return;
}
- std::cout << "Ok.\nAll tests succeeded." << std::endl;
- qApp->quit();
+ std::cout << "Ok.\nTesting I/O device functionality... " << std::flush;
+ m_state = TestingIoDevice;
+ m_sshConnection = Utils::SshConnection::create(m_sshParams);
+ connect(m_sshConnection.data(), SIGNAL(connected()), SLOT(handleConnected()));
+ connect(m_sshConnection.data(), SIGNAL(error(Utils::SshError)),
+ SLOT(handleConnectionError()));
+ m_sshConnection->connectToHost();
break;
}
+ case TestingIoDevice:
case Inactive:
Q_ASSERT(false);
}
@@ -216,16 +229,23 @@ void RemoteProcessTest::handleProcessClosed(int exitStatus)
qApp->quit();
break;
case SshRemoteProcess::KilledBySignal:
- if (m_state != TestingCrash) {
+ switch (m_state) {
+ case TestingCrash:
+ std::cout << "Ok.\nTesting remote process with terminal... " << std::flush;
+ m_state = TestingTerminal;
+ m_started = false;
+ m_timeoutTimer->start();
+ m_remoteRunner->runInTerminal("top -n 1", SshPseudoTerminal(), m_sshParams);
+ break;
+ case TestingIoDevice:
+ std::cout << "Ok.\nAll tests succeeded." << std::endl;
+ qApp->quit();
+ break;
+ default:
std::cerr << "Error: Unexpected crash." << std::endl;
qApp->quit();
return;
}
- std::cout << "Ok.\nTesting remote process with terminal... " << std::flush;
- m_state = TestingTerminal;
- m_started = false;
- m_timeoutTimer->start();
- m_remoteRunner->runInTerminal("top -n 1", SshPseudoTerminal(), m_sshParams);
}
}
@@ -234,3 +254,35 @@ void RemoteProcessTest::handleTimeout()
std::cerr << "Error: Timeout waiting for progress." << std::endl;
qApp->quit();
}
+
+void RemoteProcessTest::handleConnected()
+{
+ Q_ASSERT(m_state == TestingIoDevice);
+
+ m_catProcess = m_sshConnection->createRemoteProcess(QString::fromLocal8Bit("cat").toUtf8());
+ connect(m_catProcess.data(), SIGNAL(started()), SLOT(handleProcessStarted()));
+ connect(m_catProcess.data(), SIGNAL(closed(int)), SLOT(handleProcessClosed(int)));
+ m_started = false;
+ m_timeoutTimer->start();
+ m_catProcess->start();
+}
+
+QString RemoteProcessTest::testString() const
+{
+ return QLatin1String("x");
+}
+
+void RemoteProcessTest::handleReadyRead()
+{
+ Q_ASSERT(m_state == TestingIoDevice);
+
+ const QString &data = QString::fromUtf8(m_catProcess->readAll());
+ if (data != testString()) {
+ std::cerr << "Testing of QIODevice functionality failed: Expected '"
+ << qPrintable(testString()) << "', got '" << qPrintable(data) << "'." << std::endl;
+ qApp->exit(1);
+ }
+
+ Utils::SshRemoteProcessRunner * const killer = new Utils::SshRemoteProcessRunner(this);
+ killer->run("pkill -9 cat", m_sshParams);
+}
diff --git a/tests/manual/ssh/remoteprocess/remoteprocesstest.h b/tests/manual/ssh/remoteprocess/remoteprocesstest.h
index 46a20dd5b6..bc1a381999 100644
--- a/tests/manual/ssh/remoteprocess/remoteprocesstest.h
+++ b/tests/manual/ssh/remoteprocess/remoteprocesstest.h
@@ -35,9 +35,11 @@
#include <utils/ssh/sshremoteprocessrunner.h>
-QT_FORWARD_DECLARE_CLASS(QTimer);
#include <QtCore/QObject>
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+QT_FORWARD_DECLARE_CLASS(QTimer)
+
class RemoteProcessTest : public QObject
{
Q_OBJECT
@@ -53,13 +55,22 @@ private slots:
void handleProcessStderr(const QByteArray &output);
void handleProcessClosed(int exitStatus);
void handleTimeout();
+ void handleReadyRead();
+ void handleConnected();
private:
- enum State { Inactive, TestingSuccess, TestingFailure, TestingCrash, TestingTerminal };
+ enum State {
+ Inactive, TestingSuccess, TestingFailure, TestingCrash, TestingTerminal, TestingIoDevice
+ };
+
+ QString testString() const;
const Utils::SshConnectionParameters m_sshParams;
QTimer * const m_timeoutTimer;
+ QTextStream *m_textStream;
Utils::SshRemoteProcessRunner * const m_remoteRunner;
+ Utils::SshRemoteProcess::Ptr m_catProcess;
+ Utils::SshConnection::Ptr m_sshConnection;
QByteArray m_remoteStdout;
QByteArray m_remoteStderr;
State m_state;
diff --git a/tests/manual/ssh/shell/shell.cpp b/tests/manual/ssh/shell/shell.cpp
index 96b59c9620..e363f9c52a 100644
--- a/tests/manual/ssh/shell/shell.cpp
+++ b/tests/manual/ssh/shell/shell.cpp
@@ -115,5 +115,5 @@ void Shell::handleChannelClosed(int exitStatus)
void Shell::handleStdin()
{
- m_shell->sendInput(m_stdin->readLine());
+ m_shell->write(m_stdin->readLine());
}