#include "maemotestcontrol.h" #include #include #include #include namespace Core { class SshConnection; class SshRemoteProcess; } // namespace Core using namespace Core; namespace Qt4Test { MaemoTestControl::MaemoTestControl( Core::SshConnectionParameters &sshParam ) : TestControl() { ssh_param = sshParam; control_mode = Idle; } MaemoTestControl::~MaemoTestControl() { } bool MaemoTestControl::deviceConfiguration( QString &reply ) { runBlockingCommand( ConfigCheck, "", 10000); reply = reply_txt; return reply_ok; } bool MaemoTestControl::runCustomCommand( const QString &cmd, int timeout, QString &reply ) { runBlockingCommand( CustomCommand, cmd, timeout); reply = reply_txt; return reply_ok; } bool MaemoTestControl::runCustomBlockingCommand( const QString &cmd, int timeout, QString &reply ) { runBlockingCommand( CustomBlockingCommand, cmd, timeout); reply = reply_txt; return reply_ok; } void MaemoTestControl::runBlockingCommand( MaemoTestControlMode mode, const QString &cmd, int timeout) { reply_txt = ""; reply_ok = true; m_cmd = cmd; control_mode = mode; if (initConnection()) waitForCommandToFinish(timeout); cleanupConnection(); } bool MaemoTestControl::startApplication( const QString &application, const QStringList &arguments, bool styleQtUITest, const QStringList &environment, QString &reply ) { Q_UNUSED(environment); Q_UNUSED(arguments); // for Maemo5 applications need to be run with run-standalone.sh // however for Maemo6 we still need to set the variables // in .profile eg DISPLAY=:0 QString cmd = QString("( " "if [ -x /usr/bin/run-standalone.sh ]; then " "%1 /usr/bin/run-standalone.sh %2 %3; " "else " ". $HOME/.profile; " "%1 %2 %3; " "fi )") .arg(environment.join(" ")) .arg(application) .arg(styleQtUITest?"-style qtuitest":""); runBlockingCommand( CustomCommand, cmd, 10000); reply = reply_txt; return reply_ok; } bool MaemoTestControl::killApplication( const QString &application, QString &reply ) { // if (m_testProcess) { // m_testProcess->kill(); // } return runCustomCommand( "killall " + application, 1000, reply); } void MaemoTestControl::waitForCommandToFinish(int timeout) { QTime t; t.start(); while (t.elapsed() < 10000 && control_mode != Idle) { qApp->processEvents(); } if (control_mode != Idle) { reply_ok = false; reply_txt += "Command timed out"; } } bool MaemoTestControl::initConnection() { if (m_testProcess) { reply_ok = false; reply_txt = "Process existed already"; return false; } reply_ok = true; m_deviceTestOutput = ""; m_connection = SshConnection::create(); connect(m_connection.data(), SIGNAL(connected()), this, SLOT(handleConnected())); connect(m_connection.data(), SIGNAL(error(SshError)), this, SLOT(handleConnectionError())); m_connection->connectToHost(ssh_param); return true; } void MaemoTestControl::handleConnected() { if (!m_connection) { reply_ok = false; reply_txt += "Invalid connection\n"; return; } if (control_mode == ConfigCheck) { QLatin1String sysInfoCmd("uname -rsm"); QLatin1String qtInfoCmd("dpkg -l |grep libqt " "|sed 's/[[:space:]][[:space:]]*/ /g' " "|cut -d ' ' -f 2,3 |sed 's/~.*//g'"); QString command(sysInfoCmd + " && " + qtInfoCmd); m_testProcess = m_connection->createRemoteProcess(command.toUtf8()); } else if (control_mode == CustomCommand || control_mode == CustomBlockingCommand) { m_testProcess = m_connection->createRemoteProcess(m_cmd.toUtf8()); } QObject::connect(m_testProcess.data(), SIGNAL(closed(int)), this, SLOT(handleProcessFinished(int)), Qt::DirectConnection); connect(m_testProcess.data(), SIGNAL(outputAvailable(QByteArray)), this, SLOT(processSshOutput(QByteArray)), Qt::DirectConnection); m_testProcess->start(); if (control_mode == CustomCommand) QTimer::singleShot(500,this,SLOT(cleanupConnection())); } void MaemoTestControl::handleConnectionError() { reply_ok = false; if (!m_connection) { reply_txt += "Invalid connection\n"; } else { reply_txt += tr("Could not connect to host: %1:%2 %3 %4\n%5\n") .arg(ssh_param.host) .arg(ssh_param.port) .arg(ssh_param.uname) .arg(ssh_param.pwd) .arg(m_connection->errorString()); } cleanupConnection(); } void MaemoTestControl::handleProcessFinished(int exitStatus) { Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart || exitStatus == SshRemoteProcess::KilledBySignal || exitStatus == SshRemoteProcess::ExitedNormally); if (!m_testProcess) { reply_ok = false; reply_txt += "Invalid process\n"; return; } if (exitStatus != SshRemoteProcess::ExitedNormally || m_testProcess->exitCode() != 0) { reply_ok = false; reply_txt += m_deviceTestOutput; reply_txt += tr("Remote process failed: %1\n") .arg(m_testProcess->errorString()); } else if (control_mode == ConfigCheck) { const QString &output = parseOutput(); if (!m_qtVersionOk) { reply_txt += tr("Qt version mismatch! " " Expected Qt on device: 4.6.2 or later.\n"); } reply_txt += output; } else if (control_mode == CustomCommand || control_mode == CustomBlockingCommand) { reply_txt += m_deviceTestOutput; } cleanupConnection(); } void MaemoTestControl::cleanupConnection() { if (m_testProcess) disconnect(m_testProcess.data(), 0, this, 0); if (m_connection) disconnect(m_connection.data(), 0, this, 0); control_mode = Idle; m_testProcess.clear(); m_connection.clear(); } void MaemoTestControl::processSshOutput(const QByteArray &output) { m_deviceTestOutput.append(QString::fromUtf8(output)); } QString MaemoTestControl::parseOutput() { if (control_mode == ConfigCheck) { m_qtVersionOk = false; QString output; const QRegExp unamePattern(QLatin1String("Linux (\\S+)\\s(\\S+)")); int index = unamePattern.indexIn(m_deviceTestOutput); if (index == -1) { output = tr("Device configuration test failed: Unexpected output:\n%1") .arg(m_deviceTestOutput); return output; } output = tr("Hardware architecture: %1\n").arg(unamePattern.cap(2)); output.append(tr("Kernel version: %1\n").arg(unamePattern.cap(1))); const QRegExp dkpgPattern(QLatin1String("libqt\\S+ (\\d)\\.(\\d)\\.(\\d)")); index = dkpgPattern.indexIn(m_deviceTestOutput); if (index == -1) { output.append(tr("No Qt packages installed.")); return output; } output.append(tr("List of installed Qt packages:") + QLatin1Char('\n')); do { output.append(QLatin1Char('\t') + dkpgPattern.cap(0) + QLatin1Char('\n')); index = dkpgPattern.indexIn(m_deviceTestOutput, index + 1); if (!m_qtVersionOk && QT_VERSION_CHECK(dkpgPattern.cap(1).toInt(), dkpgPattern.cap(2).toInt(), dkpgPattern.cap(3).toInt()) >= 0x040602) { m_qtVersionOk = true; } } while (index != -1); return output; } return ""; } }