diff --git a/tests/manual/ssh/errorhandling/errorhandling.pro b/tests/manual/ssh/errorhandling/errorhandling.pro
new file mode 100644
index 0000000000000000000000000000000000000000..1161d4642da1b1d6e460403f9818986b1a4ee7b5
--- /dev/null
+++ b/tests/manual/ssh/errorhandling/errorhandling.pro
@@ -0,0 +1,4 @@
+include(../ssh.pri)
+
+TARGET=errorhandling
+SOURCES=main.cpp
diff --git a/tests/manual/ssh/errorhandling/main.cpp b/tests/manual/ssh/errorhandling/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..46dbac8c8567736546b96ee3883c1b2683426fa3
--- /dev/null
+++ b/tests/manual/ssh/errorhandling/main.cpp
@@ -0,0 +1,177 @@
+#include <coreplugin/ssh/sftpchannel.h>
+#include <coreplugin/ssh/sshconnection.h>
+#include <coreplugin/ssh/sshremoteprocess.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+#include <QtCore/QTimer>
+
+using namespace Core;
+
+class Test : public QObject {
+    Q_OBJECT
+public:
+    Test()
+    {
+        m_timeoutTimer.setSingleShot(true);
+        m_connection = SshConnection::create();
+        if (m_connection->state() != SshConnection::Unconnected) {
+            qDebug("Error: Newly created SSH connection has state %d.",
+                m_connection->state());
+        }
+
+        if (m_connection->createRemoteProcess(""))
+            qDebug("Error: Unconnected SSH connection creates remote process.");
+        if (m_connection->createSftpChannel())
+            qDebug("Error: Unconnected SSH connection creates SFTP channel.");
+
+        SshConnectionParameters noHost(SshConnectionParameters::DefaultProxy);
+        noHost.host = QLatin1String("hgdfxgfhgxfhxgfchxgcf");
+        noHost.port = 12345;
+        noHost.timeout = 10;
+
+        SshConnectionParameters noUser(SshConnectionParameters::DefaultProxy);;
+        noUser.host = QLatin1String("localhost");
+        noUser.port = 22;
+        noUser.timeout = 30;
+        noUser.authType = SshConnectionParameters::AuthByPwd;
+        noUser.uname = QLatin1String("dumdidumpuffpuff");
+        noUser.uname = QLatin1String("whatever");
+
+        SshConnectionParameters wrongPwd(SshConnectionParameters::DefaultProxy);;
+        wrongPwd.host = QLatin1String("localhost");
+        wrongPwd.port = 22;
+        wrongPwd.timeout = 30;
+        wrongPwd.authType = SshConnectionParameters::AuthByPwd;
+        wrongPwd.uname = QLatin1String("root");
+        noUser.uname = QLatin1String("thiscantpossiblybeapasswordcanit");
+
+        SshConnectionParameters invalidKeyFile(SshConnectionParameters::DefaultProxy);;
+        invalidKeyFile.host = QLatin1String("localhost");
+        invalidKeyFile.port = 22;
+        invalidKeyFile.timeout = 30;
+        invalidKeyFile.authType = SshConnectionParameters::AuthByKey;
+        invalidKeyFile.uname = QLatin1String("root");
+        invalidKeyFile.privateKeyFile
+            = QLatin1String("somefilenamethatwedontexpecttocontainavalidkey");
+
+        // TODO: Create a valid key file and check for authentication error.
+
+        m_testSet << TestItem("Behavior with non-existing host",
+            noHost, ErrorList() << SshSocketError);
+        m_testSet << TestItem("Behavior with non-existing user", noUser,
+            ErrorList() << SshSocketError << SshTimeoutError
+                << SshAuthenticationError);
+        m_testSet << TestItem("Behavior with wrong password", wrongPwd,
+            ErrorList() << SshSocketError << SshTimeoutError
+                << SshAuthenticationError);
+        m_testSet << TestItem("Behavior with invalid key file", invalidKeyFile,
+            ErrorList() << SshSocketError << SshTimeoutError
+                << SshKeyFileError);
+
+        runNextTest();
+    }
+
+    ~Test();
+
+private slots:
+    void handleConnected()
+    {
+        qDebug("Error: Received unexpected connected() signal.");
+        qApp->quit();
+    }
+
+    void handleDisconnected()
+    {
+        qDebug("Error: Received unexpected disconnected() signal.");
+        qApp->quit();
+    }
+
+    void handleDataAvailable(const QString &msg)
+    {
+        qDebug("Error: Received unexpected dataAvailable() signal. "
+            "Message was: '%s'.", qPrintable(msg));
+        qApp->quit();
+    }
+
+    void handleError(SshError error)
+    {
+        if (m_testSet.isEmpty()) {
+            qDebug("Error: Received error %d, but no test was running.", error);
+            qApp->quit();
+        }
+
+        const TestItem testItem = m_testSet.takeFirst();
+        if (testItem.allowedErrors.contains(error)) {
+            qDebug("Received error %d, as expected.", error);
+            if (m_testSet.isEmpty()) {
+                qDebug("All tests finished successfully.");
+                qApp->quit();
+            } else {
+                runNextTest();
+            }
+        } else {
+            qDebug("Received unexpected error %d.", error);
+            qApp->quit();
+        }
+    }
+
+    void handleTimeout()
+    {
+        if (m_testSet.isEmpty()) {
+            qDebug("Error: timeout, but no test was running.");
+            qApp->quit();
+        }
+        const TestItem testItem = m_testSet.takeFirst();
+        qDebug("Error: The following test timed out: %s", testItem.description);
+    }
+
+private:
+    void runNextTest()
+    {
+        if (m_connection)
+            disconnect(m_connection.data(), 0, this, 0);
+        m_connection = SshConnection::create();
+        connect(m_connection.data(), SIGNAL(connected()), this,
+            SLOT(handleConnected()));
+        connect(m_connection.data(), SIGNAL(disconnected()), this,
+            SLOT(handleDisconnected()));
+        connect(m_connection.data(), SIGNAL(dataAvailable(QString)), this,
+            SLOT(handleDataAvailable(QString)));
+        connect(m_connection.data(), SIGNAL(error(SshError)), this,
+            SLOT(handleError(SshError)));
+        const TestItem &nextItem = m_testSet.first();
+        m_timeoutTimer.stop();
+        m_timeoutTimer.setInterval(qMax(10000, nextItem.params.timeout * 1000));
+        qDebug("Testing: %s", nextItem.description);
+        m_connection->connectToHost(m_testSet.first().params);
+    }
+
+    SshConnection::Ptr m_connection;
+    typedef QList<SshError> ErrorList;
+    struct TestItem {
+        TestItem(const char *d, const SshConnectionParameters &p,
+            const ErrorList &e) : description(d), params(p), allowedErrors(e) {}
+
+        const char *description;
+        SshConnectionParameters params;
+        ErrorList allowedErrors;
+    };
+    QList<TestItem> m_testSet;
+    QTimer m_timeoutTimer;
+};
+
+Test::~Test() {}
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication a(argc, argv);
+    Test t;
+
+    return a.exec();
+}
+
+
+#include "main.moc"
diff --git a/tests/manual/ssh/sftp/argumentscollector.cpp b/tests/manual/ssh/sftp/argumentscollector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4ed54ef320a13c8392ebb5630a469920514c2294
--- /dev/null
+++ b/tests/manual/ssh/sftp/argumentscollector.cpp
@@ -0,0 +1,138 @@
+#include "argumentscollector.h"
+
+#include <iostream>
+
+using namespace std;
+using namespace Core;
+
+ArgumentsCollector::ArgumentsCollector(const QStringList &args)
+    : m_arguments(args)
+{
+}
+
+Parameters ArgumentsCollector::collect(bool &success) const
+{
+    Parameters parameters;
+    try {
+        bool authTypeGiven = false;
+        bool portGiven = false;
+        bool timeoutGiven = false;
+        bool smallFileCountGiven = false;
+        bool bigFileSizeGiven = false;
+        bool proxySettingGiven = false;
+        int pos;
+        int port;
+        for (pos = 1; pos < m_arguments.count() - 1; ++pos) {
+            if (checkAndSetStringArg(pos, parameters.sshParams.host, "-h")
+                || checkAndSetStringArg(pos, parameters.sshParams.uname, "-u"))
+                continue;
+            if (checkAndSetIntArg(pos, port, portGiven, "-p")
+                || checkAndSetIntArg(pos, parameters.sshParams.timeout, timeoutGiven, "-t")
+                || checkAndSetIntArg(pos, parameters.smallFileCount, smallFileCountGiven, "-c")
+                || checkAndSetIntArg(pos, parameters.bigFileSize, bigFileSizeGiven, "-s"))
+                continue;
+            if (checkAndSetStringArg(pos, parameters.sshParams.pwd, "-pwd")) {
+                if (!parameters.sshParams.privateKeyFile.isEmpty())
+                    throw ArgumentErrorException(QLatin1String("-pwd and -k are mutually exclusive."));
+                parameters.sshParams.authType
+                    = SshConnectionParameters::AuthByPwd;
+                authTypeGiven = true;
+                continue;
+            }
+            if (checkAndSetStringArg(pos, parameters.sshParams.privateKeyFile, "-k")) {
+                if (!parameters.sshParams.pwd.isEmpty())
+                    throw ArgumentErrorException(QLatin1String("-pwd and -k are mutually exclusive."));
+                parameters.sshParams.authType
+                    = SshConnectionParameters::AuthByKey;
+                authTypeGiven = true;
+                continue;
+            }
+            if (!checkForNoProxy(pos, parameters.sshParams.proxyType, proxySettingGiven))
+                throw ArgumentErrorException(QLatin1String("unknown option ") + m_arguments.at(pos));
+        }
+
+        Q_ASSERT(pos <= m_arguments.count());
+        if (pos == m_arguments.count() - 1) {
+            if (!checkForNoProxy(pos, parameters.sshParams.proxyType, proxySettingGiven))
+                throw ArgumentErrorException(QLatin1String("unknown option ") + m_arguments.at(pos));
+        }
+
+        if (!authTypeGiven)
+            throw ArgumentErrorException(QLatin1String("No authentication argument given."));
+        if (parameters.sshParams.host.isEmpty())
+            throw ArgumentErrorException(QLatin1String("No host given."));
+        if (parameters.sshParams.uname.isEmpty())
+            throw ArgumentErrorException(QLatin1String("No user name given."));
+
+        parameters.sshParams.port = portGiven ? port : 22;
+        if (!timeoutGiven)
+            parameters.sshParams.timeout = 30;
+        if (!smallFileCountGiven)
+            parameters.smallFileCount = 1000;
+        if (!bigFileSizeGiven)
+            parameters.bigFileSize = 1024;
+        success = true;
+    } catch (ArgumentErrorException &ex) {
+        cerr << "Error: " << qPrintable(ex.error) << endl;
+        printUsage();
+        success = false;
+    }
+    return parameters;
+}
+
+void ArgumentsCollector::printUsage() const
+{
+    cerr << "Usage: " << qPrintable(m_arguments.first())
+        << " -h <host> -u <user> "
+        << "-pwd <password> | -k <private key file> [ -p <port> ] "
+        << "[ -t <timeout> ] [ -c <small file count> ] "
+        << "[ -s <big file size in MB> ] [ -no-proxy ]" << endl;
+}
+
+bool ArgumentsCollector::checkAndSetStringArg(int &pos, QString &arg, const char *opt) const
+{
+    if (m_arguments.at(pos) == QLatin1String(opt)) {
+        if (!arg.isEmpty()) {
+            throw ArgumentErrorException(QLatin1String("option ") + opt
+                + QLatin1String(" was given twice."));
+        }
+        arg = m_arguments.at(++pos);
+        if (arg.isEmpty() && QLatin1String(opt) != QLatin1String("-pwd"))
+            throw ArgumentErrorException(QLatin1String("empty argument not allowed here."));
+        return true;
+    }
+    return false;
+}
+
+bool ArgumentsCollector::checkAndSetIntArg(int &pos, int &val,
+    bool &alreadyGiven, const char *opt) const
+{
+    if (m_arguments.at(pos) == QLatin1String(opt)) {
+        if (alreadyGiven) {
+            throw ArgumentErrorException(QLatin1String("option ") + opt
+                + QLatin1String(" was given twice."));
+        }
+        bool isNumber;
+        val = m_arguments.at(++pos).toInt(&isNumber);
+        if (!isNumber) {
+            throw ArgumentErrorException(QLatin1String("option ") + opt
+                 + QLatin1String(" needs integer argument"));
+        }
+        alreadyGiven = true;
+        return true;
+    }
+    return false;
+}
+
+bool ArgumentsCollector::checkForNoProxy(int &pos,
+    SshConnectionParameters::ProxyType &type, bool &alreadyGiven) const
+{
+    if (m_arguments.at(pos) == QLatin1String("-no-proxy")) {
+        if (alreadyGiven)
+            throw ArgumentErrorException(QLatin1String("proxy setting given twice."));
+        type = SshConnectionParameters::NoProxy;
+        alreadyGiven = true;
+        return true;
+    }
+    return false;
+}
diff --git a/tests/manual/ssh/sftp/argumentscollector.h b/tests/manual/ssh/sftp/argumentscollector.h
new file mode 100644
index 0000000000000000000000000000000000000000..9eb776714a318d8037a225899002c1f357c54c73
--- /dev/null
+++ b/tests/manual/ssh/sftp/argumentscollector.h
@@ -0,0 +1,31 @@
+#ifndef ARGUMENTSCOLLECTOR_H
+#define ARGUMENTSCOLLECTOR_H
+
+#include "parameters.h"
+
+#include <QtCore/QStringList>
+
+class ArgumentsCollector
+{
+public:
+    ArgumentsCollector(const QStringList &args);
+    Parameters collect(bool &success) const;
+private:
+    struct ArgumentErrorException
+    {
+        ArgumentErrorException(const QString &error) : error(error) {}
+        const QString error;
+    };
+
+    void printUsage() const;
+    bool checkAndSetStringArg(int &pos, QString &arg, const char *opt) const;
+    bool checkAndSetIntArg(int &pos, int &val, bool &alreadyGiven,
+        const char *opt) const;
+    bool checkForNoProxy(int &pos,
+        Core::SshConnectionParameters::ProxyType &type,
+        bool &alreadyGiven) const;
+
+    const QStringList m_arguments;
+};
+
+#endif // ARGUMENTSCOLLECTOR_H
diff --git a/tests/manual/ssh/sftp/main.cpp b/tests/manual/ssh/sftp/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b182917f1d41b82ef61f4e10aec15115ded5077
--- /dev/null
+++ b/tests/manual/ssh/sftp/main.cpp
@@ -0,0 +1,27 @@
+#include "argumentscollector.h"
+#include "sftptest.h"
+
+#include <coreplugin/ssh/sftpchannel.h>
+#include <coreplugin/ssh/sshconnection.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+
+#include <cstdlib>
+#include <iostream>
+
+using namespace Core;
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication app(argc, argv);
+    bool parseSuccess;
+    const Parameters parameters
+        = ArgumentsCollector(app.arguments()).collect(parseSuccess);
+    if (!parseSuccess)
+        return EXIT_FAILURE;
+    SftpTest sftpTest(parameters);
+    sftpTest.run();
+    return app.exec();
+}
diff --git a/tests/manual/ssh/sftp/parameters.h b/tests/manual/ssh/sftp/parameters.h
new file mode 100644
index 0000000000000000000000000000000000000000..540103525ae1ce77620f171b7ee6c781ad746968
--- /dev/null
+++ b/tests/manual/ssh/sftp/parameters.h
@@ -0,0 +1,14 @@
+#ifndef PARAMETERS_H
+#define PARAMETERS_H
+
+#include <coreplugin/ssh/sshconnection.h>
+
+struct Parameters {
+    Parameters() : sshParams(Core::SshConnectionParameters::DefaultProxy) {}
+
+    Core::SshConnectionParameters sshParams;
+    int smallFileCount;
+    int bigFileSize;
+};
+
+#endif // PARAMETERS_H
diff --git a/tests/manual/ssh/sftp/sftp.pro b/tests/manual/ssh/sftp/sftp.pro
new file mode 100644
index 0000000000000000000000000000000000000000..eb5b7d8e3b82fcaacbdd3ab3b4a2f3f19b60e17d
--- /dev/null
+++ b/tests/manual/ssh/sftp/sftp.pro
@@ -0,0 +1,6 @@
+include(../ssh.pri)
+
+TARGET=sftp
+SOURCES=main.cpp sftptest.cpp argumentscollector.cpp 
+HEADERS=sftptest.h argumentscollector.h parameters.h
+
diff --git a/tests/manual/ssh/sftp/sftptest.cpp b/tests/manual/ssh/sftp/sftptest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..65f41262e4600d31210e2c1d07269cc6e97dc785
--- /dev/null
+++ b/tests/manual/ssh/sftp/sftptest.cpp
@@ -0,0 +1,20 @@
+#include "sftptest.h"
+
+SftpTest::SftpTest(const Parameters &params)
+    : m_parameters(params), m_state(Inactive)
+{
+
+}
+
+void SftpTest::run()
+{
+// connect to remote host
+// create sftp connection
+// create n 1KB files
+// upload these files
+// download these files
+// compare the original to the downloaded files
+// remove local files
+// remove remote files
+// then the same for a big N GB file
+}
diff --git a/tests/manual/ssh/sftp/sftptest.h b/tests/manual/ssh/sftp/sftptest.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9caf6d6abd8d70cfd8d393c5c7aad6f9021e9a9
--- /dev/null
+++ b/tests/manual/ssh/sftp/sftptest.h
@@ -0,0 +1,24 @@
+#ifndef SFTPTEST_H
+#define SFTPTEST_H
+
+#include "parameters.h"
+
+#include <QtCore/QObject>
+
+class SftpTest : public QObject
+{
+    Q_OBJECT
+public:
+    SftpTest(const Parameters &params);
+    void run();
+
+private:
+    enum State { Inactive, Connecting, UploadingSmall, DownloadingSmall,
+        RemovingSmall, UploadingBig, DownloadingBig, RemovingBig
+    };
+    const Parameters m_parameters;
+    State m_state;
+};
+
+
+#endif // SFTPTEST_H
diff --git a/tests/manual/ssh/ssh.pri b/tests/manual/ssh/ssh.pri
new file mode 100644
index 0000000000000000000000000000000000000000..cdbe6778b476133b966419ab30465391889191a3
--- /dev/null
+++ b/tests/manual/ssh/ssh.pri
@@ -0,0 +1,14 @@
+INCLUDEPATH += ../../../../src/plugins
+CREATORLIBPATH = ../../../../lib/qtcreator
+PLUGINPATH=$$CREATORLIBPATH/plugins/Nokia
+LIBS *= -L$$PLUGINPATH -lCore
+LIBS *= -L$$CREATORLIBPATH
+include (../../../qtcreator.pri)
+include (../../../src/plugins/coreplugin/coreplugin_dependencies.pri)
+QT       += core
+QT       -= gui
+CONFIG   += console
+CONFIG   -= app_bundle
+TEMPLATE = app
+DEPENDPATH+=.
+INCLUDEPATH+=.
\ No newline at end of file
diff --git a/tests/manual/ssh/ssh.pro b/tests/manual/ssh/ssh.pro
index 772ff2a39cb214e31c8c4f7c9ba8d3172b58c875..432f8f192b54a74555c291165b25c2fea75c7fac 100644
--- a/tests/manual/ssh/ssh.pro
+++ b/tests/manual/ssh/ssh.pro
@@ -4,23 +4,5 @@
 #
 #-------------------------------------------------
 
-INCLUDEPATH += ../../../src/plugins
-CREATORLIBPATH = ../../../lib/qtcreator
-PLUGINPATH=$$CREATORLIBPATH/plugins/Nokia
-LIBS *= -L$$PLUGINPATH -lCore
-LIBS *= -L$$CREATORLIBPATH
-include (../../../qtcreator.pri)
-include (../../../src/plugins/coreplugin/coreplugin_dependencies.pri)
-
-QT       += core
-
-QT       -= gui
-
-TARGET = ssh
-CONFIG   += console
-CONFIG   -= app_bundle
-
-TEMPLATE = app
-
-
-SOURCES += main.cpp
+TEMPLATE = subdirs
+SUBDIRS = errorhandling sftp