diff options
author | Christian Kandeler <christian.kandeler@nokia.com> | 2011-12-21 20:14:42 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@nokia.com> | 2011-12-21 21:59:18 +0100 |
commit | 79db165dcb7c6999ccc9241910b7f762f358188a (patch) | |
tree | 1b6c529a6a877fdedb97bf52bb25a5700e4456a2 /src | |
parent | 3b67e5dd37ba539b72bc14417d2bea770c1ef88b (diff) | |
download | qt-creator-79db165dcb7c6999ccc9241910b7f762f358188a.tar.gz |
Revert "Remote Linux: Rework device testing"
This reverts commit 934c067ddf365c6f12b1e4a1e431f27610b32f7d,
because it breaks running remote Linux applications due to
buggy refactoring of the remote ports gatherer.
Change-Id: I15fd8d4f3e76452a8c5c735316991bd00900444f
Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
Diffstat (limited to 'src')
22 files changed, 703 insertions, 613 deletions
diff --git a/src/plugins/madde/madde.pro b/src/plugins/madde/madde.pro index debbe8c880..2ff8bf148e 100644 --- a/src/plugins/madde/madde.pro +++ b/src/plugins/madde/madde.pro @@ -50,6 +50,7 @@ HEADERS += \ maemorunconfiguration.h \ maddeuploadandinstallpackagesteps.h \ maemodeploybymountsteps.h \ + maddedevicetester.h \ maddedeviceconfigurationfactory.h \ SOURCES += \ @@ -95,6 +96,7 @@ SOURCES += \ maddedeviceconfigurationfactory.cpp \ maddeuploadandinstallpackagesteps.cpp \ maemodeploybymountsteps.cpp \ + maddedevicetester.cpp \ maemorunconfiguration.cpp FORMS += \ diff --git a/src/plugins/madde/maddedeviceconfigurationfactory.cpp b/src/plugins/madde/maddedeviceconfigurationfactory.cpp index d1d43506c9..7dfff2837a 100644 --- a/src/plugins/madde/maddedeviceconfigurationfactory.cpp +++ b/src/plugins/madde/maddedeviceconfigurationfactory.cpp @@ -31,9 +31,9 @@ **************************************************************************/ #include "maddedeviceconfigurationfactory.h" +#include "maddedevicetester.h" #include "maemoconstants.h" #include "maemodeviceconfigwizard.h" -#include "maemoglobal.h" #include <remotelinux/linuxdevicetestdialog.h> #include <remotelinux/publickeydeploymentdialog.h> @@ -46,8 +46,10 @@ using namespace RemoteLinux; namespace Madde { namespace Internal { - +namespace { +const char MaddeDeviceTestActionId[] = "Madde.DeviceTestAction"; const char MaddeRemoteProcessesActionId[] = "Madde.RemoteProcessesAction"; +} // anonymous namespace MaddeDeviceConfigurationFactory::MaddeDeviceConfigurationFactory(QObject *parent) : ILinuxDeviceConfigurationFactory(parent) @@ -105,27 +107,8 @@ QDialog *MaddeDeviceConfigurationFactory::createDeviceAction(const QString &acti { Q_ASSERT(supportedDeviceActionIds().contains(actionId)); - if (actionId == QLatin1String(MaddeDeviceTestActionId)) { - QList<LinuxDeviceTester *> tests; - tests.append(new AuthenticationTester(deviceConfig)); - tests.append(new LinuxDeviceTester(deviceConfig, - tr("Checking kernel version..."), - QLatin1String("uname -rsm"))); - QString infoCmd = QLatin1String("dpkg-query -W -f " - "'${Package} ${Version} ${Status}\\n' 'libqt*' | " - "grep ' installed$' | cut -d' ' -f-2"); - if (deviceConfig->osType() == MeeGoOsType) - infoCmd = QLatin1String("rpm -qa 'libqt*' --queryformat '%{NAME} %{VERSION}\\n'"); - tests.append(new LinuxDeviceTester(deviceConfig, tr("Checking for Qt libraries..."), infoCmd)); - tests.append(new LinuxDeviceTester(deviceConfig, - tr("Checking for connectivity support..."), - QLatin1String("test -x ") + MaemoGlobal::devrootshPath())); - tests.append(new LinuxDeviceTester(deviceConfig, - tr("Checking for QML tooling support..."), - QLatin1String("test -d /usr/lib/qt4/plugins/qmltooling"))); - tests.append(new UsedPortsTester(deviceConfig)); - return new LinuxDeviceTestDialog(tests, parent); - } + if (actionId == QLatin1String(MaddeDeviceTestActionId)) + return new LinuxDeviceTestDialog(deviceConfig, new MaddeDeviceTester, parent); if (actionId == QLatin1String(MaddeRemoteProcessesActionId)) return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(deviceConfig), parent); if (actionId == QLatin1String(Constants::GenericDeployKeyToDeviceActionId)) diff --git a/src/plugins/madde/maddedeviceconfigurationfactory.h b/src/plugins/madde/maddedeviceconfigurationfactory.h index 133b9b1970..38da1b9894 100644 --- a/src/plugins/madde/maddedeviceconfigurationfactory.h +++ b/src/plugins/madde/maddedeviceconfigurationfactory.h @@ -37,8 +37,6 @@ namespace Madde { namespace Internal { -const char MaddeDeviceTestActionId[] = "Madde.DeviceTestAction"; - class MaddeDeviceConfigurationFactory : public RemoteLinux::ILinuxDeviceConfigurationFactory { Q_OBJECT diff --git a/src/plugins/madde/maddedevicetester.cpp b/src/plugins/madde/maddedevicetester.cpp new file mode 100644 index 0000000000..0968f20695 --- /dev/null +++ b/src/plugins/madde/maddedevicetester.cpp @@ -0,0 +1,293 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#include "maddedevicetester.h" + +#include "maemoconstants.h" +#include "maemoglobal.h" + +#include <remotelinux/linuxdeviceconfiguration.h> +#include <utils/qtcassert.h> +#include <utils/ssh/sshremoteprocessrunner.h> + +#include <QtCore/QRegExp> + +using namespace RemoteLinux; +using namespace Utils; + +namespace Madde { +namespace Internal { +namespace { +const char QmlToolingDirectory[] = "/usr/lib/qt4/plugins/qmltooling"; +} // anonymous namespace + +MaddeDeviceTester::MaddeDeviceTester(QObject *parent) + : AbstractLinuxDeviceTester(parent), + m_genericTester(new GenericLinuxDeviceTester(this)), + m_state(Inactive), + m_processRunner(0) +{ +} + +MaddeDeviceTester::~MaddeDeviceTester() +{ +} + +void MaddeDeviceTester::testDevice(const LinuxDeviceConfiguration::ConstPtr &deviceConfiguration) +{ + QTC_ASSERT(m_state == Inactive, return); + + m_deviceConfiguration = deviceConfiguration; + m_result = TestSuccess; + + m_state = GenericTest; + connect(m_genericTester, SIGNAL(progressMessage(QString)), SIGNAL(progressMessage(QString))); + connect(m_genericTester, SIGNAL(errorMessage(QString)), SIGNAL(errorMessage(QString))); + connect(m_genericTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)), + SLOT(handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult))); + m_genericTester->testDevice(deviceConfiguration); +} + +void MaddeDeviceTester::stopTest() +{ + QTC_ASSERT(m_state != Inactive, return); + + switch (m_state) { + case Inactive: + break; + case GenericTest: + m_genericTester->stopTest(); + break; + case QtTest: + case MadDeveloperTest: + case QmlToolingTest: + m_processRunner->cancel(); + break; + } + + m_result = TestFailure; + setFinished(); +} + +void MaddeDeviceTester::handleGenericTestFinished(TestResult result) +{ + QTC_ASSERT(m_state == GenericTest, return); + + if (result == TestFailure) { + m_result = TestFailure; + setFinished(); + return; + } + + if (!m_processRunner) + m_processRunner = new SshRemoteProcessRunner(this); + connect(m_processRunner, SIGNAL(connectionError()), SLOT(handleConnectionError())); + connect(m_processRunner, SIGNAL(processOutputAvailable(QByteArray)), + SLOT(handleStdout(QByteArray))); + connect(m_processRunner, SIGNAL(processErrorOutputAvailable(QByteArray)), + SLOT(handleStderr(QByteArray))); + connect(m_processRunner, SIGNAL(processClosed(int)), SLOT(handleProcessFinished(int))); + + QString qtInfoCmd; + if (m_deviceConfiguration->osType() == QLatin1String(MeeGoOsType)) { + qtInfoCmd = QLatin1String("rpm -qa 'libqt*' --queryformat '%{NAME} %{VERSION}\\n'"); + } else { + qtInfoCmd = QLatin1String("dpkg-query -W -f " + "'${Package} ${Version} ${Status}\n' 'libqt*' |grep ' installed$'"); + } + + emit progressMessage(tr("Checking for Qt libraries...")); + m_stdout.clear(); + m_stderr.clear(); + m_state = QtTest; + m_processRunner->run(qtInfoCmd.toUtf8(), m_genericTester->connection()->connectionParameters()); +} + +void MaddeDeviceTester::handleConnectionError() +{ + QTC_ASSERT(m_state != Inactive, return); + + emit errorMessage(tr("SSH connection error: %1\n") + .arg(m_processRunner->lastConnectionErrorString())); + m_result = TestFailure; + setFinished(); +} + +void MaddeDeviceTester::handleStdout(const QByteArray &data) +{ + QTC_ASSERT(m_state == QtTest || m_state == MadDeveloperTest || m_state == QmlToolingTest, + return); + + m_stdout += data; +} + +void MaddeDeviceTester::handleStderr(const QByteArray &data) +{ + QTC_ASSERT(m_state == QtTest || m_state == MadDeveloperTest || m_state == QmlToolingTest, + return); + + m_stderr += data; +} + +void MaddeDeviceTester::handleProcessFinished(int exitStatus) +{ + switch (m_state) { + case QtTest: + handleQtTestFinished(exitStatus); + break; + case MadDeveloperTest: + handleMadDeveloperTestFinished(exitStatus); + break; + case QmlToolingTest: + handleQmlToolingTestFinished(exitStatus); + break; + default: + qWarning("%s: Unexpected state %d.", Q_FUNC_INFO, m_state); + } +} + +void MaddeDeviceTester::handleQtTestFinished(int exitStatus) +{ + if (exitStatus != SshRemoteProcess::ExitedNormally + || m_processRunner->processExitCode() != 0) { + if (!m_stderr.isEmpty()) { + emit errorMessage(tr("Error checking for Qt libraries: %1\n") + .arg(QString::fromUtf8(m_stderr))); + } else { + emit errorMessage(tr("Error checking for Qt libraries.\n")); + } + + m_result = TestFailure; + } else { + emit progressMessage(processedQtLibsList()); + } + + m_stdout.clear(); + m_stderr.clear(); + + emit progressMessage(tr("Checking for connectivity support...")); + m_state = MadDeveloperTest; + m_processRunner->run(QString(QLatin1String("test -x") + MaemoGlobal::devrootshPath()).toUtf8(), + m_genericTester->connection()->connectionParameters()); +} + +void MaddeDeviceTester::handleMadDeveloperTestFinished(int exitStatus) +{ + if (exitStatus != SshRemoteProcess::ExitedNormally) { + if (!m_stderr.isEmpty()) { + emit errorMessage(tr("Error checking for connectivity tool: %1\n") + .arg(QString::fromUtf8(m_stderr))); + } else { + emit errorMessage(tr("Error checking for connectivity tool.\n")); + } + m_result = TestFailure; + } else if (m_processRunner->processExitCode() != 0) { + QString message = tr("Connectivity tool not installed on device. " + "Deployment currently not possible."); + if (m_deviceConfiguration->osType() == QLatin1String(HarmattanOsType)) { + message += tr("Please switch the device to developer mode " + "via Settings -> Security."); + } + emit errorMessage(message + QLatin1Char('\n')); + m_result = TestFailure; + } else { + emit progressMessage(tr("Connectivity tool present.\n")); + } + + if (m_deviceConfiguration->osType() != QLatin1String(HarmattanOsType)) { + setFinished(); + return; + } + + m_stdout.clear(); + m_stderr.clear(); + + emit progressMessage(tr("Checking for QML tooling support...")); + m_state = QmlToolingTest; + m_processRunner->run(QString(QLatin1String("test -d ") + + QLatin1String(QmlToolingDirectory)).toUtf8(), + m_genericTester->connection()->connectionParameters()); +} + +void MaddeDeviceTester::handleQmlToolingTestFinished(int exitStatus) +{ + if (exitStatus != SshRemoteProcess::ExitedNormally) { + if (!m_stderr.isEmpty()) { + emit errorMessage(tr("Error checking for QML tooling support: %1\n") + .arg(QString::fromUtf8(m_stderr))); + } else { + emit errorMessage(tr("Error checking for QML tooling support.\n")); + } + m_result = TestFailure; + } else if (m_processRunner->processExitCode() != 0) { + emit errorMessage(tr("Missing directory '%1'. You will not be able to do " + "QML debugging on this device.\n").arg(QmlToolingDirectory)); + m_result = TestFailure; + } else { + emit progressMessage(tr("QML tooling support present.\n")); + } + + setFinished(); +} + +QString MaddeDeviceTester::processedQtLibsList() +{ + QString unfilteredLibs = QString::fromUtf8(m_stdout); + QString filteredLibs; + QString patternString; + if (m_deviceConfiguration->osType() == QLatin1String(MeeGoOsType)) + patternString = QLatin1String("(libqt\\S+) ((\\d+)\\.(\\d+)\\.(\\d+))"); + else + patternString = QLatin1String("(\\S+) (\\S*(\\d+)\\.(\\d+)\\.(\\d+)\\S*) \\S+ \\S+ \\S+"); + const QRegExp packagePattern(patternString); + int index = packagePattern.indexIn(unfilteredLibs); + if (index == -1) + return tr("No Qt packages installed."); + + do { + filteredLibs += QLatin1String(" ") + packagePattern.cap(1) + QLatin1String(": ") + + packagePattern.cap(2) + QLatin1Char('\n'); + index = packagePattern.indexIn(unfilteredLibs, index + packagePattern.cap(0).length()); + } while (index != -1); + return filteredLibs; +} + + void MaddeDeviceTester::setFinished() +{ + m_state = Inactive; + disconnect(m_genericTester, 0, this, 0); + if (m_processRunner) + disconnect(m_processRunner, 0, this, 0); + emit finished(m_result); +} + +} // namespace Internal +} // namespace Madde diff --git a/src/plugins/madde/maddedevicetester.h b/src/plugins/madde/maddedevicetester.h new file mode 100644 index 0000000000..cb13fe9109 --- /dev/null +++ b/src/plugins/madde/maddedevicetester.h @@ -0,0 +1,85 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#ifndef MADDEDEVICETESTER_H +#define MADDEDEVICETESTER_H + +#include <remotelinux/linuxdevicetester.h> + +#include <QtCore/QByteArray> + +namespace Utils { +class SshRemoteProcessRunner; +} + +namespace Madde { +namespace Internal { + +class MaddeDeviceTester : public RemoteLinux::AbstractLinuxDeviceTester +{ + Q_OBJECT +public: + explicit MaddeDeviceTester(QObject *parent = 0); + ~MaddeDeviceTester(); + + void testDevice(const QSharedPointer<const RemoteLinux::LinuxDeviceConfiguration> &deviceConfiguration); + void stopTest(); + +private slots: + void handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result); + void handleConnectionError(); + void handleStdout(const QByteArray &data); + void handleStderr(const QByteArray &data); + void handleProcessFinished(int exitStatus); + +private: + enum State { Inactive, GenericTest, QtTest, MadDeveloperTest, QmlToolingTest }; + + void handleQtTestFinished(int exitStatus); + void handleMadDeveloperTestFinished(int exitStatus); + void handleQmlToolingTestFinished(int exitStatus); + + QString processedQtLibsList(); + void setFinished(); + + RemoteLinux::GenericLinuxDeviceTester * const m_genericTester; + State m_state; + TestResult m_result; + Utils::SshRemoteProcessRunner *m_processRunner; + QSharedPointer<const RemoteLinux::LinuxDeviceConfiguration> m_deviceConfiguration; + QByteArray m_stdout; + QByteArray m_stderr; +}; + +} // namespace Internal +} // namespace Madde + +#endif // MADDEDEVICETESTER_H diff --git a/src/plugins/madde/maemodeploymentmounter.cpp b/src/plugins/madde/maemodeploymentmounter.cpp index 648ed0cbf7..81cca42c61 100644 --- a/src/plugins/madde/maemodeploymentmounter.cpp +++ b/src/plugins/madde/maemodeploymentmounter.cpp @@ -52,7 +52,7 @@ MaemoDeploymentMounter::MaemoDeploymentMounter(QObject *parent) : QObject(parent), m_state(Inactive), m_mounter(new MaemoRemoteMounter(this)), - m_portsGatherer(0) + m_portsGatherer(new RemoteLinuxUsedPortsGatherer(this)) { connect(m_mounter, SIGNAL(error(QString)), SLOT(handleMountError(QString))); connect(m_mounter, SIGNAL(mounted()), SLOT(handleMounted())); @@ -61,6 +61,11 @@ MaemoDeploymentMounter::MaemoDeploymentMounter(QObject *parent) SIGNAL(reportProgress(QString))); connect(m_mounter, SIGNAL(debugOutput(QString)), SIGNAL(debugOutput(QString))); + + connect(m_portsGatherer, SIGNAL(error(QString)), + SLOT(handlePortsGathererError(QString))); + connect(m_portsGatherer, SIGNAL(portListReady()), + SLOT(handlePortListReady())); } MaemoDeploymentMounter::~MaemoDeploymentMounter() {} @@ -137,12 +142,7 @@ void MaemoDeploymentMounter::handleUnmounted() break; case UnmountingCurrentDirs: setState(GatheringPorts); - if (m_portsGatherer) - delete m_portsGatherer; - m_portsGatherer = new RemoteLinuxUsedPortsGatherer(m_devConf); - connect(m_portsGatherer, SIGNAL(finished(RemoteLinux::LinuxDeviceTester::TestResult)), - this, SLOT(handlePortListReady(RemoteLinux::LinuxDeviceTester::TestResult))); - m_portsGatherer->run(); + m_portsGatherer->start(m_connection, m_devConf); break; case UnmountingCurrentMounts: setState(Inactive); @@ -166,20 +166,16 @@ void MaemoDeploymentMounter::handlePortsGathererError(const QString &errorMsg) emit error(errorMsg); } -void MaemoDeploymentMounter::handlePortListReady(LinuxDeviceTester::TestResult result) +void MaemoDeploymentMounter::handlePortListReady() { QTC_ASSERT(m_state == GatheringPorts || m_state == Inactive, return); if (m_state == Inactive) return; - if (result == LinuxDeviceTester::TestFailure) { - handlePortsGathererError(tr("Failed to gather port information.")); - } else { - setState(Mounting); - m_freePorts = MaemoGlobal::freePorts(m_devConf, m_buildConfig->qtVersion()); - m_mounter->mount(&m_freePorts, m_portsGatherer); - } + setState(Mounting); + m_freePorts = MaemoGlobal::freePorts(m_devConf, m_buildConfig->qtVersion()); + m_mounter->mount(&m_freePorts, m_portsGatherer); } void MaemoDeploymentMounter::handleMountError(const QString &errorMsg) diff --git a/src/plugins/madde/maemodeploymentmounter.h b/src/plugins/madde/maemodeploymentmounter.h index 50a1690958..0a6ac4a698 100644 --- a/src/plugins/madde/maemodeploymentmounter.h +++ b/src/plugins/madde/maemodeploymentmounter.h @@ -35,7 +35,6 @@ #include "maemomountspecification.h" -#include <remotelinux/linuxdevicetester.h> #include <remotelinux/portlist.h> #include <QtCore/QList> @@ -80,7 +79,7 @@ private slots: void handleUnmounted(); void handleMountError(const QString &errorMsg); void handlePortsGathererError(const QString &errorMsg); - void handlePortListReady(RemoteLinux::LinuxDeviceTester::TestResult result); + void handlePortListReady(); void handleConnectionError(); private: @@ -97,7 +96,7 @@ private: QSharedPointer<Utils::SshConnection> m_connection; QSharedPointer<const RemoteLinux::LinuxDeviceConfiguration> m_devConf; MaemoRemoteMounter * const m_mounter; - RemoteLinux::RemoteLinuxUsedPortsGatherer *m_portsGatherer; + RemoteLinux::RemoteLinuxUsedPortsGatherer * const m_portsGatherer; RemoteLinux::PortList m_freePorts; QList<MaemoMountSpecification> m_mountSpecs; const Qt4ProjectManager::Qt4BuildConfiguration *m_buildConfig; diff --git a/src/plugins/madde/maemodeviceconfigwizard.cpp b/src/plugins/madde/maemodeviceconfigwizard.cpp index a4f6f65616..a627912870 100644 --- a/src/plugins/madde/maemodeviceconfigwizard.cpp +++ b/src/plugins/madde/maemodeviceconfigwizard.cpp @@ -30,23 +30,21 @@ **************************************************************************/ #include "maemodeviceconfigwizard.h" -#include "maddedeviceconfigurationfactory.h" #include "ui_maemodeviceconfigwizardkeycreationpage.h" #include "ui_maemodeviceconfigwizardkeydeploymentpage.h" #include "ui_maemodeviceconfigwizardpreviouskeysetupcheckpage.h" #include "ui_maemodeviceconfigwizardreusekeyscheckpage.h" #include "ui_maemodeviceconfigwizardstartpage.h" +#include "maddedevicetester.h" #include "maemoconstants.h" #include "maemoglobal.h" -#include <extensionsystem/pluginmanager.h> #include <remotelinux/genericlinuxdeviceconfigurationwizardpages.h> #include <remotelinux/linuxdevicetestdialog.h> #include <remotelinux/remotelinuxutils.h> #include <remotelinux/sshkeydeployer.h> #include <utils/fileutils.h> -#include <utils/qtcassert.h> #include <utils/ssh/sshkeygenerator.h> #include <QtCore/QDir> @@ -584,13 +582,8 @@ LinuxDeviceConfiguration::Ptr MaemoDeviceConfigWizard::deviceConfiguration() d->wizardData.osType, d->wizardData.deviceType, PortList::fromString(freePortsSpec), sshParams); if (doTest) { - MaddeDeviceConfigurationFactory *factory - = ExtensionSystem::PluginManager::instance()->getObject<MaddeDeviceConfigurationFactory>(); - QTC_ASSERT(factory, return LinuxDeviceConfiguration::Ptr(0)); - QDialog *dlg = factory->createDeviceAction(QLatin1String(MaddeDeviceTestActionId), devConf, 0); - QTC_ASSERT(dlg, return LinuxDeviceConfiguration::Ptr(0)); - dlg->exec(); - delete dlg; + LinuxDeviceTestDialog dlg(devConf, new MaddeDeviceTester(this), this); + dlg.exec(); } return devConf; } diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp index 364b5a2792..65f3653308 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp @@ -93,15 +93,8 @@ QDialog *GenericLinuxDeviceConfigurationFactory::createDeviceAction(const QStrin { Q_ASSERT(supportedDeviceActionIds().contains(actionId)); - if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) { - QList<LinuxDeviceTester *> tests; - tests.append(new AuthenticationTester(deviceConfig)); - tests.append(new LinuxDeviceTester(deviceConfig, - tr("Checking kernel version..."), - QLatin1String("uname -rsm"))); - tests.append(new UsedPortsTester(deviceConfig)); - return new LinuxDeviceTestDialog(tests, parent); - } + if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) + return new LinuxDeviceTestDialog(deviceConfig, new GenericLinuxDeviceTester, parent); if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) { return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(deviceConfig), parent); diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h index 931ae931b9..c29f52435f 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h @@ -29,7 +29,6 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ - #ifndef GENERICLINUXDEVICECONFIGURATIONFACTORY_H #define GENERICLINUXDEVICECONFIGURATIONFACTORY_H diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp index 8bba285cf4..bbb838d98d 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp @@ -30,17 +30,12 @@ **************************************************************************/ #include "genericlinuxdeviceconfigurationwizard.h" -#include "genericlinuxdeviceconfigurationfactory.h" #include "genericlinuxdeviceconfigurationwizardpages.h" #include "linuxdevicetestdialog.h" #include "linuxdevicetester.h" #include "portlist.h" #include "remotelinux_constants.h" -#include <extensionsystem/pluginmanager.h> - -#include <utils/qtcassert.h> - using namespace Utils; namespace RemoteLinux { @@ -92,16 +87,8 @@ LinuxDeviceConfiguration::Ptr GenericLinuxDeviceConfigurationWizard::deviceConfi LinuxDeviceConfiguration::Ptr devConf = LinuxDeviceConfiguration::create(d->setupPage.configurationName(), QLatin1String(Constants::GenericLinuxOsType), LinuxDeviceConfiguration::Hardware, PortList::fromString(QLatin1String("10000-10100")), sshParams); - - GenericLinuxDeviceConfigurationFactory *factory = - ExtensionSystem::PluginManager::instance()->getObject<GenericLinuxDeviceConfigurationFactory>(); - QTC_ASSERT(factory, return LinuxDeviceConfiguration::Ptr(0)); - - QDialog *dlg = factory->createDeviceAction(QLatin1String(Constants::GenericTestDeviceActionId), devConf, 0); - QTC_ASSERT(dlg, return LinuxDeviceConfiguration::Ptr(0)); - dlg->exec(); - delete dlg; - + LinuxDeviceTestDialog dlg(devConf, new GenericLinuxDeviceTester(this), this); + dlg.exec(); return devConf; } diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.cpp b/src/plugins/remotelinux/linuxdevicetestdialog.cpp index e19f2c0a9a..dcb9cfbb4a 100644 --- a/src/plugins/remotelinux/linuxdevicetestdialog.cpp +++ b/src/plugins/remotelinux/linuxdevicetestdialog.cpp @@ -32,9 +32,6 @@ #include "linuxdevicetestdialog.h" #include "ui_linuxdevicetestdialog.h" -#include <utils/qtcassert.h> -#include <utils/ssh/sshconnectionmanager.h> - #include <QtGui/QBrush> #include <QtGui/QColor> #include <QtGui/QFont> @@ -43,77 +40,34 @@ namespace RemoteLinux { namespace Internal { - -class LinuxDeviceTestDialogPrivate -{ +class LinuxDeviceTestDialogPrivate { public: - LinuxDeviceTestDialogPrivate(LinuxDeviceTestDialog *qptr, QList<LinuxDeviceTester *> &tester) - : deviceTests(tester), lastTest(0), currentTestPosition(-1), failCount(0), q(qptr) - { } - - ~LinuxDeviceTestDialogPrivate() - { - qDeleteAll(deviceTests); - } - - LinuxDeviceTester *currentTest() - { - return deviceTests.at(currentTestPosition); - } - - void runTest() - { - if (lastTest) - QObject::disconnect(lastTest, 0, q, 0); - - LinuxDeviceTester *curTest = currentTest(); - - QObject::connect(curTest, SIGNAL(progressMessage(QString)), - q, SLOT(handleProgressMessage(QString))); - QObject::connect(curTest, SIGNAL(errorMessage(QString)), - q, SLOT(handleErrorMessage(QString))); - QObject::connect(curTest, SIGNAL(finished(int)), - q, SLOT(handleTestFinished(int))); - - lastTest = curTest; - - q->addText(curTest->headLine(), QLatin1String("black"), true); - q->addText(curTest->commandLine(), QLatin1String("darkGray"), false); - curTest->run(); - } - - bool runNextTest() + LinuxDeviceTestDialogPrivate(AbstractLinuxDeviceTester *tester) + : deviceTester(tester), finished(false) { - ++currentTestPosition; - if (currentTestPosition < deviceTests.count()) { - runTest(); - } else { - currentTestPosition = -1; - lastTest = 0; - } - - return currentTestPosition != -1; } Ui::LinuxDeviceTestDialog ui; - QList<LinuxDeviceTester *> deviceTests; - LinuxDeviceTester *lastTest; - int currentTestPosition; - int failCount; - LinuxDeviceTestDialog *const q; + AbstractLinuxDeviceTester * const deviceTester; + bool finished; }; } // namespace Internal -LinuxDeviceTestDialog::LinuxDeviceTestDialog(QList<LinuxDeviceTester *> tests, QWidget *parent) : - QDialog(parent), - d(new Internal::LinuxDeviceTestDialogPrivate(this, tests)) -{ - QTC_ASSERT(!tests.isEmpty(), return); +using namespace Internal; +LinuxDeviceTestDialog::LinuxDeviceTestDialog(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, + AbstractLinuxDeviceTester *deviceTester, QWidget *parent) + : QDialog(parent), d(new LinuxDeviceTestDialogPrivate(deviceTester)) +{ d->ui.setupUi(this); - d->runNextTest(); + d->deviceTester->setParent(this); + connect(d->deviceTester, SIGNAL(progressMessage(QString)), SLOT(handleProgressMessage(QString))); + connect(d->deviceTester, SIGNAL(errorMessage(QString)), SLOT(handleErrorMessage(QString))); + connect(d->deviceTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)), + SLOT(handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult))); + d->deviceTester->testDevice(deviceConfiguration); } LinuxDeviceTestDialog::~LinuxDeviceTestDialog() @@ -123,22 +77,14 @@ LinuxDeviceTestDialog::~LinuxDeviceTestDialog() void LinuxDeviceTestDialog::reject() { - if (d->currentTestPosition >= 0) { - d->deviceTests.at(d->currentTestPosition)->cancel(); - disconnect(d->deviceTests.at(d->currentTestPosition), 0, this, 0); - } - + if (!d->finished) + d->deviceTester->stopTest(); QDialog::reject(); } void LinuxDeviceTestDialog::handleProgressMessage(const QString &message) { - QString tmp = QLatin1String(" ") + message; - if (tmp.endsWith('\n')) - tmp = tmp.left(tmp.count() - 1); - tmp.replace(QLatin1Char('\n'), QLatin1String("\n ")); - - addText(tmp, QLatin1String("black"), false); + addText(message, QLatin1String("black"), false); } void LinuxDeviceTestDialog::handleErrorMessage(const QString &message) @@ -146,33 +92,15 @@ void LinuxDeviceTestDialog::handleErrorMessage(const QString &message) addText(message, QLatin1String("red"), false); } -void LinuxDeviceTestDialog::handleTestFinished(int result) +void LinuxDeviceTestDialog::handleTestFinished(AbstractLinuxDeviceTester::TestResult result) { - bool abortRun = false; - if (result == LinuxDeviceTester::TestSuccess) { - addText(tr("Ok.\n"), QLatin1String("black"), true); - } else if (result == LinuxDeviceTester::TestCriticalFailure) { - addText(tr("Critical device test failure, aborting.\n"), QLatin1String("red"), true); - ++d->failCount; - abortRun = true; - } else { - addText(tr("Device test failed.\n"), QLatin1String("red"), true); - ++d->failCount; - } - - if (abortRun || !d->runNextTest()) { - if (d->failCount == 0 && !abortRun) { - addText(tr("All device tests finished successfully.\n"), QLatin1String("blue"), true); - } else { - if (!abortRun) { - //: %1: number of failed tests, %2 total tests - addText(tr("%1 device tests of %2 failed.\n").arg(d->failCount).arg(d->deviceTests.count()), - QLatin1String("red"), true); - } - } + d->finished = true; + d->ui.buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close")); - d->ui.buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close")); - } + if (result == AbstractLinuxDeviceTester::TestSuccess) + addText(tr("Device test finished successfully."), QLatin1String("blue"), true); + else + addText(tr("Device test failed."), QLatin1String("red"), true); } void LinuxDeviceTestDialog::addText(const QString &text, const QString &color, bool bold) diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.h b/src/plugins/remotelinux/linuxdevicetestdialog.h index 6aa150bcc3..ec8becdce9 100644 --- a/src/plugins/remotelinux/linuxdevicetestdialog.h +++ b/src/plugins/remotelinux/linuxdevicetestdialog.h @@ -47,8 +47,9 @@ class REMOTELINUX_EXPORT LinuxDeviceTestDialog : public QDialog Q_OBJECT public: - // Note: The dialog takes ownership of deviceTests - LinuxDeviceTestDialog(QList<LinuxDeviceTester *> tests, QWidget *parent = 0); + // Note: The dialog takes ownership of deviceTester + explicit LinuxDeviceTestDialog(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, + AbstractLinuxDeviceTester * deviceTester, QWidget *parent = 0); ~LinuxDeviceTestDialog(); void reject(); @@ -56,14 +57,12 @@ public: private slots: void handleProgressMessage(const QString &message); void handleErrorMessage(const QString &message); - void handleTestFinished(int result); + void handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result); private: void addText(const QString &text, const QString &color, bool bold); - Internal::LinuxDeviceTestDialogPrivate *const d; - - friend class Internal::LinuxDeviceTestDialogPrivate; + Internal::LinuxDeviceTestDialogPrivate * const d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index 5d2f4b2c9a..cd9c465174 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -35,99 +35,164 @@ #include "remotelinuxusedportsgatherer.h" #include <utils/qtcassert.h> -#include <utils/ssh/sshremoteprocessrunner.h> +#include <utils/ssh/sshremoteprocess.h> #include <utils/ssh/sshconnection.h> -#include <utils/ssh/sshconnectionmanager.h> using namespace Utils; namespace RemoteLinux { namespace Internal { +namespace { -class LinuxDeviceTesterPrivate +enum State { Inactive, Connecting, RunningUname, TestingPorts }; + +} // anonymous namespace + +class GenericLinuxDeviceTesterPrivate { public: - LinuxDeviceTesterPrivate() - { } + GenericLinuxDeviceTesterPrivate() : state(Inactive) {} - QString headLine; + LinuxDeviceConfiguration::ConstPtr deviceConfiguration; + SshConnection::Ptr connection; + SshRemoteProcess::Ptr process; + RemoteLinuxUsedPortsGatherer portsGatherer; + State state; }; } // namespace Internal using namespace Internal; -LinuxDeviceTester::LinuxDeviceTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &headline, const QString &commandline) : - SimpleRunner(deviceConfiguration, commandline), - d(new LinuxDeviceTesterPrivate) +AbstractLinuxDeviceTester::AbstractLinuxDeviceTester(QObject *parent) : QObject(parent) { - d->headLine = headline; } -LinuxDeviceTester::~LinuxDeviceTester() + +GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent) + : AbstractLinuxDeviceTester(parent), d(new GenericLinuxDeviceTesterPrivate) { - delete d; } -QString LinuxDeviceTester::headLine() const +GenericLinuxDeviceTester::~GenericLinuxDeviceTester() { - return d->headLine; + delete d; } -int LinuxDeviceTester::processFinished(int exitStatus) +void GenericLinuxDeviceTester::testDevice(const LinuxDeviceConfiguration::ConstPtr &deviceConfiguration) { - return SimpleRunner::processFinished(exitStatus) == 0 ? TestSuccess : TestFailure; + QTC_ASSERT(d->state == Inactive, return); + + d->deviceConfiguration = deviceConfiguration; + d->connection = SshConnection::create(deviceConfiguration->sshParameters()); + connect(d->connection.data(), SIGNAL(connected()), SLOT(handleConnected())); + connect(d->connection.data(), SIGNAL(error(Utils::SshError)), + SLOT(handleConnectionFailure())); + + emit progressMessage(tr("Connecting to host...")); + d->state = Connecting; + d->connection->connectToHost(); } -AuthenticationTester::AuthenticationTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) : - LinuxDeviceTester(deviceConfiguration, tr("Checking authentication data..."), - QLatin1String("echo \"Success!\"")) +void GenericLinuxDeviceTester::stopTest() { - SshConnectionManager::instance().forceNewConnection(sshParameters()); + QTC_ASSERT(d->state != Inactive, return); + + switch (d->state) { + case Connecting: + d->connection->disconnectFromHost(); + break; + case TestingPorts: + d->portsGatherer.stop(); + break; + case RunningUname: + d->process->close(); + break; + case Inactive: + break; + } + + setFinished(TestFailure); } -void AuthenticationTester::handleStdOutput(const QByteArray &data) +SshConnection::Ptr GenericLinuxDeviceTester::connection() const { - m_authenticationSucceded = data.contains("Success!"); - LinuxDeviceTester::handleStdOutput(data); + return d->connection; } -int AuthenticationTester::processFinished(int exitStatus) +void GenericLinuxDeviceTester::handleConnected() { - return LinuxDeviceTester::processFinished(exitStatus) == TestSuccess - && m_authenticationSucceded ? TestSuccess : TestCriticalFailure; + QTC_ASSERT(d->state == Connecting, return); + + d->process = d->connection->createRemoteProcess("uname -rsm"); + connect(d->process.data(), SIGNAL(closed(int)), SLOT(handleProcessFinished(int))); + + emit progressMessage("Checking kernel version..."); + d->state = RunningUname; + d->process->start(); } -UsedPortsTester::UsedPortsTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) : - LinuxDeviceTester(deviceConfiguration, tr("Checking for available ports..."), QString()), - gatherer(new RemoteLinuxUsedPortsGatherer(deviceConfiguration)) +void GenericLinuxDeviceTester::handleConnectionFailure() { - connect(gatherer, SIGNAL(aboutToStart()), this, SIGNAL(aboutToStart())); - connect(gatherer, SIGNAL(errorMessage(QString)), this, SIGNAL(errorMessage(QString))); - connect(gatherer, SIGNAL(finished(int)), this, SIGNAL(finished(int))); - connect(gatherer, SIGNAL(progressMessage(QString)), this, SIGNAL(progressMessage(QString))); - connect(gatherer, SIGNAL(started()), this, SIGNAL(started())); + QTC_ASSERT(d->state != Inactive, return); + + emit errorMessage(tr("SSH connection failure: %1\n").arg(d->connection->errorString())); + setFinished(TestFailure); } -UsedPortsTester::~UsedPortsTester() +void GenericLinuxDeviceTester::handleProcessFinished(int exitStatus) { - delete gatherer; + QTC_ASSERT(d->state == RunningUname, return); + + if (exitStatus != SshRemoteProcess::ExitedNormally || d->process->exitCode() != 0) { + const QByteArray stderrOutput = d->process->readAllStandardError(); + if (!stderrOutput.isEmpty()) + emit errorMessage(tr("uname failed: %1\n").arg(QString::fromUtf8(stderrOutput))); + else + emit errorMessage(tr("uname failed.\n")); + } else { + emit progressMessage(QString::fromUtf8(d->process->readAllStandardOutput())); + } + + connect(&d->portsGatherer, SIGNAL(error(QString)), SLOT(handlePortsGatheringError(QString))); + connect(&d->portsGatherer, SIGNAL(portListReady()), SLOT(handlePortListReady())); + + emit progressMessage(tr("Checking if specified ports are available...")); + d->state = TestingPorts; + d->portsGatherer.start(d->connection, d->deviceConfiguration); } -QString UsedPortsTester::commandLine() const +void GenericLinuxDeviceTester::handlePortsGatheringError(const QString &message) { - return gatherer->commandLine(); + QTC_ASSERT(d->state == TestingPorts, return); + + emit errorMessage(tr("Error gathering ports: %1\n").arg(message)); + setFinished(TestFailure); } -void UsedPortsTester::run() +void GenericLinuxDeviceTester::handlePortListReady() { - gatherer->run(); + QTC_ASSERT(d->state == TestingPorts, return); + + if (d->portsGatherer.usedPorts().isEmpty()) { + emit progressMessage("All specified ports are available.\n"); + } else { + QString portList; + foreach (const int port, d->portsGatherer.usedPorts()) + portList += QString::number(port) + QLatin1String(", "); + portList.remove(portList.count() - 2, 2); + emit errorMessage(tr("The following specified ports are currently in use: %1\n") + .arg(portList)); + } + setFinished(TestSuccess); } -void UsedPortsTester::cancel() +void GenericLinuxDeviceTester::setFinished(TestResult result) { - gatherer->cancel(); + d->state = Inactive; + disconnect(d->connection.data(), 0, this, 0); + disconnect(&d->portsGatherer, 0, this, 0); + emit finished(result); } } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h index 7c1df21eae..1a469af806 100644 --- a/src/plugins/remotelinux/linuxdevicetester.h +++ b/src/plugins/remotelinux/linuxdevicetester.h @@ -34,79 +34,65 @@ #include "remotelinux_export.h" -#include "simplerunner.h" - -#include <utils/ssh/sshconnection.h> - #include <QtCore/QObject> #include <QtCore/QSharedPointer> QT_FORWARD_DECLARE_CLASS(QString) +namespace Utils { +class SshConnection; +} + namespace RemoteLinux { class LinuxDeviceConfiguration; -class RemoteLinuxUsedPortsGatherer; namespace Internal { -class LinuxDeviceTesterPrivate; +class GenericLinuxDeviceTesterPrivate; } // namespace Internal -// ----------------------------------------------------------------------- -// LinuxDeviceTester: -// ----------------------------------------------------------------------- - -class REMOTELINUX_EXPORT LinuxDeviceTester : public SimpleRunner +class REMOTELINUX_EXPORT AbstractLinuxDeviceTester : public QObject { Q_OBJECT - + Q_DISABLE_COPY(AbstractLinuxDeviceTester) public: - enum TestResult { TestSuccess = 0, TestFailure, TestCriticalFailure }; + enum TestResult { TestSuccess, TestFailure }; - LinuxDeviceTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &headline, const QString &commandline); - ~LinuxDeviceTester(); + virtual void testDevice(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) = 0; + virtual void stopTest() = 0; - virtual QString headLine() const; +signals: + void progressMessage(const QString &message); + void errorMessage(const QString &message); + void finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result); protected: - int processFinished(int exitStatus); - -private: - Internal::LinuxDeviceTesterPrivate *const d; + explicit AbstractLinuxDeviceTester(QObject *parent = 0); }; -class REMOTELINUX_EXPORT AuthenticationTester : public LinuxDeviceTester -{ - Q_OBJECT - -public: - AuthenticationTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); - -protected slots: - void handleStdOutput(const QByteArray &data); - -protected: - int processFinished(int exitStatus); - -private: - bool m_authenticationSucceded; -}; -class REMOTELINUX_EXPORT UsedPortsTester : public LinuxDeviceTester +class REMOTELINUX_EXPORT GenericLinuxDeviceTester : public AbstractLinuxDeviceTester { Q_OBJECT - public: - UsedPortsTester(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); - ~UsedPortsTester(); + explicit GenericLinuxDeviceTester(QObject *parent = 0); + ~GenericLinuxDeviceTester(); - QString commandLine() const; + void testDevice(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); + void stopTest(); - void run(); - void cancel(); + QSharedPointer<Utils::SshConnection> connection() const; + +private slots: + void handleConnected(); + void handleConnectionFailure(); + void handleProcessFinished(int exitStatus); + void handlePortsGatheringError(const QString &message); + void handlePortListReady(); private: - RemoteLinuxUsedPortsGatherer *const gatherer; + void setFinished(TestResult result); + + Internal::GenericLinuxDeviceTesterPrivate * const d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro index 8852d46111..00990e0252 100644 --- a/src/plugins/remotelinux/remotelinux.pro +++ b/src/plugins/remotelinux/remotelinux.pro @@ -9,7 +9,6 @@ HEADERS += \ embeddedlinuxtargetfactory.h \ embeddedlinuxqtversion.h \ embeddedlinuxqtversionfactory.h \ - simplerunner.h \ remotelinuxplugin.h \ remotelinux_export.h \ linuxdeviceconfiguration.h \ @@ -69,7 +68,6 @@ SOURCES += \ embeddedlinuxtargetfactory.cpp \ embeddedlinuxqtversion.cpp \ embeddedlinuxqtversionfactory.cpp \ - simplerunner.cpp \ remotelinuxplugin.cpp \ linuxdeviceconfiguration.cpp \ linuxdeviceconfigurations.cpp \ diff --git a/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp b/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp index d9a77c4e81..c38b29444d 100644 --- a/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp +++ b/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp @@ -62,8 +62,7 @@ class AbstractRemoteLinuxApplicationRunnerPrivate { public: AbstractRemoteLinuxApplicationRunnerPrivate(const RemoteLinuxRunConfiguration *runConfig) - : portsGatherer(runConfig->deviceConfig()), - devConfig(runConfig->deviceConfig()), + : devConfig(runConfig->deviceConfig()), remoteExecutable(runConfig->remoteExecutableFilePath()), appArguments(runConfig->arguments()), commandPrefix(runConfig->commandPrefix()), @@ -168,7 +167,7 @@ void AbstractRemoteLinuxApplicationRunner::stop() emit remoteProcessFinished(InvalidExitCode); break; case GatheringPorts: - d->portsGatherer.cancel(); + d->portsGatherer.stop(); setInactive(); emit remoteProcessFinished(InvalidExitCode); break; @@ -308,7 +307,7 @@ void AbstractRemoteLinuxApplicationRunner::handleRemoteProcessFinished(int exitS void AbstractRemoteLinuxApplicationRunner::setInactive() { - d->portsGatherer.cancel(); + d->portsGatherer.stop(); if (d->connection) { disconnect(d->connection.data(), 0, this, 0); SshConnectionManager::instance().releaseConnection(d->connection); @@ -423,7 +422,7 @@ void AbstractRemoteLinuxApplicationRunner::handleInitialCleanupDone(bool success } d->state = GatheringPorts; - d->portsGatherer.run(); + d->portsGatherer.start(d->connection, d->devConfig); } void AbstractRemoteLinuxApplicationRunner::handleInitializationsDone(bool success) diff --git a/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp b/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp index e0d201ddde..a239edfae0 100644 --- a/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp +++ b/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp @@ -33,7 +33,6 @@ #include "linuxdeviceconfiguration.h" #include "portlist.h" -#include <utils/ssh/sshconnectionmanager.h> #include <utils/ssh/sshremoteprocessrunner.h> #include <QtCore/QString> @@ -46,32 +45,23 @@ namespace Internal { class RemoteLinuxUsedPortsGathererPrivate { public: - RemoteLinuxUsedPortsGathererPrivate() - { } + RemoteLinuxUsedPortsGathererPrivate() : running(false) {} + SshRemoteProcessRunner procRunner; PortList portsToCheck; QList<int> usedPorts; - QByteArray keepSake; + QByteArray remoteStdout; + QByteArray remoteStderr; + bool running; // TODO: Redundant due to being in sync with procRunner? }; } // namespace Internal using namespace Internal; -RemoteLinuxUsedPortsGatherer::RemoteLinuxUsedPortsGatherer( - const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration) : - SimpleRunner(deviceConfiguration, - // Match - // 0: 0100007F:706E 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8141 1 ce498900 300 0 0 2 -1 - // and report ^^^^ this local port number - QLatin1String("FILE=/proc/net/tcp ; " - "echo \"$SSH_CONNECTION\" | grep : > /dev/null && FILE=/proc/net/tcp6 ; " - "sed 's/^\\s\\+[0-9a-fA-F]\\+:\\s\\+[0-9a-fA-F]\\+:\\([0-9a-fA-F]\\+\\)\\s.*$/\\1/' $FILE")), - d(new RemoteLinuxUsedPortsGathererPrivate) +RemoteLinuxUsedPortsGatherer::RemoteLinuxUsedPortsGatherer(QObject *parent) : + QObject(parent), d(new RemoteLinuxUsedPortsGathererPrivate) { - d->portsToCheck = deviceConfiguration->freePorts(); - - connect(this, SIGNAL(aboutToStart()), this, SLOT(cleanup())); } RemoteLinuxUsedPortsGatherer::~RemoteLinuxUsedPortsGatherer() @@ -79,6 +69,48 @@ RemoteLinuxUsedPortsGatherer::~RemoteLinuxUsedPortsGatherer() delete d; } +void RemoteLinuxUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connection, + const LinuxDeviceConfiguration::ConstPtr &devConf) +{ + if (d->running) + qWarning("Unexpected call of %s in running state", Q_FUNC_INFO); + d->portsToCheck = devConf->freePorts(); + d->usedPorts.clear(); + d->remoteStdout.clear(); + d->remoteStderr.clear(); + connect(&d->procRunner, SIGNAL(connectionError()), SLOT(handleConnectionError())); + connect(&d->procRunner, SIGNAL(processClosed(int)), SLOT(handleProcessClosed(int))); + connect(&d->procRunner, SIGNAL(processOutputAvailable(QByteArray)), + SLOT(handleRemoteStdOut(QByteArray))); + connect(&d->procRunner, SIGNAL(processErrorOutputAvailable(QByteArray)), + SLOT(handleRemoteStdErr(QByteArray))); + QString procFilePath; + int addressLength; + if (connection->ipProtocolVersion() == QAbstractSocket::IPv4Protocol) { + procFilePath = QLatin1String("/proc/net/tcp"); + addressLength = 8; + } else { + procFilePath = QLatin1String("/proc/net/tcp6"); + addressLength = 32; + } + const QString command = QString::fromLocal8Bit("sed " + "'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2") + .arg(addressLength).arg(procFilePath); + + // TODO: We should not use an SshRemoteProcessRunner here, because we have to check + // for the type of the connection before we can say what the exact command line is. + d->procRunner.run(command.toUtf8(), connection->connectionParameters()); + d->running = true; +} + +void RemoteLinuxUsedPortsGatherer::stop() +{ + if (!d->running) + return; + d->running = false; + disconnect(&d->procRunner, 0, this, 0); +} + int RemoteLinuxUsedPortsGatherer::getNextFreePort(PortList *freePorts) const { while (freePorts->hasMore()) { @@ -94,20 +126,12 @@ QList<int> RemoteLinuxUsedPortsGatherer::usedPorts() const return d->usedPorts; } -void RemoteLinuxUsedPortsGatherer::handleStdOutput(const QByteArray &output) +void RemoteLinuxUsedPortsGatherer::setupUsedPorts() { - QByteArray data = d->keepSake + output; - - // make sure we only process complete lines: - int lastEol = output.lastIndexOf('\n'); - if (lastEol != output.count() - 1) { - d->keepSake = data.mid(lastEol + 1); - data = data.left(lastEol); - } - - QList<QByteArray> portStrings = data.split('\n'); + QList<QByteArray> portStrings = d->remoteStdout.split('\n'); + portStrings.removeFirst(); foreach (const QByteArray &portString, portStrings) { - if (portString.isEmpty() || portString.contains("local_address")) + if (portString.isEmpty()) continue; bool ok; const int port = portString.toInt(&ok, 16); @@ -119,32 +143,61 @@ void RemoteLinuxUsedPortsGatherer::handleStdOutput(const QByteArray &output) Q_FUNC_INFO, portString.data()); } } + emit portListReady(); } -void RemoteLinuxUsedPortsGatherer::cleanup() +void RemoteLinuxUsedPortsGatherer::handleConnectionError() { - d->keepSake.clear(); - d->usedPorts.clear(); + if (!d->running) + return; + emit error(tr("Connection error: %1").arg(d->procRunner.lastConnectionErrorString())); + stop(); } -int RemoteLinuxUsedPortsGatherer::processFinished(int exitStatus) +void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus) { - if (!d->keepSake.isEmpty()) { - d->keepSake.append('\n'); - handleStdOutput(d->keepSake); + if (!d->running) + return; + QString errMsg; + switch (exitStatus) { + case SshRemoteProcess::FailedToStart: + errMsg = tr("Could not start remote process: %1") + .arg(d->procRunner.processErrorString()); + break; + case SshRemoteProcess::KilledBySignal: + errMsg = tr("Remote process crashed: %1") + .arg(d->procRunner.processErrorString()); + break; + case SshRemoteProcess::ExitedNormally: + if (d->procRunner.processExitCode() == 0) { + setupUsedPorts(); + } else { + errMsg = tr("Remote process failed; exit code was %1.") + .arg(d->procRunner.processExitCode()); + } + break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); } - if (usedPorts().isEmpty()) { - emit progressMessage("All specified ports are available.\n"); - } else { - QString portList; - foreach (const int port, usedPorts()) - portList += QString::number(port) + QLatin1String(", "); - portList.remove(portList.count() - 2, 2); - emit errorMessage(tr("The following specified ports are currently in use: %1\n") - .arg(portList)); + if (!errMsg.isEmpty()) { + if (!d->remoteStderr.isEmpty()) { + errMsg += tr("\nRemote error output was: %1") + .arg(QString::fromUtf8(d->remoteStderr)); + } + emit error(errMsg); } - return SimpleRunner::processFinished(exitStatus); + stop(); +} + +void RemoteLinuxUsedPortsGatherer::handleRemoteStdOut(const QByteArray &output) +{ + d->remoteStdout += output; +} + +void RemoteLinuxUsedPortsGatherer::handleRemoteStdErr(const QByteArray &output) +{ + d->remoteStderr += output; } } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinuxusedportsgatherer.h b/src/plugins/remotelinux/remotelinuxusedportsgatherer.h index dec6b00669..a5a51362af 100644 --- a/src/plugins/remotelinux/remotelinuxusedportsgatherer.h +++ b/src/plugins/remotelinux/remotelinuxusedportsgatherer.h @@ -33,9 +33,9 @@ #include "remotelinux_export.h" -#include "simplerunner.h" - #include <QtCore/QList> +#include <QtCore/QObject> +#include <QtCore/QSharedPointer> QT_FORWARD_DECLARE_CLASS(QString) @@ -51,28 +51,33 @@ namespace Internal { class RemoteLinuxUsedPortsGathererPrivate; } // namespace Internal -class REMOTELINUX_EXPORT RemoteLinuxUsedPortsGatherer : public SimpleRunner +class REMOTELINUX_EXPORT RemoteLinuxUsedPortsGatherer : public QObject { Q_OBJECT - + Q_DISABLE_COPY(RemoteLinuxUsedPortsGatherer) public: - explicit RemoteLinuxUsedPortsGatherer(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); + explicit RemoteLinuxUsedPortsGatherer(QObject *parent = 0); ~RemoteLinuxUsedPortsGatherer(); - + void start(const QSharedPointer<Utils::SshConnection> &connection, + const QSharedPointer<const LinuxDeviceConfiguration> &devConf); + void stop(); int getNextFreePort(PortList *freePorts) const; // returns -1 if no more are left QList<int> usedPorts() const; -protected slots: - void handleStdOutput(const QByteArray &output); - -protected: - int processFinished(int exitStatus); +signals: + void error(const QString &errMsg); + void portListReady(); private slots: - void cleanup(); + void handleConnectionError(); + void handleProcessClosed(int exitStatus); + void handleRemoteStdOut(const QByteArray &output); + void handleRemoteStdErr(const QByteArray &output); private: - Internal::RemoteLinuxUsedPortsGathererPrivate *const d; + void setupUsedPorts(); + + Internal::RemoteLinuxUsedPortsGathererPrivate * const d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/simplerunner.cpp b/src/plugins/remotelinux/simplerunner.cpp deleted file mode 100644 index cdebd869aa..0000000000 --- a/src/plugins/remotelinux/simplerunner.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "simplerunner.h" - -#include "linuxdeviceconfiguration.h" - -#include <utils/qtcassert.h> -#include <utils/ssh/sshremoteprocessrunner.h> -#include <utils/ssh/sshconnection.h> -#include <utils/ssh/sshconnectionmanager.h> - -using namespace Utils; - -namespace RemoteLinux { -namespace Internal { - -class SimpleRunnerPrivate -{ -public: - SimpleRunnerPrivate() : process(0), sshParameters(Utils::SshConnectionParameters::NoProxy) - { } - - QString commandline; - - SshRemoteProcessRunner *process; - Utils::SshConnectionParameters sshParameters; -}; - -} // namespace Internal - -using namespace Internal; - -SimpleRunner::SimpleRunner(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &commandline) : - d(new SimpleRunnerPrivate) -{ - QTC_ASSERT(!deviceConfiguration.isNull(), return); - d->commandline = commandline; - d->sshParameters = deviceConfiguration->sshParameters(); -} - -SimpleRunner::~SimpleRunner() -{ - delete d; -} - -QString SimpleRunner::commandLine() const -{ - return d->commandline; -} - -void SimpleRunner::run() -{ - QTC_ASSERT(!d->process, return); - - d->process = new SshRemoteProcessRunner(this); - - connect(d->process, SIGNAL(connectionError()), this, SLOT(handleConnectionFailure())); - connect(d->process, SIGNAL(processClosed(int)), this, SLOT(handleProcessFinished(int))); - connect(d->process, SIGNAL(processOutputAvailable(QByteArray)), this, SLOT(handleStdOutput(QByteArray))); - connect(d->process, SIGNAL(processErrorOutputAvailable(QByteArray)), - this, SLOT(handleStdError(QByteArray))); - - emit aboutToStart(); - d->process->run(d->commandline.toUtf8(), sshParameters()); - emit started(); -} - -void SimpleRunner::cancel() -{ - if (!d->process) - return; - - d->process->cancel(); - emit finished(-1); -} - -void SimpleRunner::handleConnectionFailure() -{ - QTC_ASSERT(d->process, return); - - emit errorMessage(tr("SSH connection failure: %1\n").arg(d->process->lastConnectionErrorString())); - delete d->process; - d->process = 0; - - emit finished(processFinished(SshRemoteProcess::FailedToStart)); -} - -void SimpleRunner::handleProcessFinished(int exitStatus) -{ - emit finished(processFinished(exitStatus)); -} - -void SimpleRunner::handleStdOutput(const QByteArray &data) -{ - if (data.isEmpty()) - return; - emit progressMessage(QString::fromUtf8(data)); -} - -void SimpleRunner::handleStdError(const QByteArray &data) -{ - if (data.isEmpty()) - return; - emit errorMessage(QString::fromUtf8(data)); -} - -int SimpleRunner::processFinished(int exitStatus) -{ - int exitCode = -1; - if (d->process) - exitCode = d->process->processExitCode(); - delete d->process; - d->process = 0; - - return (exitStatus == SshRemoteProcess::ExitedNormally && exitCode == 0) ? 0 : 1; -} - -void SimpleRunner::setCommandLine(const QString &cmd) -{ - QTC_ASSERT(d->commandline.isEmpty(), return); - d->commandline = cmd; -} - -SshConnectionParameters SimpleRunner::sshParameters() const -{ - return d->sshParameters; -} - -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/simplerunner.h b/src/plugins/remotelinux/simplerunner.h deleted file mode 100644 index 056d19268b..0000000000 --- a/src/plugins/remotelinux/simplerunner.h +++ /dev/null @@ -1,98 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef SIMPLERUNNER_H -#define SIMPLERUNNER_H - -#include "remotelinux_export.h" - -#include <utils/ssh/sshconnection.h> - -#include <QtCore/QObject> - -QT_FORWARD_DECLARE_CLASS(QString) - -namespace RemoteLinux { -class LinuxDeviceConfiguration; - -namespace Internal { -class SimpleRunnerPrivate; -} // namespace Internal - -// ----------------------------------------------------------------------- -// SimpleRunner: -// ----------------------------------------------------------------------- - -class REMOTELINUX_EXPORT SimpleRunner : public QObject -{ - Q_OBJECT - -public: - SimpleRunner(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, - const QString &commandline); - ~SimpleRunner(); - - virtual QString commandLine() const; - - virtual void run(); - virtual void cancel(); - -signals: - void aboutToStart(); - void started(); - void progressMessage(const QString &message); - void errorMessage(const QString &message); - // 0 on success, other value on failure. - void finished(int result); - -protected slots: - void handleProcessFinished(int exitStatus); - - virtual void handleConnectionFailure(); - virtual void handleStdOutput(const QByteArray &data); - virtual void handleStdError(const QByteArray &data); - - // 0 on success, any other value on failure. - virtual int processFinished(int exitStatus); - -protected: - void setCommandLine(const QString &cmd); - - Utils::SshConnectionParameters sshParameters() const; - -private: - Internal::SimpleRunnerPrivate *const d; -}; - -} // namespace RemoteLinux - -#endif // SIMPLERUNNER_H diff --git a/src/plugins/remotelinux/startgdbserverdialog.cpp b/src/plugins/remotelinux/startgdbserverdialog.cpp index 879815f72c..794fb6135f 100644 --- a/src/plugins/remotelinux/startgdbserverdialog.cpp +++ b/src/plugins/remotelinux/startgdbserverdialog.cpp @@ -103,14 +103,14 @@ public: QPushButton *closeButton; PathChooser *sysrootPathChooser; - RemoteLinuxUsedPortsGatherer *gatherer; + RemoteLinuxUsedPortsGatherer gatherer; SshRemoteProcessRunner runner; QSettings *settings; QString remoteCommandLine; }; StartGdbServerDialogPrivate::StartGdbServerDialogPrivate(StartGdbServerDialog *q) - : q(q), processList(0), gatherer(0), settings(0) + : q(q), processList(0) { settings = ICore::instance()->settings(); @@ -179,6 +179,8 @@ StartGdbServerDialog::StartGdbServerDialog(QWidget *parent) : d->deviceComboBox->setModel(devices); d->deviceComboBox->setCurrentIndex(d->settings->value(LastDevice).toInt()); + connect(&d->gatherer, SIGNAL(error(QString)), SLOT(portGathererError(QString))); + connect(&d->gatherer, SIGNAL(portListReady()), SLOT(portListReady())); if (devices->rowCount() == 0) { d->tableView->setEnabled(false); } else { @@ -213,15 +215,6 @@ StartGdbServerDialog::~StartGdbServerDialog() void StartGdbServerDialog::attachToDevice(int index) { LinuxDeviceConfigurations *devices = LinuxDeviceConfigurations::instance(); - - if (d->gatherer) - delete d->gatherer; - - d->gatherer = new RemoteLinuxUsedPortsGatherer(devices->deviceAt(index)); - connect(d->gatherer, SIGNAL(finished(RemoteLinux::LinuxDeviceTester::TestResult)), - this, SLOT(portListReady(RemoteLinux::LinuxDeviceTester::TestResult))); - connect(d->gatherer, SIGNAL(errorMessage(QString)), SLOT(portGathererError(QString))); - delete d->processList; d->processList = new GenericRemoteLinuxProcessList(devices->deviceAt(index)); d->proxyModel.setSourceModel(d->processList); @@ -257,8 +250,6 @@ void StartGdbServerDialog::updateProcessList() void StartGdbServerDialog::attachToProcess() { - QTC_ASSERT(d->gatherer, return); - const QModelIndexList &indexes = d->tableView->selectionModel()->selectedIndexes(); if (indexes.empty()) @@ -267,7 +258,7 @@ void StartGdbServerDialog::attachToProcess() LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); PortList ports = device->freePorts(); - const int port = d->gatherer->getNextFreePort(&ports); + const int port = d->gatherer.getNextFreePort(&ports); const int row = d->proxyModel.mapToSource(indexes.first()).row(); QTC_ASSERT(row >= 0, return); const int pid = d->processList->pidAt(row); @@ -321,11 +312,7 @@ void StartGdbServerDialog::portListReady() void StartGdbServerDialog::startGdbServer() { LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); - if (d->gatherer) - delete d->gatherer; - d->gatherer = new RemoteLinuxUsedPortsGatherer(device); - - d->gatherer->run(); + d->gatherer.start(SshConnection::create(device->sshParameters()), device); } void StartGdbServerDialog::attachToRemoteProcess() |