summaryrefslogtreecommitdiffstats
path: root/src/qtestlib/wince
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit50123887ba0f33cf47520bee7c419d68742af2d1 (patch)
tree0eb8679b9e4e4370e59b44bfdcae616816e39aca /src/qtestlib/wince
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/qtestlib/wince')
-rw-r--r--src/qtestlib/wince/cetcpsync/cetcpsync.pro22
-rw-r--r--src/qtestlib/wince/cetcpsync/main.cpp191
-rw-r--r--src/qtestlib/wince/cetcpsync/qtcesterconnection.cpp552
-rw-r--r--src/qtestlib/wince/cetcpsync/qtcesterconnection.h86
-rw-r--r--src/qtestlib/wince/cetcpsync/remoteconnection.cpp65
-rw-r--r--src/qtestlib/wince/cetcpsync/remoteconnection.h81
-rw-r--r--src/qtestlib/wince/cetcpsyncserver/cetcpsyncserver.pro17
-rw-r--r--src/qtestlib/wince/cetcpsyncserver/commands.cpp686
-rw-r--r--src/qtestlib/wince/cetcpsyncserver/commands.h292
-rw-r--r--src/qtestlib/wince/cetcpsyncserver/connectionmanager.cpp138
-rw-r--r--src/qtestlib/wince/cetcpsyncserver/connectionmanager.h83
-rw-r--r--src/qtestlib/wince/cetcpsyncserver/main.cpp63
-rw-r--r--src/qtestlib/wince/cetcpsyncserver/transfer_global.h159
-rw-r--r--src/qtestlib/wince/cetest/activesyncconnection.cpp640
-rw-r--r--src/qtestlib/wince/cetest/activesyncconnection.h89
-rw-r--r--src/qtestlib/wince/cetest/bootstrapped.pri45
-rw-r--r--src/qtestlib/wince/cetest/cetcpsyncconnection.cpp221
-rw-r--r--src/qtestlib/wince/cetest/cetcpsyncconnection.h85
-rw-r--r--src/qtestlib/wince/cetest/cetest.pro56
-rw-r--r--src/qtestlib/wince/cetest/deployment.cpp293
-rw-r--r--src/qtestlib/wince/cetest/deployment.h75
-rw-r--r--src/qtestlib/wince/cetest/main.cpp445
-rw-r--r--src/qtestlib/wince/cetest/qmake_include.pri13
-rw-r--r--src/qtestlib/wince/cetest/remoteconnection.cpp100
-rw-r--r--src/qtestlib/wince/cetest/remoteconnection.h84
-rw-r--r--src/qtestlib/wince/remotelib/commands.cpp212
-rw-r--r--src/qtestlib/wince/remotelib/commands.h54
-rw-r--r--src/qtestlib/wince/remotelib/remotelib.pro15
-rw-r--r--src/qtestlib/wince/wince.pro2
29 files changed, 4864 insertions, 0 deletions
diff --git a/src/qtestlib/wince/cetcpsync/cetcpsync.pro b/src/qtestlib/wince/cetcpsync/cetcpsync.pro
new file mode 100644
index 000000000..d1d7c999a
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsync/cetcpsync.pro
@@ -0,0 +1,22 @@
+TARGET = cetcpsync
+DESTDIR = ../../../../bin
+CONFIG += console
+CONFIG -= app_bundle
+QT += network
+QT -= gui
+TEMPLATE = app
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+INCLUDEPATH += ../cetcpsyncserver
+
+SOURCES += main.cpp \
+ remoteconnection.cpp \
+ qtcesterconnection.cpp
+
+HEADERS += \
+ remoteconnection.h \
+ qtcesterconnection.h
diff --git a/src/qtestlib/wince/cetcpsync/main.cpp b/src/qtestlib/wince/cetcpsync/main.cpp
new file mode 100644
index 000000000..4d209e356
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsync/main.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <iostream>
+#include "qtcesterconnection.h"
+
+using namespace std;
+
+static void showUsage()
+{
+ cout << "cetcpsync is meant to be used by cetest internally." << endl
+ << "For usage instructions remoteconnection.h could be useful." << endl;
+}
+
+const int debugLevel = 0;
+void debugOutput(const QString& text, int level)
+{
+ if (level <= debugLevel)
+ cout << qPrintable(text) << endl;
+}
+
+class Exception
+{
+public:
+ Exception(const QString& msg = QString())
+ : m_message(msg)
+ {}
+
+ QString message() { return m_message; }
+
+protected:
+ QString m_message;
+};
+
+class TooFewParametersException : public Exception
+{
+public:
+ TooFewParametersException(const QLatin1String& cmd, int expectedParameterCount)
+ {
+ m_message = QLatin1String("Command ") + cmd + QLatin1String(" needs at least ");
+ m_message.append(QString::number(expectedParameterCount));
+ m_message.append(QLatin1String(" parameters."));
+ }
+};
+
+static void fileTimeFromString(FILETIME& ft, const QString& str)
+{
+ int idx = str.indexOf("*");
+ if (idx <= 0)
+ return;
+ ft.dwLowDateTime = str.left(idx).toULong();
+ ft.dwHighDateTime = str.mid(idx+1).toULong();
+}
+
+static QString fileTimeToString(FILETIME& ft)
+{
+ return QString::number(ft.dwLowDateTime) + "*" + QString::number(ft.dwHighDateTime);
+}
+
+static int execCommand(const QLatin1String& cmd, int argc, char* argv[])
+{
+ int retval = 0;
+ bool success = true;
+ QtCesterConnection connection;
+ if (cmd == "copyFileToDevice") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.copyFileToDevice(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "copyDirectoryToDevice") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.copyDirectoryToDevice(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "copyFileFromDevice") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.copyFileFromDevice(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "copyDirectoryFromDevice") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.copyDirectoryFromDevice(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "timeStampForLocalFileTime") {
+ if (argc < 1)
+ throw TooFewParametersException(cmd, 1);
+ FILETIME ft;
+ fileTimeFromString(ft, argv[0]);
+ success = connection.timeStampForLocalFileTime(&ft);
+ if (success)
+ cout << qPrintable(fileTimeToString(ft));
+ } else if (cmd == "fileCreationTime") {
+ if (argc < 1)
+ throw TooFewParametersException(cmd, 1);
+ FILETIME ft;
+ success = connection.fileCreationTime(argv[0], &ft);
+ if (success)
+ cout << qPrintable(fileTimeToString(ft));
+ } else if (cmd == "copyFile") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.copyFile(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "copyDirectory") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.copyDirectory(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "deleteFile") {
+ if (argc < 1)
+ throw TooFewParametersException(cmd, 1);
+ success = connection.deleteFile(argv[0]);
+ } else if (cmd == "deleteDirectory") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.deleteDirectory(argv[0], argv[1] == "true", argv[2] == "true");
+ } else if (cmd == "moveFile") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.moveFile(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "moveDirectory") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ success = connection.moveDirectory(argv[0], argv[1], argv[2] == "true");
+ } else if (cmd == "createDirectory") {
+ if (argc < 2)
+ throw TooFewParametersException(cmd, 2);
+ success = connection.createDirectory(argv[0], argv[1] == "true");
+ } else if (cmd == "execute") {
+ if (argc < 3)
+ throw TooFewParametersException(cmd, 3);
+ int timeout = QString(argv[2]).toInt();
+ success = connection.execute(argv[0], argv[1], timeout, &retval);
+ } else if (cmd == "noop") {
+ // do nothing :)
+ success = true;
+ } else {
+ throw Exception("unknown command");
+ }
+
+ return success ? retval : 1;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc <= 1) {
+ showUsage();
+ return 0;
+ }
+
+ QLatin1String param(argv[1]);
+ int result = 1;
+ try {
+ result = execCommand(param, argc - 2, argv + 2);
+ } catch (Exception e) {
+ cerr << "Error: " << qPrintable(e.message());
+ }
+ return result;
+}
diff --git a/src/qtestlib/wince/cetcpsync/qtcesterconnection.cpp b/src/qtestlib/wince/cetcpsync/qtcesterconnection.cpp
new file mode 100644
index 000000000..5d358e80b
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsync/qtcesterconnection.cpp
@@ -0,0 +1,552 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qtcesterconnection.h"
+#include <transfer_global.h>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtNetwork/QTcpSocket>
+#include <QtNetwork/QHostAddress>
+
+extern void debugOutput(const QString& text, int level);
+
+#pragma warning(disable:4996)
+
+#define END_ERROR(s, a) \
+ if(a) qDebug() << a; \
+ _freeSocket(s); \
+ return false;
+
+QtCesterConnection::QtCesterConnection()
+ : AbstractRemoteConnection()
+{
+}
+
+QtCesterConnection::~QtCesterConnection()
+{
+}
+
+bool QtCesterConnection::connect(QVariantList&)
+{
+ // We connect with each command, so this is always true
+ // The command itself will fail then
+ connected = true;
+ return true;
+}
+
+void QtCesterConnection::disconnect()
+{
+ connected = false;
+}
+
+bool QtCesterConnection::isConnected() const
+{
+ return connected;
+}
+
+bool QtCesterConnection::copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists)
+{
+ debugOutput( qPrintable(QString::fromLatin1("Copy File: %1 -> %2").arg(localSource).arg(deviceDest)),0);
+ QFile localFile(localSource);
+ QFileInfo info(localSource);
+ if (!localFile.exists() || !localFile.open(QIODevice::ReadOnly)) {
+ qDebug() << "Could not open File!";
+ return false;
+ }
+
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_CREATE_FILE)) {
+ END_ERROR(socket, "Could not initialized command");
+ }
+
+ CreateFileOptions option;
+ strcpy(option.fileName, qPrintable(deviceDest));
+#ifdef Q_OS_WIN
+ // Copy FileTime for update verification
+ FILETIME creationTime, accessTime, writeTime;
+ HANDLE localHandle = CreateFile(localSource.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (localHandle != INVALID_HANDLE_VALUE) {
+ if (GetFileTime(localHandle, &creationTime, &accessTime, &writeTime)) {
+ LocalFileTimeToFileTime(&writeTime, &writeTime);
+ option.fileTime = writeTime;
+ }
+ CloseHandle(localHandle);
+ }
+ DWORD attributes = GetFileAttributes(localSource.utf16());
+ if (attributes != -1 )
+ option.fileAttributes = attributes;
+#endif
+ option.fileSize = info.size();
+ option.overwriteExisting = !failIfExists;
+
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send options...");
+ }
+
+ if (!_checkResult(socket)) {
+ END_ERROR(socket, "Server did not accept configuration");
+ }
+
+ int bytesWritten = 0;
+ const int bufferSize = 1024;
+ QByteArray data;
+ while (bytesWritten < option.fileSize) {
+ data = localFile.read(bufferSize);
+ bytesWritten += data.size();
+#ifdef Q_OS_WIN
+ wprintf( L"%s -> %s (%d / %d) %d %%\r", localSource.utf16() , deviceDest.utf16(),
+ bytesWritten , option.fileSize, (100*bytesWritten)/option.fileSize );
+#endif
+ if (!_sendData(socket, data.constData(), data.size())) {
+ END_ERROR(socket, "Error during file transfer");
+ }
+ if (!_checkResult(socket)) {
+ END_ERROR(socket, "Got some strange result");
+ }
+ }
+#ifdef Q_OS_WIN
+ wprintf( L"\n"); // We should jump to next line...
+#endif
+ if (bytesWritten != option.fileSize) {
+ END_ERROR(socket, "Did not send sufficient data");
+ }
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive)
+{
+ QTcpSocket* socket = NULL;
+ QFileInfo info(localSource);
+ if (!info.exists() || !info.isDir()) {
+ END_ERROR(socket, "Input directory invalid");
+ }
+
+ createDirectory(deviceDest, true);
+ QDir dir(localSource);
+ QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach(QFileInfo item, list) {
+ QString targetName = deviceDest + QLatin1String("\\") + item.fileName();
+ if (item.isDir()) {
+ if (recursive) {
+ if (!copyDirectoryToDevice(item.absoluteFilePath() , targetName, recursive))
+ return false;
+ }
+ } else {
+ if (!copyFileToDevice(item.absoluteFilePath(), targetName))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool QtCesterConnection::copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists)
+{
+ QFile targetFile(localDest);
+ QTcpSocket* socket = 0;
+ if (targetFile.exists() && failIfExists) {
+ END_ERROR(socket, "Local file not supposed to be overwritten");
+ }
+
+ if (!targetFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ END_ERROR(socket, "Could not open local file for writing");
+ }
+
+ if (!_initCommand(socket, COMMAND_READ_FILE)) {
+ END_ERROR(socket, "Could not establish connection");
+ }
+
+ ReadFileOptions option;
+ strcpy(option.fileName, qPrintable(deviceSource));
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send options");
+ }
+
+ QByteArray data;
+ if (!_receiveData(socket, data)) {
+ END_ERROR(socket, "Did not receive any data");
+ }
+
+ ReadFileReply* reply = (ReadFileReply*) data.data();
+ if (!reply->fileValid) {
+ END_ERROR(socket, "Requested file invalid");
+ }
+
+ int fileSize = reply->fileSize;
+ int currentSize = 0;
+ // ### TODO: make a little bit more error-prone
+ do {
+ _sendData(socket, COMMAND_SUCCESS, strlen(COMMAND_SUCCESS));
+ _receiveData(socket, data);
+ currentSize += data.size();
+ targetFile.write(data);
+ } while(currentSize < fileSize);
+
+ _freeSocket(socket);
+ targetFile.close();
+ return true;
+}
+
+bool QtCesterConnection::copyDirectoryFromDevice(const QString& /*deviceSource*/
+ , const QString& /*localDest*/
+ , bool /*recursive*/)
+{
+ qDebug() << "To be implemented!! Should not be needed for autotest system";
+ exit(-1);
+ return false;
+}
+
+bool QtCesterConnection::copyFile(const QString &srcFile, const QString &destFile, bool failIfExists)
+{
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_COPY_FILE)) {
+ END_ERROR(socket, "Could not establish connection for copy");
+ }
+
+ CopyFileOptions option;
+ strcpy(option.from, qPrintable(srcFile));
+ strcpy(option.to, qPrintable(destFile));
+ option.overwriteExisting = !failIfExists;
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send copy options");
+ }
+
+ if (!_checkResult(socket)) {
+ END_ERROR(socket, "Copy failed");
+ }
+
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::copyDirectory(const QString &srcDirectory, const QString &destDirectory,
+ bool recursive)
+{
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_COPY_DIRECTORY)) {
+ END_ERROR(socket, "Could not establish connection for dir copy");
+ }
+
+ CopyDirectoryOptions option;
+ strcpy(option.from, qPrintable(srcDirectory));
+ strcpy(option.to, qPrintable(destDirectory));
+ option.recursive = recursive;
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send dir copy options");
+ }
+
+ if (!_checkResult(socket)) {
+ END_ERROR(socket, "Dir Copy failed");
+ }
+
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::deleteFile(const QString &fileName)
+{
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_DELETE_FILE)) {
+ END_ERROR(socket, "Could not establish connection for file deletion");
+ }
+
+ DeleteFileOptions option;
+ strcpy(option.fileName, qPrintable(fileName));
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send file options");
+ }
+
+ if (!_checkResult(socket)) {
+ //END_ERROR(socket, "File Deletion failed");
+ // This is actually not an error so ignore it.
+ }
+
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::deleteDirectory(const QString &directory, bool recursive, bool failIfContentExists)
+{
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_DELETE_DIRECTORY)) {
+ END_ERROR(socket, "Could not establish connection for dir deletion");
+ }
+
+ DeleteDirectoryOptions option;
+ strcpy(option.dirName, qPrintable(directory));
+ option.recursive = recursive;
+ option.failIfContentExists = failIfContentExists;
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send dir options");
+ }
+
+ if (!_checkResult(socket)) {
+ // we do not write an error as this will fail a lot on recursive.
+ END_ERROR(socket, 0);
+ }
+
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::execute(QString program,
+ QString arguments,
+ int timeout,
+ int *returnValue)
+{
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_EXECUTE)) {
+ END_ERROR(socket, "Could not establish connection for dir deletion");
+ }
+
+ ExecuteOptions options;
+ strcpy(options.appName, qPrintable(program));
+ QStringList argList = arguments.split(QLatin1Char(' '));
+ options.argumentsCount = qMin(argList.size(), MAX_ARGUMENTS);
+ options.waitForFinished = true;
+ options.timeout = timeout;
+ if (!_sendData(socket, (char*) &options, sizeof(options))) {
+ END_ERROR(socket, "Could not send dir options");
+ }
+ if (!_checkResult(socket)) {
+ END_ERROR(socket, "Did not receive an answer");
+ }
+
+ for (int i=0; i < options.argumentsCount; ++i) {
+ char someData[MAX_NAME_LENGTH];
+ strcpy(someData, qPrintable(argList[i]));
+ if (!_sendData(socket, someData, MAX_NAME_LENGTH)) {
+ END_ERROR(socket, "Could not send argument");
+ }
+ if (!_checkResult(socket)) {
+ END_ERROR(socket, "Failure in argument send");
+ }
+ }
+
+ // trigger the startup
+ if (!_sendData(socket, COMMAND_SUCCESS, strlen(COMMAND_SUCCESS))) {
+ END_ERROR(socket, "Could not trigger startup");
+ }
+
+ const int waitTime = 60 * 60 * 1000;
+ if (!socket->waitForReadyRead(waitTime)) {
+ END_ERROR(socket, "Process timed out");
+ }
+
+ QByteArray result = socket->readAll();
+ if (result != COMMAND_SUCCESS) {
+ if (returnValue)
+ *returnValue = -1; // just some at least
+ END_ERROR(socket, "Application did not start or returned error");
+ }
+
+ if (returnValue)
+ *returnValue = 0;
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::createDirectory(const QString &path, bool deleteBefore)
+{
+ if (deleteBefore)
+ deleteDirectory(path, true, true);
+
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_CREATE_DIRECTORY)) {
+ END_ERROR(socket, "Could not establish connection for dir creation");
+ }
+
+ CreateDirectoryOptions option;
+ strcpy(option.dirName, qPrintable(path));
+ option.recursively = true;
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send dir options");
+ }
+
+ if (!_checkResult(socket)) {
+ END_ERROR(socket, "Dir creation failed");
+ }
+
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::timeStampForLocalFileTime(FILETIME* fTime) const
+{
+ if (!fTime)
+ return false;
+
+ FILETIME copyTime = *fTime;
+ LocalFileTimeToFileTime(&copyTime, &copyTime);
+
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_TIME_STAMP)) {
+ END_ERROR(socket, "Could not establish time stamp connection");
+ }
+
+ if (!_sendData(socket, (char*) &copyTime, sizeof(copyTime))) {
+ END_ERROR(socket, "Could not send stamp time");
+ }
+
+ QByteArray data;
+ if (!_receiveData(socket, data)) {
+ END_ERROR(socket, "Did not receive time stamp or connection interrupted");
+ }
+
+ copyTime = *((FILETIME*)data.data());
+ if (copyTime.dwLowDateTime == -1 && copyTime.dwHighDateTime == -1) {
+ END_ERROR(socket, "remote Time stamp failed!");
+ }
+
+ *fTime = copyTime;
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::fileCreationTime(const QString &fileName, FILETIME* deviceCreationTime) const
+{
+ if (!deviceCreationTime)
+ return false;
+
+ QTcpSocket* socket = 0;
+ if (!_initCommand(socket, COMMAND_FILE_TIME)) {
+ END_ERROR(socket, "Could not establish connection for file time access");
+ }
+
+ FileTimeOptions option;
+ strcpy(option.fileName, qPrintable(fileName));
+ if (!_sendData(socket, (char*) &option, sizeof(option))) {
+ END_ERROR(socket, "Could not send file time name");
+ }
+
+ QByteArray data;
+ if (!_receiveData(socket, data)) {
+ END_ERROR(socket, "File Time request failed");
+ }
+
+ FILETIME* resultTime = (FILETIME*) data.data();
+ if (resultTime->dwLowDateTime == -1 && resultTime->dwHighDateTime == -1) {
+ END_ERROR(socket, 0);
+ debugOutput("Could not access file time", 0);
+ }
+
+ *deviceCreationTime = *resultTime;
+ _freeSocket(socket);
+ return true;
+}
+
+bool QtCesterConnection::_createSocket(QTcpSocket*& result) const
+{
+ QTcpSocket* sock = new QTcpSocket();
+ QByteArray ipAddress = qgetenv("DEVICE_IP");
+ if (ipAddress.isEmpty()) {
+ qWarning("Error: You need to have DEVICE_IP set");
+ exit(0);
+ }
+ sock->connectToHost(QHostAddress(QString(ipAddress)), 12145);
+
+ if (!sock->waitForConnected()) {
+ qDebug() << "connection timeout...";
+ result = NULL;
+ return false;
+ }
+ result = sock;
+ return true;
+}
+
+void QtCesterConnection::_freeSocket(QTcpSocket*& sock) const
+{
+ if (!sock)
+ return;
+ if (sock->state() == QAbstractSocket::ConnectedState) {
+ sock->disconnectFromHost();
+ // seems like no need to wait
+ //sock->waitForDisconnected();
+ }
+ delete sock;
+ sock = NULL;
+#ifdef Q_OS_WIN
+ Sleep(100);
+#endif
+}
+
+bool QtCesterConnection::_initCommand(QTcpSocket*& sock, const char* command) const
+{
+ QTcpSocket* socket = NULL;
+ if (!_createSocket(socket)) {
+ END_ERROR(socket, "Could not connect to server");
+ }
+
+ if (!_sendData(socket, command, strlen(command)) ||
+ !_checkResult(socket)) {
+ END_ERROR(socket, "Cound not send command");
+ }
+ sock = socket;
+ return true;
+}
+
+bool QtCesterConnection::_sendData(QTcpSocket*& sock, const char* data, int dataSize) const
+{
+ int amount = sock->write(data, dataSize);
+ if (amount != dataSize) {
+ fprintf(stderr, "*******COULD NOT SEND ENOUGH DATA*************\n");
+ }
+ return sock->waitForBytesWritten();
+}
+
+bool QtCesterConnection::_receiveData(QTcpSocket*& sock, QByteArray& data) const
+{
+ if (!sock->waitForReadyRead()) {
+ qDebug() << "did not receive any data";
+ return false;
+ }
+ data = sock->readAll();
+ return true;
+}
+
+bool QtCesterConnection::_checkResult(QTcpSocket*& sock) const
+{
+ QByteArray response;
+ if (!_receiveData(sock, response) || response != COMMAND_SUCCESS)
+ return false;
+ return true;
+}
+
diff --git a/src/qtestlib/wince/cetcpsync/qtcesterconnection.h b/src/qtestlib/wince/cetcpsync/qtcesterconnection.h
new file mode 100644
index 000000000..c33935d90
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsync/qtcesterconnection.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef ACTIVESYNC_REMOTECONNECTION_H
+#define ACTIVESYNC_REMOTECONNECTION_H
+
+#include "remoteconnection.h"
+
+class QTcpSocket;
+
+class QtCesterConnection : public AbstractRemoteConnection
+{
+public:
+ QtCesterConnection();
+ virtual ~QtCesterConnection();
+
+ bool connect(QVariantList &list = QVariantList());
+ void disconnect();
+ bool isConnected() const;
+
+ // These functions are designed for transfer between desktop and device
+ // Caution: deviceDest path has to be device specific (eg. no drive letters for CE)
+ bool copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists = false);
+ bool copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive = true);
+ bool copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists = false);
+ bool copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive = true);
+
+ bool timeStampForLocalFileTime(FILETIME*) const;
+ bool fileCreationTime(const QString &fileName, FILETIME*) const;
+
+ // These functions only work on files existing on the device
+ bool copyFile(const QString&, const QString&, bool failIfExists = false);
+ bool copyDirectory(const QString&, const QString&, bool recursive = true);
+ bool deleteFile(const QString&);
+ bool deleteDirectory(const QString&, bool recursive = true, bool failIfContentExists = false);
+ bool createDirectory(const QString&, bool deleteBefore=false);
+
+ bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL);
+private:
+ bool _createSocket(QTcpSocket*&) const;
+ void _freeSocket(QTcpSocket*&) const;
+ bool _initCommand(QTcpSocket*&, const char*) const;
+ bool _sendData(QTcpSocket*&, const char* data, int dataSize) const;
+ bool _receiveData(QTcpSocket*&, QByteArray&) const;
+ bool _checkResult(QTcpSocket*&) const;
+ bool connected;
+};
+
+#endif
diff --git a/src/qtestlib/wince/cetcpsync/remoteconnection.cpp b/src/qtestlib/wince/cetcpsync/remoteconnection.cpp
new file mode 100644
index 000000000..01a37201e
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsync/remoteconnection.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "remoteconnection.h"
+
+AbstractRemoteConnection::AbstractRemoteConnection()
+{
+}
+
+AbstractRemoteConnection::~AbstractRemoteConnection()
+{
+}
+
+// Slow but should be ok...
+bool AbstractRemoteConnection::moveFile(const QString &src, const QString &dest, bool FailIfExists)
+{
+ bool result = copyFile(src, dest, FailIfExists);
+ deleteFile(src);
+ return result;
+}
+
+// Slow but should be ok...
+bool AbstractRemoteConnection::moveDirectory(const QString &src, const QString &dest, bool recursive)
+{
+ bool result = copyDirectory(src, dest, true);
+ deleteDirectory(src, recursive);
+ return result;
+}
diff --git a/src/qtestlib/wince/cetcpsync/remoteconnection.h b/src/qtestlib/wince/cetcpsync/remoteconnection.h
new file mode 100644
index 000000000..bf0fcce17
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsync/remoteconnection.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef REMOTECONNECTION_H
+#define REMOTECONNECTION_H
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <windows.h>
+class AbstractRemoteConnection
+{
+public:
+ AbstractRemoteConnection();
+ virtual ~AbstractRemoteConnection();
+
+ virtual bool connect(QVariantList&) = 0;
+ virtual void disconnect() = 0;
+ virtual bool isConnected() const = 0;
+
+ // These functions are designed for transfer between desktop and device
+ // Caution: deviceDest path has to be device specific (eg. no drive letters for CE)
+ virtual bool copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists = false) = 0;
+ virtual bool copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive = true) = 0;
+ virtual bool copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists = false) = 0;
+ virtual bool copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive = true) = 0;
+
+ // For "intelligent deployment" we need to investigate on filetimes on the device
+ virtual bool timeStampForLocalFileTime(FILETIME*) const = 0;
+ virtual bool fileCreationTime(const QString &fileName, FILETIME*) const = 0;
+
+ // These functions only work on files existing on the device
+ virtual bool copyFile(const QString&, const QString&, bool failIfExists = false) = 0;
+ virtual bool copyDirectory(const QString&, const QString&, bool recursive = true) = 0;
+ virtual bool deleteFile(const QString&) = 0;
+ virtual bool deleteDirectory(const QString&, bool recursive = true, bool failIfContentExists = false) = 0;
+ bool moveFile(const QString&, const QString&, bool FailIfExists = false);
+ bool moveDirectory(const QString&, const QString&, bool recursive = true);
+
+ virtual bool createDirectory(const QString&, bool deleteBefore=false) = 0;
+
+ virtual bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL) = 0;
+};
+
+#endif
diff --git a/src/qtestlib/wince/cetcpsyncserver/cetcpsyncserver.pro b/src/qtestlib/wince/cetcpsyncserver/cetcpsyncserver.pro
new file mode 100644
index 000000000..bd01d2dab
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsyncserver/cetcpsyncserver.pro
@@ -0,0 +1,17 @@
+TEMPLATE = app
+TARGET = cetcpsyncsvr
+DEPENDPATH += .
+QT -= gui
+QT += network
+
+CONFIG += console
+
+HEADERS += \
+ connectionmanager.h \
+ commands.h \
+ transfer_global.h
+
+SOURCES += \
+ connectionmanager.cpp \
+ commands.cpp \
+ main.cpp
diff --git a/src/qtestlib/wince/cetcpsyncserver/commands.cpp b/src/qtestlib/wince/cetcpsyncserver/commands.cpp
new file mode 100644
index 000000000..aaf5431d5
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsyncserver/commands.cpp
@@ -0,0 +1,686 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "commands.h"
+#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QProcess>
+
+#ifdef Q_OS_WINCE
+#include <windows.h>
+#endif
+
+/////////////////////////////////////////////////////
+// Abstract Command Implementation //
+/////////////////////////////////////////////////////
+AbstractCommand::AbstractCommand()
+: m_socket(0)
+{
+}
+
+AbstractCommand::~AbstractCommand()
+{
+}
+
+void AbstractCommand::reportSuccess()
+{
+ m_socket->write(COMMAND_SUCCESS, strlen(COMMAND_SUCCESS));
+ m_socket->waitForBytesWritten();
+}
+
+void AbstractCommand::reportError()
+{
+ m_socket->write(COMMAND_ERROR, strlen(COMMAND_ERROR));
+ m_socket->waitForBytesWritten();
+}
+
+void AbstractCommand::dataReceived(QByteArray&)
+{
+ debugOutput(1, "AbstractCommand::dataReceived NOT SUPPOSED TO BE HERE");
+}
+
+void AbstractCommand::commandFinished()
+{
+ debugOutput(1, "AbstractCommand::commandFinished()NOT SUPPOSED TO BE HERE");
+}
+
+void AbstractCommand::setSocket(QTcpSocket* socket)
+{
+ debugOutput(0, "AbstractCommand::setSocket()");
+ Q_ASSERT(socket);
+ m_socket = socket;
+ connect(m_socket, SIGNAL(readyRead()), this, SLOT(_readData()));
+ reportSuccess();
+}
+
+QTcpSocket* AbstractCommand::socket()
+{
+ return m_socket;
+}
+
+void AbstractCommand::_readData()
+{
+ QByteArray arr = m_socket->readAll();
+ dataReceived(arr);
+}
+
+void AbstractCommand::_disconnect()
+{
+}
+
+/////////////////////////////////////////////////////
+// Create File Command Implementation //
+/////////////////////////////////////////////////////
+CreateFileCommand::CreateFileCommand()
+: m_dataCount(0)
+{
+ debugOutput(0, "CreateFileCommand::CreateFileCommand");
+ m_options.fileSize= -1;
+}
+
+CreateFileCommand::~CreateFileCommand()
+{
+ debugOutput(0, "CreateFileCommand::~CreateFileCommand");
+ if (m_file.isOpen()) {
+ fprintf(stderr, "****************FILE IS STILL OPENED AND HAVENT FINISHED WRITING**********************\n");
+ fprintf(stderr, "Current: %d Expected: %d\n", m_dataCount , m_options.fileSize);
+ m_file.close();
+ }
+}
+
+void CreateFileCommand::dataReceived(QByteArray &data)
+{
+ bool successful = true;
+ // If we haven't received the options yet
+ if (m_options.fileSize == -1) {
+ CreateFileOptions* opt = (CreateFileOptions*) data.data();
+ memcpy(&m_options , opt , sizeof(CreateFileOptions));
+
+ if (QFileInfo(QString::fromLatin1(m_options.fileName)).exists()) {
+ if (m_options.overwriteExisting) {
+#ifdef Q_OS_WINCE
+ SetFileAttributes(QFileInfo(m_options.fileName).absoluteFilePath().utf16(), FILE_ATTRIBUTE_NORMAL);
+#endif
+ QFile::remove(m_options.fileName);
+ } else
+ successful = false;
+ }
+ m_file.setFileName(QString::fromLatin1(m_options.fileName));
+ if (!m_file.open(QIODevice::WriteOnly))
+ successful = false;
+ else
+ debugOutput(3, QString::fromLatin1("Creating file: %1").arg(m_options.fileName));
+ } else { // write buffer on disc
+ if (!m_file.isOpen())
+ return;
+ m_file.write(data);
+ m_dataCount += data.size();
+ if (m_dataCount >= m_options.fileSize) {
+ // We do not care about more data than announced
+ m_file.close();
+ }
+ }
+
+ if (successful)
+ reportSuccess();
+ else
+ reportError();
+}
+
+void CreateFileCommand::commandFinished()
+{
+ debugOutput(0, "CreateFileCommand::commandFinished");
+#ifdef Q_OS_WIN
+ // We need to set the file attributes for intelligent time comparisons
+ QString tmpFile = QString::fromLatin1(m_options.fileName);
+ HANDLE handle = CreateFile(tmpFile.utf16(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (handle != INVALID_HANDLE_VALUE) {
+ SetFileTime(handle, &(m_options.fileTime), NULL, NULL);
+ CloseHandle(handle);
+ }
+ SetFileAttributes(tmpFile.utf16(), m_options.fileAttributes);
+#endif
+}
+
+/////////////////////////////////////////////////////
+// Create Directory Command Implementation //
+/////////////////////////////////////////////////////
+CreateDirectoryCommand::CreateDirectoryCommand()
+ : AbstractCommand()
+{
+ debugOutput(0, "CreateDirectoryCommand::CreateDirectoryCommand");
+}
+
+CreateDirectoryCommand::~CreateDirectoryCommand()
+{
+ debugOutput(0, "CreateDirectoryCommand::~CreateDirectoryCommand()");
+}
+
+void CreateDirectoryCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "CreateDirectoryCommand::dataReceived()");
+ CreateDirectoryOptions* options = (CreateDirectoryOptions*) data.data();
+ debugOutput(3, QString::fromLatin1("Creating directory: %1").arg(options->dirName));
+ bool success = true;
+ QDir dir;
+ if (options->recursively)
+ success = dir.mkpath(options->dirName);
+ else
+ success = dir.mkdir(options->dirName);
+
+ if (success)
+ reportSuccess();
+ else
+ reportError();
+}
+
+void CreateDirectoryCommand::commandFinished()
+{
+ debugOutput(0, "CreateDirectoryCommand::commandFinished()");
+}
+
+/////////////////////////////////////////////////////
+// Copy File Command Implementation //
+/////////////////////////////////////////////////////
+CopyFileCommand::CopyFileCommand()
+ : AbstractCommand()
+{
+ debugOutput(0, "CopyFileCommand::CopyFileCommand()");
+}
+
+CopyFileCommand::~CopyFileCommand()
+{
+ debugOutput(0, "CopyFileCommand::~CopyFileCommand()");
+}
+
+void CopyFileCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "CopyFileCommand::dataReceived()");
+ CopyFileOptions* options = (CopyFileOptions*) data.data();
+ debugOutput(3, QString::fromLatin1("Copy File: %1 -> %2").arg(options->from).arg(options->to));
+ bool success = true;
+ if (QFileInfo(options->to).exists()) {
+ if (options->overwriteExisting)
+ QFile::remove(options->to);
+ else
+ success = false;
+ }
+ if (success)
+ if (!QFile::copy(options->from , options->to))
+ success = false;
+
+ if (success)
+ reportSuccess();
+ else
+ reportError();
+}
+
+void CopyFileCommand::commandFinished()
+{
+ debugOutput(0, "CopyFileCommand::commandFinished()");
+}
+
+/////////////////////////////////////////////////////
+// Copy Directory Command Implementation //
+/////////////////////////////////////////////////////
+CopyDirectoryCommand::CopyDirectoryCommand()
+ : AbstractCommand()
+{
+ debugOutput(0, "CopyDirectoryCommand::CopyDirectoryCommand()");
+}
+
+CopyDirectoryCommand::~CopyDirectoryCommand()
+{
+ debugOutput(0, "CopyDirectoryCommand::~CopyDirectoryCommand()");
+}
+
+void CopyDirectoryCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "CopyDirectoryCommand::dataReceived()");
+ CopyDirectoryOptions* options = (CopyDirectoryOptions*) data.data();
+ debugOutput(3, QString::fromLatin1("Copy Directory: %1 %2").arg(options->from).arg(options->to));
+ if (copyDir(QLatin1String(options->from) , QLatin1String(options->to) , options->recursive))
+ reportSuccess();
+ else
+ reportError();
+}
+
+void CopyDirectoryCommand::commandFinished()
+{
+ debugOutput(0, "CopyDirectoryCommand::commandFinished()");
+}
+
+bool CopyDirectoryCommand::copyDir(const QString &from, const QString &to, bool recursive)
+{
+ QDir().mkpath(to);
+ QDir sourceDir(from);
+ QDir destDir(to);
+ QStringList entries = sourceDir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
+ foreach (QString item , entries) {
+ QString itemFrom = sourceDir.absoluteFilePath(item);
+ QString itemTo = destDir.absoluteFilePath(item);
+ if (QFileInfo(item).isDir()) {
+ if (recursive && !copyDir(itemFrom, itemTo, recursive))
+ return false;
+ } else {
+ if (!QFile::copy(itemFrom, itemTo))
+ return false;
+ }
+ }
+ return true;
+}
+
+/////////////////////////////////////////////////////
+// Delete File Command Implementation //
+/////////////////////////////////////////////////////
+DeleteFileCommand::DeleteFileCommand()
+ : AbstractCommand()
+{
+ debugOutput(0, "DeleteFileCommand::DeleteFileCommand()");
+}
+
+DeleteFileCommand::~DeleteFileCommand()
+{
+ debugOutput(0, "DeleteFileCommand::~DeleteFileCommand()");
+}
+
+void DeleteFileCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "DeleteFileCommand::dataReceived()");
+ DeleteFileOptions* options = (DeleteFileOptions*) data.data();
+ debugOutput(3, QString::fromLatin1("Delete File: %1").arg(options->fileName));
+ bool success = true;
+ QFile file(options->fileName);
+ if (file.exists()) {
+#ifdef Q_OS_WINCE
+ SetFileAttributes(QFileInfo(options->fileName).absoluteFilePath().utf16(), FILE_ATTRIBUTE_NORMAL);
+#endif
+ success = file.remove();
+ } else
+ success = false;
+
+ if (success)
+ reportSuccess();
+ else
+ reportError();
+}
+
+void DeleteFileCommand::commandFinished()
+{
+ debugOutput(0, "DeleteFileCommand::commandFinished()");
+}
+
+/////////////////////////////////////////////////////
+// Delete Directory Command Implementation //
+/////////////////////////////////////////////////////
+DeleteDirectoryCommand::DeleteDirectoryCommand()
+ : AbstractCommand()
+{
+ debugOutput(0, "DeleteDirectoryCommand::DeleteDirectoryCommand()");
+}
+
+DeleteDirectoryCommand::~DeleteDirectoryCommand()
+{
+ debugOutput(0, "DeleteDirectoryCommand::~DeleteDirectoryCommand()");
+}
+
+void DeleteDirectoryCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "DeleteDirectoryCommand::dataReceived()");
+ DeleteDirectoryOptions* options = (DeleteDirectoryOptions*) data.data();
+ debugOutput(3, QString::fromLatin1("Delete directory: %1").arg(options->dirName));
+ if (deleteDirectory(QLatin1String(options->dirName), options->recursive, options->failIfContentExists))
+ reportSuccess();
+ else
+ reportError();
+}
+
+void DeleteDirectoryCommand::commandFinished()
+{
+ debugOutput(0, "DeleteDirectoryCommand::commandFinished()");
+}
+
+bool DeleteDirectoryCommand::deleteDirectory(const QString &dirName, bool recursive, bool failIfContentExists)
+{
+ QDir dir(dirName);
+ if (!dir.exists())
+ return false;
+
+ QStringList itemList = dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ if (itemList.size() > 0 && failIfContentExists)
+ return false;
+
+ foreach (QString item, itemList) {
+ QString itemName = dir.absoluteFilePath(item);
+ if (QFileInfo(itemName).isDir()) {
+ if (recursive && !deleteDirectory(itemName, recursive, failIfContentExists))
+ return false;
+ } else {
+ if (!dir.remove(item))
+ return false;
+ }
+ }
+ QString lastName = dir.dirName();
+ dir.cdUp();
+ dir.rmpath(lastName);
+ return true;
+}
+
+/////////////////////////////////////////////////////
+// Execute Command Implementation //
+/////////////////////////////////////////////////////
+ExecuteCommand::ExecuteCommand()
+ : AbstractCommand()
+ , m_argumentCount(0)
+ , m_timeout(-1)
+{
+ debugOutput(0, "ExecuteCommand::ExecuteCommand()");
+}
+
+ExecuteCommand::~ExecuteCommand()
+{
+ debugOutput(0, "ExecuteCommand::~ExecuteCommand()");
+}
+
+void ExecuteCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "ExecuteCommand::dataReceived()");
+
+ if (m_argumentCount == 0) {
+ ExecuteOptions* options = (ExecuteOptions*) data.data();
+ if (!QFileInfo(options->appName).exists()) {
+ debugOutput(1, "Error execute: application does not exist");
+ reportError();
+ return;
+ }
+
+ m_program = QLatin1String(options->appName);
+ m_argumentCount = options->argumentsCount;
+ m_waitFinished = options->waitForFinished;
+ m_timeout = options->timeout;
+ if (m_argumentCount == 0)
+ m_argumentCount = -1; // to trigger startup on next receive
+ reportSuccess();
+ } else if (m_arguments.size() < m_argumentCount) {
+ m_arguments += data;
+ reportSuccess();
+ } else { // do the execution
+ if (data == COMMAND_SUCCESS)
+ _doExecute();
+ }
+}
+
+void ExecuteCommand::_doExecute()
+{
+ debugOutput(0, "ExecuteCommand::_doExecute()");
+ debugOutput(3, QString::fromLatin1("Execute: %1 %2").arg(m_program).arg(m_arguments.join(" ")));
+ if (m_waitFinished) {
+ QProcess process;
+ process.start(m_program, m_arguments);
+ if (process.waitForFinished(m_timeout) == false || process.exitCode() < 0)
+ reportError();
+ else
+ reportSuccess();
+ } else {
+ if (QProcess::startDetached(m_program, m_arguments))
+ reportSuccess();
+ else
+ reportError();
+ }
+}
+void ExecuteCommand::commandFinished()
+{
+ debugOutput(0,"ExecuteCommand::commandFinished()");
+}
+
+/////////////////////////////////////////////////////
+// Read File Implementation //
+/////////////////////////////////////////////////////
+ReadFileCommand::ReadFileCommand()
+ : AbstractCommand()
+ , m_currentPos(0)
+{
+ debugOutput(0, "ReadFileCommand::ReadFileCommand()");
+ m_fileName.clear();
+}
+
+ReadFileCommand::~ReadFileCommand()
+{
+ debugOutput(0, "ReadFileCommand::~ReadFileCommand()");
+ if (m_file.isOpen())
+ m_file.close();
+}
+
+void ReadFileCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "ReadFileCommand::dataReceived()");
+ if (m_fileName.isEmpty()) {
+ ReadFileOptions* option = (ReadFileOptions*) data.data();
+ m_fileName = QLatin1String(option->fileName);
+ QFileInfo info(m_fileName);
+ m_file.setFileName(m_fileName);
+ ReadFileReply reply;
+ if (!info.exists() || !info.isFile() || !m_file.open(QIODevice::ReadOnly))
+ reply.fileValid = false;
+ else
+ reply.fileValid = true;
+ reply.fileSize = info.size();
+ m_fileSize = reply.fileSize;
+ socket()->write((char*) &reply, sizeof(reply));
+ debugOutput(3, QString::fromLatin1("Reading file: %1").arg(m_fileName));
+ } else {
+ QTcpSocket* sock = socket(); // design failure???
+ if (data != COMMAND_SUCCESS || m_currentPos >= m_fileSize) {
+ sock->disconnectFromHost();
+ return;
+ }
+ const int bufferSize = 1024;
+ QByteArray buffer = m_file.read(bufferSize);
+ m_currentPos += buffer.size();
+ sock->write(buffer);
+ sock->waitForBytesWritten();
+ }
+}
+
+void ReadFileCommand::commandFinished()
+{
+ debugOutput(0, "ReadFileCommand::commandFinished()");
+}
+
+/////////////////////////////////////////////////////
+// Read Directory Implementation //
+/////////////////////////////////////////////////////
+ReadDirectoryCommand::ReadDirectoryCommand()
+ : AbstractCommand()
+ , m_iterator(0)
+{
+ debugOutput(0, "ReadDirectoryCommand::ReadDirectoryCommand");
+ m_dirName.clear();
+}
+
+ReadDirectoryCommand::~ReadDirectoryCommand()
+{
+ debugOutput(0, "ReadDirectoryCommand::~ReadDirectoryCommand()");
+ delete m_iterator;
+}
+
+void ReadDirectoryCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "ReadDirectoryCommand::dataReceived()");
+ QTcpSocket* sock = socket();
+ if (m_dirName.isEmpty()) {
+ ReadDirectoryOptions* option = (ReadDirectoryOptions*) data.data();
+ QFileInfo info(QLatin1String(option->dirName));
+ debugOutput(3, QString::fromLatin1("Reading Directory entries: %1").arg(option->dirName));
+ ReadDirectoryReply reply;
+ if (!info.exists() || !info.isDir()) {
+ reply.itemCount = -1;
+ reply.entryValid = false;
+ } else {
+ m_dirName = QLatin1String(option->dirName);
+ m_dir.setPath(m_dirName);
+ m_iterator = new QDirIterator(m_dir);
+ reply.itemCount = m_dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot).size();
+ reply.entryValid = true;
+ }
+ sock->write((char*) &reply, sizeof(reply));
+ sock->waitForBytesWritten();
+ } else {
+ if (data != COMMAND_SUCCESS) {
+ qDebug() << "Something went wrong in the meantime";
+ return;
+ }
+ ReadDirectoryItem reply;
+ if (m_iterator->hasNext()) {
+ m_iterator->next();
+ QFileInfo info = m_iterator->fileInfo();
+ strcpy(reply.name, qPrintable(info.absoluteFilePath()));
+ reply.isDirectory = info.isDir();
+ if (!reply.isDirectory)
+ reply.size = info.size();
+ }
+ reply.hasMore = m_iterator->hasNext();
+ sock->write((char*) &reply, sizeof(reply));
+ sock->waitForBytesWritten();
+ }
+}
+
+void ReadDirectoryCommand::commandFinished()
+{
+ debugOutput(0, "ReadDirectoryCommand::commandFinished()");
+}
+
+/////////////////////////////////////////////////////
+// File Time Implementation //
+/////////////////////////////////////////////////////
+FileTimeCommand::FileTimeCommand()
+ : AbstractCommand()
+{
+ debugOutput(0, "FileTimeCommand::FileTimeCommand()");
+}
+
+FileTimeCommand::~FileTimeCommand()
+{
+ debugOutput(0, "FileTimeCommand::~FileTimeCommand()");
+}
+
+void FileTimeCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "FileTimeCommand::dataReceived()");
+ FileTimeOptions* option = (FileTimeOptions*) data.data();
+
+ FILETIME resultTime;
+ resultTime.dwLowDateTime = -1;
+ resultTime.dwHighDateTime = -1;
+
+#ifdef Q_OS_WIN
+ QString fileName = QLatin1String(option->fileName);
+ HANDLE deviceHandle = CreateFile(fileName.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ debugOutput(3, QString::fromLatin1("Asking FileTime: %1").arg(fileName));
+ if (deviceHandle != INVALID_HANDLE_VALUE) {
+ FILETIME deviceCreationTime;
+ if (GetFileTime(deviceHandle, &deviceCreationTime, NULL, NULL)) {
+ resultTime = deviceCreationTime;
+ }
+ CloseHandle(deviceHandle);
+ }
+#endif
+ QTcpSocket* sock = socket();
+ sock->write((char*) &resultTime, sizeof(resultTime));
+ sock->waitForBytesWritten();
+}
+
+void FileTimeCommand::commandFinished()
+{
+ debugOutput(0, "FileTimeCommand::commandFinished()");
+}
+
+/////////////////////////////////////////////////////
+// Time Stamp Implementation //
+/////////////////////////////////////////////////////
+TimeStampCommand::TimeStampCommand()
+ : AbstractCommand()
+{
+ debugOutput(0, "TimeStampCommand::TimeStampCommand()");
+}
+
+TimeStampCommand::~TimeStampCommand()
+{
+ debugOutput(0, "TimeStampCommand::~TimeStampCommand()");
+}
+
+void TimeStampCommand::dataReceived(QByteArray &data)
+{
+ debugOutput(0, "TimeStampCommand::dataReceived()");
+ FILETIME resultTime;
+ resultTime.dwLowDateTime = -1;
+ resultTime.dwHighDateTime = -1;
+
+#ifdef Q_OS_WIN
+ FILETIME stampTime = *((FILETIME*)data.data());
+
+ QString tmpFile = QString::fromLatin1("\\qt_tmp_ftime_convert");
+ HANDLE remoteHandle = CreateFile(tmpFile.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (remoteHandle != INVALID_HANDLE_VALUE) {
+ if (!SetFileTime(remoteHandle, &stampTime, NULL, NULL)) {
+ CloseHandle(remoteHandle);
+ } else {
+ CloseHandle(remoteHandle);
+ remoteHandle = CreateFile(tmpFile.utf16(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (remoteHandle != INVALID_HANDLE_VALUE) {
+ if (GetFileTime(remoteHandle, &stampTime, NULL, NULL))
+ resultTime = stampTime;
+ CloseHandle(remoteHandle);
+ DeleteFile(tmpFile.utf16());
+ }
+ }
+ }
+ debugOutput(3, QString::fromLatin1("Asking TimeStamp"));
+#endif
+ QTcpSocket* sock = socket();
+ sock->write((char*) &resultTime, sizeof(resultTime));
+ sock->waitForBytesWritten();
+}
+
+void TimeStampCommand::commandFinished()
+{
+ debugOutput(0, "TimeStampCommand::commandFinished()");
+}
diff --git a/src/qtestlib/wince/cetcpsyncserver/commands.h b/src/qtestlib/wince/cetcpsyncserver/commands.h
new file mode 100644
index 000000000..b880dcd1d
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsyncserver/commands.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef COMMANDS_INCL
+#define COMMANDS_INCL
+
+#include "transfer_global.h"
+
+#include <QtNetwork/QTcpSocket>
+#include <QtCore/QString>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
+#include <windows.h>
+
+// debug output
+#define DEBUG_LEVEL 2
+inline void debugOutput(int level, const char* text)
+{
+ if (level >= DEBUG_LEVEL)
+ qDebug() << text;
+}
+
+inline void debugOutput(int level, const QString &text)
+{
+ if (level >= DEBUG_LEVEL)
+ qDebug() << text;
+}
+// Basic abtract command class
+class AbstractCommand : public QObject
+{
+ Q_OBJECT
+public:
+ AbstractCommand();
+ virtual ~AbstractCommand();
+
+ void setSocket(QTcpSocket*);
+ QTcpSocket* socket();
+
+ void reportSuccess();
+ void reportError();
+
+public slots:
+ virtual void dataReceived(QByteArray&);
+ virtual void commandFinished();
+
+private slots:
+ void _readData();
+ void _disconnect();
+
+private:
+ QTcpSocket* m_socket;
+};
+
+// File Creation class
+class CreateFileCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ CreateFileCommand();
+ ~CreateFileCommand();
+
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+
+private:
+ CreateFileOptions m_options;
+ QFile m_file;
+ int m_dataCount;
+};
+
+inline AbstractCommand* instCreateFile() { return new CreateFileCommand(); }
+
+// Directory Creation class
+class CreateDirectoryCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ CreateDirectoryCommand();
+ ~CreateDirectoryCommand();
+
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+};
+inline AbstractCommand* instCreateDirectory() { return new CreateDirectoryCommand(); }
+
+// File copy class
+class CopyFileCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ CopyFileCommand();
+ ~CopyFileCommand();
+
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+};
+inline AbstractCommand* instCopyFile() { return new CopyFileCommand(); }
+
+// Copy directory class
+class CopyDirectoryCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ CopyDirectoryCommand();
+ ~CopyDirectoryCommand();
+
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+private:
+ bool copyDir(const QString &from, const QString &to, bool recursive);
+};
+inline AbstractCommand* instCopyDirectory() { return new CopyDirectoryCommand(); }
+
+// Delete File class
+class DeleteFileCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ DeleteFileCommand();
+ ~DeleteFileCommand();
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+};
+inline AbstractCommand* instDeleteFile() { return new DeleteFileCommand(); }
+
+// Delete Directory class
+class DeleteDirectoryCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ DeleteDirectoryCommand();
+ ~DeleteDirectoryCommand();
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+private:
+ bool deleteDirectory(const QString &dirName, bool recursive, bool failIfContentExists);
+};
+inline AbstractCommand* instDeleteDirectory() { return new DeleteDirectoryCommand(); }
+
+// Execute application class
+class ExecuteCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ ExecuteCommand();
+ ~ExecuteCommand();
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+private:
+ void _doExecute();
+ QString m_program;
+ QStringList m_arguments;
+ int m_argumentCount;
+ bool m_waitFinished;
+ int m_timeout;
+};
+inline AbstractCommand* instExecution() { return new ExecuteCommand(); }
+
+// Read File class
+class ReadFileCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ ReadFileCommand();
+ ~ReadFileCommand();
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+private:
+ QString m_fileName;
+ QFile m_file;
+ qint64 m_currentPos;
+ qint64 m_fileSize;
+};
+inline AbstractCommand* instReadFile() { return new ReadFileCommand(); }
+
+// Read Directory class
+class ReadDirectoryCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ ReadDirectoryCommand();
+ ~ReadDirectoryCommand();
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+private:
+ QString m_dirName;
+ QDir m_dir;
+ QDirIterator* m_iterator;
+};
+inline AbstractCommand* instReadDirectory() { return new ReadDirectoryCommand(); }
+
+// Read File Time class
+class FileTimeCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ FileTimeCommand();
+ ~FileTimeCommand();
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+};
+inline AbstractCommand* instFileTime() { return new FileTimeCommand(); }
+
+// Time stamp class
+class TimeStampCommand : public AbstractCommand
+{
+ Q_OBJECT
+public:
+ TimeStampCommand();
+ ~TimeStampCommand();
+public slots:
+ void dataReceived(QByteArray&);
+ void commandFinished();
+};
+inline AbstractCommand* instTimeStamp() { return new TimeStampCommand(); }
+
+// Access part
+typedef AbstractCommand* (*instantiator)();
+
+struct CommandInfo
+{
+ CommandInfo(const QString &name, instantiator func) : commandName(name) , commandFunc(func) { }
+ QString commandName;
+ instantiator commandFunc;
+};
+
+inline QList<CommandInfo> availableCommands()
+{
+ QList<CommandInfo> list;
+ list.append(CommandInfo(QLatin1String(COMMAND_CREATE_FILE), instCreateFile));
+ list.append(CommandInfo(QLatin1String(COMMAND_CREATE_DIRECTORY), instCreateDirectory));
+ list.append(CommandInfo(QLatin1String(COMMAND_COPY_FILE), instCopyFile));
+ list.append(CommandInfo(QLatin1String(COMMAND_COPY_DIRECTORY), instCopyDirectory));
+ list.append(CommandInfo(QLatin1String(COMMAND_DELETE_FILE), instDeleteFile));
+ list.append(CommandInfo(QLatin1String(COMMAND_DELETE_DIRECTORY), instDeleteDirectory));
+ list.append(CommandInfo(QLatin1String(COMMAND_EXECUTE), instExecution));
+ list.append(CommandInfo(QLatin1String(COMMAND_READ_FILE), instReadFile));
+ list.append(CommandInfo(QLatin1String(COMMAND_READ_DIRECTORY), instReadDirectory));
+ list.append(CommandInfo(QLatin1String(COMMAND_FILE_TIME), instFileTime));
+ list.append(CommandInfo(QLatin1String(COMMAND_TIME_STAMP), instTimeStamp));
+ return list;
+}
+
+#endif
diff --git a/src/qtestlib/wince/cetcpsyncserver/connectionmanager.cpp b/src/qtestlib/wince/cetcpsyncserver/connectionmanager.cpp
new file mode 100644
index 000000000..1d5600d1b
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsyncserver/connectionmanager.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "connectionmanager.h"
+#include "commands.h"
+#include <QtCore/QDebug>
+
+ConnectionManager::ConnectionManager()
+ : QObject()
+ , m_server(0)
+{
+ debugOutput(0, "ConnectionManager::ConnectionManager()");
+}
+
+ConnectionManager::~ConnectionManager()
+{
+ debugOutput(0, "ConnectionManager::~ConnectionManager()");
+ cleanUp();
+}
+
+bool ConnectionManager::init()
+{
+ debugOutput(0, "ConnectionManager::init()");
+ debugOutput(3, "Initializing server...");
+ cleanUp();
+ m_server = new QTcpServer(this);
+ connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+ bool result = m_server->listen(QHostAddress::Any, SERVER_PORT);
+ if (!result)
+ debugOutput(3, QString::fromLatin1(" Error: Server start failed:") + m_server->errorString());
+ debugOutput(3, " Waiting for action");
+ return result;
+}
+
+void ConnectionManager::cleanUp()
+{
+ debugOutput(0, "ConnectionManager::cleanUp()");
+
+ if (m_server) {
+ debugOutput(1, "Removing server instance...");
+ disconnect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+ delete m_server;
+ m_server = 0;
+ }
+}
+
+void ConnectionManager::newConnection()
+{
+ debugOutput(0, "ConnectionManager::newConnection()");
+
+ QTcpSocket* connection = m_server->nextPendingConnection();
+ if (!connection) {
+ debugOutput(3, "Received connection has empty socket");
+ return;
+ }
+ debugOutput(0, QString::fromLatin1(" received a connection: %1").arg((int) connection));
+ new Connection(connection);
+}
+
+Connection::Connection(QTcpSocket *socket)
+ : QObject()
+ , m_connection(socket)
+ , m_command(0)
+{
+ connect(m_connection, SIGNAL(readyRead()), this, SLOT(receiveCommand()));
+ connect(m_connection, SIGNAL(disconnected()), this, SLOT(closedConnection()));
+}
+
+Connection::~Connection()
+{
+ if (m_command) {
+ m_command->commandFinished();
+ delete m_command;
+ m_command = 0;
+ }
+ delete m_connection;
+}
+
+void Connection::receiveCommand()
+{
+ QByteArray arr = m_connection->readAll();
+ debugOutput(1, QString::fromLatin1("Command received: ") + (arr));
+ QList<CommandInfo> commands = availableCommands();
+ for(QList<CommandInfo>::iterator it = commands.begin(); it != commands.end(); ++it) {
+ if (it->commandName == QString::fromLatin1(arr)) {
+ debugOutput(1, "Found command in list");
+ disconnect(m_connection, SIGNAL(readyRead()), this, SLOT(receiveCommand()));
+ AbstractCommand* command = (*it).commandFunc();
+ command->setSocket(m_connection);
+ m_command = command;
+ return;
+ }
+ }
+ debugOutput(2, QString::fromLatin1("Unknown command received: ") + (arr));
+}
+
+void Connection::closedConnection()
+{
+ debugOutput(0, "connection being closed...");
+ this->deleteLater();
+}
diff --git a/src/qtestlib/wince/cetcpsyncserver/connectionmanager.h b/src/qtestlib/wince/cetcpsyncserver/connectionmanager.h
new file mode 100644
index 000000000..e9f725cc8
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsyncserver/connectionmanager.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef CONNECTION_MANAGER_INCL
+#define CONNECTION_MANAGER_INCL
+
+#include "transfer_global.h"
+#include "commands.h"
+
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QTcpSocket>
+
+class Connection : public QObject
+{
+ Q_OBJECT
+public:
+ Connection(QTcpSocket* socket);
+ ~Connection();
+
+public slots:
+ void receiveCommand();
+ void closedConnection();
+
+private:
+ QTcpSocket* m_connection;
+ AbstractCommand* m_command;
+};
+
+class ConnectionManager : public QObject
+{
+ Q_OBJECT
+public:
+ ConnectionManager();
+ ~ConnectionManager();
+
+ bool init();
+
+public slots:
+ void cleanUp();
+ void newConnection();
+
+private:
+ QTcpServer* m_server;
+};
+
+#endif
diff --git a/src/qtestlib/wince/cetcpsyncserver/main.cpp b/src/qtestlib/wince/cetcpsyncserver/main.cpp
new file mode 100644
index 000000000..eccd86839
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsyncserver/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "connectionmanager.h"
+
+#include <QtCore>
+#include <QtNetwork>
+
+void messageOutput(QtMsgType type, const char *msg)
+{
+ switch(type) {
+ case QtDebugMsg: fprintf(stderr, "Debug: %s\n", msg); break;
+ case QtWarningMsg: fprintf(stderr, "Warning: %s\n", msg); break;
+ default: fprintf(stderr, "Some Msg: %s\n", msg); break;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ qInstallMsgHandler(messageOutput);
+
+ QCoreApplication app(argc, argv);
+ ConnectionManager manager;
+ manager.init();
+ return app.exec();
+}
diff --git a/src/qtestlib/wince/cetcpsyncserver/transfer_global.h b/src/qtestlib/wince/cetcpsyncserver/transfer_global.h
new file mode 100644
index 000000000..a2c029753
--- /dev/null
+++ b/src/qtestlib/wince/cetcpsyncserver/transfer_global.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TRANSFER_GLOBAL_H
+#define TRANSFER_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+#ifdef Q_OS_WIN
+#include <windows.h>
+#endif
+
+#define SERVER_PORT 12145
+
+#define MAX_NAME_LENGTH 512
+#define MAX_ARGUMENTS 10
+
+// Defines for commands sent/received
+#define COMMAND_CREATE_FILE "CREATEFILE"
+#define COMMAND_CREATE_DIRECTORY "CREATEDIR"
+#define COMMAND_COPY_FILE "COPYFILE"
+#define COMMAND_COPY_DIRECTORY "COPYDIR"
+#define COMMAND_DELETE_FILE "DELETEFILE"
+#define COMMAND_DELETE_DIRECTORY "DELETEDIR"
+#define COMMAND_EXECUTE "EXECUTE"
+#define COMMAND_QUIT_SERVER "QUIT"
+#define COMMAND_FILE_TIME "FILETIME"
+#define COMMAND_TIME_STAMP "TIMESTAMP"
+
+// Report back commands
+#define COMMAND_SUCCESS "SUCCESS"
+#define COMMAND_ERROR "ERROR"
+
+// Defines for commands that send data back to requester
+#define COMMAND_READ_FILE "READFILE"
+#define COMMAND_READ_DIRECTORY "READDIR"
+
+#include <QtCore/qglobal.h>
+// Option-Structures for commands
+
+struct CreateFileOptions
+{
+ char fileName[MAX_NAME_LENGTH];
+#ifdef Q_OS_WIN
+ FILETIME fileTime;
+ DWORD fileAttributes;
+#endif
+ int fileSize;
+ bool overwriteExisting;
+};
+
+struct CreateDirectoryOptions
+{
+ char dirName[MAX_NAME_LENGTH];
+ bool recursively; // in case of \foo\bar create \foo if it does not exist
+};
+
+struct CopyFileOptions
+{
+ char from[MAX_NAME_LENGTH];
+ char to[MAX_NAME_LENGTH];
+ bool overwriteExisting;
+};
+
+struct CopyDirectoryOptions
+{
+ char from[MAX_NAME_LENGTH];
+ char to[MAX_NAME_LENGTH];
+ bool recursive;
+};
+
+struct DeleteFileOptions
+{
+ char fileName[MAX_NAME_LENGTH];
+};
+
+struct DeleteDirectoryOptions
+{
+ char dirName[MAX_NAME_LENGTH];
+ bool recursive;
+ bool failIfContentExists;
+};
+
+struct ExecuteOptions
+{
+ char appName[MAX_NAME_LENGTH];
+ int argumentsCount;
+ bool waitForFinished;
+ int timeout;
+};
+
+struct ReadFileOptions
+{
+ char fileName[MAX_NAME_LENGTH];
+};
+
+struct ReadFileReply
+{
+ qint64 fileSize;
+ bool fileValid;
+};
+
+struct ReadDirectoryOptions
+{
+ char dirName[MAX_NAME_LENGTH];
+};
+
+struct ReadDirectoryItem
+{
+ char name[MAX_NAME_LENGTH];
+ qint64 size;
+ bool isDirectory;
+ bool hasMore;
+};
+
+#define FileTimeOptions ReadFileOptions
+
+struct ReadDirectoryReply
+{
+ bool entryValid;
+ int itemCount; // might change during iteration
+};
+#endif
diff --git a/src/qtestlib/wince/cetest/activesyncconnection.cpp b/src/qtestlib/wince/cetest/activesyncconnection.cpp
new file mode 100644
index 000000000..c336c273b
--- /dev/null
+++ b/src/qtestlib/wince/cetest/activesyncconnection.cpp
@@ -0,0 +1,640 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "activesyncconnection.h"
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo>
+#include <rapi.h>
+
+extern void debugOutput(const QString& text, int level);
+
+ActiveSyncConnection::ActiveSyncConnection()
+ : AbstractRemoteConnection()
+ , connected(false)
+{
+}
+
+ActiveSyncConnection::~ActiveSyncConnection()
+{
+ if (isConnected())
+ disconnect();
+}
+
+bool ActiveSyncConnection::connect(QVariantList&)
+{
+ if (connected)
+ return true;
+ connected = false;
+ RAPIINIT init;
+ init.cbSize = sizeof(init);
+ if (CeRapiInitEx(&init) != S_OK)
+ return connected;
+
+ DWORD res;
+ res = WaitForMultipleObjects(1,&(init.heRapiInit),true, 5000);
+ if ((res == -1) || (res == WAIT_TIMEOUT) || (init.hrRapiInit != S_OK))
+ return connected;
+
+ connected = true;
+ return connected;
+}
+
+void ActiveSyncConnection::disconnect()
+{
+ connected = false;
+ CeRapiUninit();
+}
+
+bool ActiveSyncConnection::isConnected() const
+{
+ return connected;
+}
+
+bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists)
+{
+ if (failIfExists) {
+ CE_FIND_DATA search;
+ HANDLE searchHandle = CeFindFirstFile(deviceDest.utf16(), &search);
+ if (searchHandle != INVALID_HANDLE_VALUE) {
+ CeFindClose(searchHandle);
+ return false;
+ }
+ }
+
+ QFile file(localSource);
+ if (!file.exists())
+ return false;
+ if (!file.open(QIODevice::ReadOnly)) {
+ debugOutput(QString::fromLatin1(" Could not open source file"),2);
+ if (file.size() == 0) {
+ // Create an empy file
+ deleteFile(deviceDest);
+ HANDLE deviceHandle = CeCreateFile(deviceDest.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (deviceHandle != INVALID_HANDLE_VALUE) {
+ CeCloseHandle(deviceHandle);
+ return true;
+ }
+ } else {
+ qWarning("Could not open %s: %s", qPrintable(localSource), qPrintable(file.errorString()));
+ }
+ return false;
+ }
+
+ deleteFile(deviceDest);
+ HANDLE deviceHandle = CeCreateFile(deviceDest.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (deviceHandle == INVALID_HANDLE_VALUE) {
+ qWarning("Could not create %s: %s", qPrintable(deviceDest), strwinerror(CeGetLastError()).constData());
+ return false;
+ }
+
+ DWORD written = 0;
+ int currentPos = 0;
+ int size = file.size();
+ DWORD toWrite = 0;
+ const int bufferSize = 65000;
+ QByteArray data;
+ data.reserve(bufferSize);
+ while (currentPos < size) {
+ data = file.read(bufferSize);
+ if (data.size() <= 0) {
+ wprintf( L"Error while reading file!\n");
+ return false;
+ }
+ if (size - currentPos > bufferSize )
+ toWrite = bufferSize;
+ else
+ toWrite = size - currentPos;
+ if (toWrite == 0)
+ break;
+ if (!CeWriteFile(deviceHandle, data.data() , toWrite, &written, NULL)) {
+ qWarning("Could not write to %s: %s", qPrintable(deviceDest), strwinerror(CeGetLastError()).constData());
+ return false;
+ }
+ currentPos += written;
+ data.clear();
+ wprintf( L"%s -> %s (%d / %d) %d %%\r", localSource.utf16() , deviceDest.utf16(), currentPos , size, (100*currentPos)/size );
+ }
+ wprintf(L"\n");
+
+ // Copy FileTime for update verification
+ FILETIME creationTime, accessTime, writeTime;
+ HANDLE localHandle = CreateFile(localSource.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (localHandle != INVALID_HANDLE_VALUE) {
+ if (GetFileTime(localHandle, &creationTime, &accessTime, &writeTime)) {
+ LocalFileTimeToFileTime(&writeTime, &writeTime);
+ if (!CeSetFileTime(deviceHandle, &writeTime, NULL, NULL)) {
+ debugOutput(QString::fromLatin1(" Could not write time values"), 0);
+ }
+ }
+ CloseHandle(localHandle);
+ }
+ CeCloseHandle(deviceHandle);
+
+ DWORD attributes = GetFileAttributes(localSource.utf16());
+ if (attributes != -1 )
+ CeSetFileAttributes(deviceDest.utf16(), attributes);
+ return true;
+}
+
+bool ActiveSyncConnection::copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive)
+{
+ QDir dir(localSource);
+ if (!dir.exists())
+ return false;
+
+ deleteDirectory(deviceDest, recursive);
+ CeCreateDirectory(deviceDest.utf16(), NULL);
+ foreach(QString entry, dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot)) {
+ QString source = localSource + "\\" + entry;
+ QString target = deviceDest + "\\" + entry;
+ QFileInfo info(source);
+ if (info.isDir()) {
+ if (recursive) {
+ if (!copyDirectoryToDevice(source, target, recursive))
+ return false;
+ }
+ } else {
+ if (!copyFileToDevice(source, target))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ActiveSyncConnection::copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists)
+{
+ QFile target(localDest);
+ if (failIfExists && target.exists()) {
+ debugOutput(QString::fromLatin1(" Not allowed to overwrite file"), 2);
+ return false;
+ }
+
+ if (target.exists())
+ target.remove();
+
+ HANDLE deviceHandle = CeCreateFile(deviceSource.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (deviceHandle == INVALID_HANDLE_VALUE) {
+ debugOutput(QString::fromLatin1(" Could not open file on device"), 2);
+ return false;
+ }
+
+ DWORD fileSize = CeGetFileSize( deviceHandle, NULL );
+ if (fileSize == -1) {
+ debugOutput(QString::fromLatin1(" Could not stat filesize of remote file"), 2);
+ CeCloseHandle(deviceHandle);
+ return false;
+ }
+
+ if (!target.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ debugOutput(QString::fromLatin1(" Could not open local file for writing"), 2);
+ CeCloseHandle(deviceHandle);
+ return false;
+ }
+
+ int bufferSize = 65000;
+ char *buffer = (char*) malloc(bufferSize);
+ DWORD bufferRead = 0;
+ DWORD bufferWritten = 0;
+ bool readUntilEnd = false;
+ while(CeReadFile(deviceHandle, buffer, bufferSize, &bufferRead, NULL)) {
+ if (bufferRead == 0) {
+ readUntilEnd = true;
+ break;
+ }
+ target.write(buffer, bufferRead);
+ bufferWritten += bufferRead;
+ wprintf(L"%s -> %s (%d / %d) %d %%\r", deviceSource.utf16(), localDest.utf16(), bufferWritten, fileSize, (100*bufferWritten)/fileSize);
+ }
+ wprintf(L"\n");
+
+ if (!readUntilEnd) {
+ debugOutput(QString::fromLatin1(" an error occurred during copy"), 2);
+ return false;
+ }
+
+ CeCloseHandle(deviceHandle);
+ return true;
+}
+
+bool ActiveSyncConnection::copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive)
+{
+ if (!QDir(localDest).exists() && !QDir(localDest).mkpath(QDir(localDest).absolutePath())) {
+ debugOutput(QString::fromLatin1(" Could not create local path"), 2);
+ }
+
+ QString searchArg = deviceSource + "\\*";
+ CE_FIND_DATA data;
+ HANDLE searchHandle = CeFindFirstFile(searchArg.utf16(), &data);
+ if (searchHandle == INVALID_HANDLE_VALUE) {
+ // We return true because we might be in a recursive call
+ // where nothing is to copy and the copy process
+ // might still be correct
+ return true;
+ }
+
+ do {
+ QString srcFile = deviceSource + "\\" + QString::fromWCharArray(data.cFileName);
+ QString destFile = localDest + "\\" + QString::fromWCharArray(data.cFileName);
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (recursive && !copyDirectoryFromDevice(srcFile, destFile, recursive)) {
+ wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16());
+ return false;
+ }
+ } else {
+ copyFileFromDevice(srcFile, destFile, false);
+ }
+ } while(CeFindNextFile(searchHandle, &data));
+ CeFindClose(searchHandle);
+ return true;
+}
+
+bool ActiveSyncConnection::copyFile(const QString &srcFile, const QString &destFile, bool failIfExists)
+{
+ return CeCopyFile(QDir::toNativeSeparators(srcFile).utf16(),
+ QDir::toNativeSeparators(destFile).utf16(), failIfExists);
+}
+
+bool ActiveSyncConnection::copyDirectory(const QString &srcDirectory, const QString &destDirectory,
+ bool recursive)
+{
+ CeCreateDirectory(destDirectory.utf16(), NULL);
+ QString searchArg = srcDirectory + "\\*";
+ CE_FIND_DATA data;
+ HANDLE searchHandle = CeFindFirstFile(searchArg.utf16(), &data);
+ if (searchHandle == INVALID_HANDLE_VALUE) {
+ // We return true because we might be in a recursive call
+ // where nothing is to copy and the copy process
+ // might still be correct
+ return true;
+ }
+
+ do {
+ QString srcFile = srcDirectory + "\\" + QString::fromWCharArray(data.cFileName);
+ QString destFile = destDirectory + "\\" + QString::fromWCharArray(data.cFileName);
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (recursive && !copyDirectory(srcFile, destFile, recursive)) {
+ wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16());
+ return false;
+ }
+ } else {
+ debugOutput(QString::fromLatin1("Copy %1 -> %2\n").arg(srcFile).arg(destFile), 0);
+ CeCopyFile(srcFile.utf16(), destFile.utf16(), false);
+ }
+ } while(CeFindNextFile(searchHandle, &data));
+ CeFindClose(searchHandle);
+ return true;
+}
+
+bool ActiveSyncConnection::deleteFile(const QString &fileName)
+{
+ CeSetFileAttributes(fileName.utf16(), FILE_ATTRIBUTE_NORMAL);
+ return CeDeleteFile(fileName.utf16());
+}
+
+bool ActiveSyncConnection::deleteDirectory(const QString &directory, bool recursive, bool failIfContentExists)
+{
+ HANDLE hFind;
+ CE_FIND_DATA FindFileData;
+ QString FileName = directory + "\\*";
+ hFind = CeFindFirstFile(FileName.utf16(), &FindFileData);
+ if( hFind == INVALID_HANDLE_VALUE )
+ return CeRemoveDirectory(directory.utf16());
+
+ if (failIfContentExists)
+ return false;
+
+ do {
+ QString FileName = directory + "\\" + QString::fromWCharArray(FindFileData.cFileName);
+ if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (recursive)
+ if (!deleteDirectory(FileName, recursive, failIfContentExists))
+ return false;
+ } else {
+ if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ CeSetFileAttributes(FileName.utf16(), FILE_ATTRIBUTE_NORMAL);
+ if( !CeDeleteFile(FileName.utf16()) )
+ break;
+ }
+ } while(CeFindNextFile(hFind,&FindFileData));
+ CeFindClose(hFind);
+
+ return CeRemoveDirectory(directory.utf16());
+}
+
+bool ActiveSyncConnection::execute(QString program, QString arguments, int timeout, int *returnValue)
+{
+ if (!isConnected()) {
+ qWarning("Cannot execute, connect to device first!");
+ return false;
+ }
+
+ PROCESS_INFORMATION* pid = new PROCESS_INFORMATION;
+ bool result = false;
+ if (timeout != 0) {
+ // If we want to wait, we have to use CeRapiInvoke, as CeCreateProcess has no way to wait
+ // until the process ends. The lib must have been build and also deployed already.
+ if (!isConnected() && !connect())
+ return false;
+
+ QString dllLocation = "\\Windows\\QtRemote.dll";
+ QString functionName = "qRemoteLaunch";
+
+ DWORD outputSize;
+ BYTE* output;
+ IRAPIStream *stream;
+ int returned = 0;
+ DWORD error = 0;
+ HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0);
+ if (S_OK != res) {
+ DWORD ce_error = CeGetLastError();
+ if (S_OK != ce_error) {
+ qWarning("Error invoking %s on %s: %s", qPrintable(functionName),
+ qPrintable(dllLocation), strwinerror(ce_error).constData());
+ } else {
+ qWarning("Error: %s on %s unexpectedly returned %d", qPrintable(functionName),
+ qPrintable(dllLocation), res);
+ }
+ } else {
+ DWORD written;
+ int strSize = program.length();
+ if (S_OK != stream->Write(&strSize, sizeof(strSize), &written)) {
+ qWarning(" Could not write appSize to process");
+ return false;
+ }
+ if (S_OK != stream->Write(program.utf16(), program.length()*sizeof(wchar_t), &written)) {
+ qWarning(" Could not write appName to process");
+ return false;
+ }
+ strSize = arguments.length();
+ if (S_OK != stream->Write(&strSize, sizeof(strSize), &written)) {
+ qWarning(" Could not write argumentSize to process");
+ return false;
+ }
+ if (S_OK != stream->Write(arguments.utf16(), arguments.length()*sizeof(wchar_t), &written)) {
+ qWarning(" Could not write arguments to process");
+ return false;
+ }
+ if (S_OK != stream->Write(&timeout, sizeof(timeout), &written)) {
+ qWarning(" Could not write waiting option to process");
+ return false;
+ }
+
+ if (S_OK != stream->Read(&returned, sizeof(returned), &written)) {
+ qWarning(" Could not access return value of process");
+ }
+ if (S_OK != stream->Read(&error, sizeof(error), &written)) {
+ qWarning(" Could not access error code");
+ }
+
+ if (error) {
+ qWarning("Error on target: %s", strwinerror(error).constData());
+ result = false;
+ }
+ else {
+ result = true;
+ }
+ }
+
+ if (returnValue)
+ *returnValue = returned;
+ } else {
+ // We do not need to invoke another lib etc, if we are not interested in results anyway...
+ result = CeCreateProcess(program.utf16(), arguments.utf16(), 0, 0, false, 0, 0, 0, 0, pid);
+ }
+ return result;
+}
+
+bool ActiveSyncConnection::setDeviceAwake(bool activate, int *returnValue)
+{
+ if (!isConnected()) {
+ qWarning("Cannot execute, connect to device first!");
+ return false;
+ }
+ bool result = false;
+
+ // If we want to wait, we have to use CeRapiInvoke, as CeCreateProcess has no way to wait
+ // until the process ends. The lib must have been build and also deployed already.
+ if (!isConnected() && !connect())
+ return false;
+
+ HRESULT res = S_OK;
+
+ //SYSTEM_POWER_STATUS_EX systemPowerState;
+
+ //res = CeGetSystemPowerStatusEx(&systemPowerState, true);
+
+ QString dllLocation = "\\Windows\\QtRemote.dll";
+ QString functionName = "qRemoteToggleUnattendedPowerMode";
+
+ DWORD outputSize;
+ BYTE* output;
+ IRAPIStream *stream;
+ int returned = 0;
+ int toggle = int(activate);
+
+ res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0);
+ if (S_OK != res) {
+ DWORD ce_error = CeGetLastError();
+ if (S_OK != ce_error) {
+ qWarning("Error invoking %s on %s: %s", qPrintable(functionName),
+ qPrintable(dllLocation), strwinerror(ce_error).constData());
+ } else {
+ qWarning("Error: %s on %s unexpectedly returned %d", qPrintable(functionName),
+ qPrintable(dllLocation), res);
+ }
+ } else {
+ DWORD written;
+
+ if (S_OK != stream->Write(&toggle, sizeof(toggle), &written)) {
+ qWarning(" Could not write toggle option to process");
+ return false;
+ }
+
+ if (S_OK != stream->Read(&returned, sizeof(returned), &written)) {
+ qWarning(" Could not access return value of process");
+ }
+ else
+ result = true;
+ }
+
+ if (returnValue)
+ *returnValue = returned;
+
+ return result;
+}
+
+bool ActiveSyncConnection::resetDevice()
+{
+ if (!isConnected()) {
+ qWarning("Cannot execute, connect to device first!");
+ return false;
+ }
+
+ bool result = false;
+ if (!isConnected() && !connect())
+ return false;
+
+ QString dllLocation = "\\Windows\\QtRemote.dll";
+ QString functionName = "qRemoteSoftReset";
+
+ DWORD outputSize;
+ BYTE* output;
+ IRAPIStream *stream;
+
+ int returned = 0;
+
+ HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0);
+ if (S_OK != res) {
+ DWORD ce_error = CeGetLastError();
+ if (S_OK != ce_error) {
+ qWarning("Error invoking %s on %s: %s", qPrintable(functionName),
+ qPrintable(dllLocation), strwinerror(ce_error).constData());
+ } else {
+ qWarning("Error: %s on %s unexpectedly returned %d", qPrintable(functionName),
+ qPrintable(dllLocation), res);
+ }
+ } else {
+ result = true;
+ }
+ return result;
+}
+
+bool ActiveSyncConnection::toggleDevicePower(int *returnValue)
+{
+ if (!isConnected()) {
+ qWarning("Cannot execute, connect to device first!");
+ return false;
+ }
+
+ bool result = false;
+ if (!isConnected() && !connect())
+ return false;
+
+ QString dllLocation = "\\Windows\\QtRemote.dll";
+ QString functionName = "qRemotePowerButton";
+
+ DWORD outputSize;
+ BYTE* output;
+ IRAPIStream *stream;
+ int returned = 0;
+
+ HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0);
+ if (S_OK != res) {
+ DWORD ce_error = CeGetLastError();
+ if (S_OK != ce_error) {
+ qWarning("Error invoking %s on %s: %s", qPrintable(functionName),
+ qPrintable(dllLocation), strwinerror(ce_error).constData());
+ } else {
+ qWarning("Error: %s on %s unexpectedly returned %d", qPrintable(functionName),
+ qPrintable(dllLocation), res);
+ }
+ } else {
+ DWORD written;
+ if (S_OK != stream->Read(&returned, sizeof(returned), &written)) {
+ qWarning(" Could not access return value of process");
+ }
+ else {
+ result = true;
+ }
+ }
+
+ if (returnValue)
+ *returnValue = returned;
+ return result;
+}
+
+bool ActiveSyncConnection::createDirectory(const QString &path, bool deleteBefore)
+{
+ if (deleteBefore)
+ deleteDirectory(path);
+ QStringList separated = path.split(QLatin1Char('\\'));
+ QString current = QLatin1String("\\");
+ bool result;
+ for (int i=1; i < separated.size(); ++i) {
+ current += separated.at(i);
+ result = CeCreateDirectory(current.utf16(), NULL);
+ current += QLatin1String("\\");
+ }
+ return result;
+}
+
+bool ActiveSyncConnection::timeStampForLocalFileTime(FILETIME* fTime) const
+{
+ QString tmpFile = QString::fromLatin1("\\qt_tmp_ftime_convert");
+ HANDLE remoteHandle = CeCreateFile(tmpFile.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (remoteHandle == INVALID_HANDLE_VALUE)
+ return false;
+
+ LocalFileTimeToFileTime(fTime, fTime);
+
+ if (!CeSetFileTime(remoteHandle, fTime, NULL, NULL)) {
+ CeCloseHandle(remoteHandle);
+ return false;
+ }
+
+ CeCloseHandle(remoteHandle);
+ remoteHandle = CeCreateFile(tmpFile.utf16(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (remoteHandle == INVALID_HANDLE_VALUE)
+ return false;
+ if (!CeGetFileTime(remoteHandle, fTime, NULL, NULL)) {
+ CeCloseHandle(remoteHandle);
+ return false;
+ }
+
+ CeCloseHandle(remoteHandle);
+ CeDeleteFile(tmpFile.utf16());
+ return true;
+}
+
+bool ActiveSyncConnection::fileCreationTime(const QString &fileName, FILETIME* deviceCreationTime) const
+{
+ HANDLE deviceHandle = CeCreateFile(fileName.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (deviceHandle == INVALID_HANDLE_VALUE)
+ return false;
+
+ bool result = true;
+ if (!CeGetFileTime(deviceHandle, deviceCreationTime, NULL, NULL))
+ result = false;
+
+ CeCloseHandle(deviceHandle);
+ return result;
+}
diff --git a/src/qtestlib/wince/cetest/activesyncconnection.h b/src/qtestlib/wince/cetest/activesyncconnection.h
new file mode 100644
index 000000000..c23742e50
--- /dev/null
+++ b/src/qtestlib/wince/cetest/activesyncconnection.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACTIVESYNC_REMOTECONNECTION_H
+#define ACTIVESYNC_REMOTECONNECTION_H
+
+#include "remoteconnection.h"
+
+#if defined(Q_OS_WIN32)
+#define REMOTELIBNAME "remotecommands"
+#endif
+
+class ActiveSyncConnection : public AbstractRemoteConnection
+{
+public:
+ ActiveSyncConnection();
+ virtual ~ActiveSyncConnection();
+
+ bool connect(QVariantList &list = QVariantList());
+ void disconnect();
+ bool isConnected() const;
+
+ // These functions are designed for transfer between desktop and device
+ // Caution: deviceDest path has to be device specific (eg. no drive letters for CE)
+ bool copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists = false);
+ bool copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive = true);
+ bool copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists = false);
+ bool copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive = true);
+
+ bool timeStampForLocalFileTime(FILETIME*) const;
+ bool fileCreationTime(const QString &fileName, FILETIME*) const;
+
+ // These functions only work on files existing on the device
+ bool copyFile(const QString&, const QString&, bool failIfExists = false);
+ bool copyDirectory(const QString&, const QString&, bool recursive = true);
+ bool deleteFile(const QString&);
+ bool deleteDirectory(const QString&, bool recursive = true, bool failIfContentExists = false);
+ bool moveFile(const QString&, const QString&, bool FailIfExists = false);
+ bool moveDirectory(const QString&, const QString&, bool recursive = true);
+
+ bool createDirectory(const QString&, bool deleteBefore=false);
+
+ bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL);
+ bool resetDevice();
+ bool toggleDevicePower(int *returnValue = NULL);
+ bool setDeviceAwake(bool activate, int *returnValue = NULL);
+private:
+ bool connected;
+};
+
+#endif
diff --git a/src/qtestlib/wince/cetest/bootstrapped.pri b/src/qtestlib/wince/cetest/bootstrapped.pri
new file mode 100644
index 000000000..56c8ab7e9
--- /dev/null
+++ b/src/qtestlib/wince/cetest/bootstrapped.pri
@@ -0,0 +1,45 @@
+# Bootstrapped Input
+SOURCES += \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstring.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfilesystemiterator_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qbuffer.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qurl.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qsettings.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qsettings_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearray.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearraymatcher.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvector.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvsnprintf.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlist.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qhash.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qglobal.cpp \
+ $$QT_BUILD_TREE/src/corelib/global/qconfig.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qmalloc.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qnumeric.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qlibraryinfo.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qregexp.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qmetatype.cpp \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp \
+ $$QT_SOURCE_TREE/src/corelib/codecs/qutfcodec.cpp \
+ $$QT_SOURCE_TREE/src/corelib/xml/qxmlstream.cpp \
+ $$QT_SOURCE_TREE/src/corelib/xml/qxmlutils.cpp
+
diff --git a/src/qtestlib/wince/cetest/cetcpsyncconnection.cpp b/src/qtestlib/wince/cetest/cetcpsyncconnection.cpp
new file mode 100644
index 000000000..ba55c3928
--- /dev/null
+++ b/src/qtestlib/wince/cetest/cetcpsyncconnection.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "CeTcpSyncConnection.h"
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo>
+
+static const QString ceTcpSyncProgram = "cetcpsync";
+extern void debugOutput(const QString& text, int level);
+
+CeTcpSyncConnection::CeTcpSyncConnection()
+ : AbstractRemoteConnection()
+ , connected(false)
+{
+}
+
+CeTcpSyncConnection::~CeTcpSyncConnection()
+{
+ if (isConnected())
+ disconnect();
+}
+
+bool CeTcpSyncConnection::connect(QVariantList&)
+{
+ // We connect with each command, so this is always true
+ // The command itself will fail then
+ const QString cmd = ceTcpSyncProgram + " noop";
+ if (system(qPrintable(cmd)) != 0)
+ return false;
+ connected = true;
+ return true;
+}
+
+void CeTcpSyncConnection::disconnect()
+{
+ connected = false;
+}
+
+bool CeTcpSyncConnection::isConnected() const
+{
+ return connected;
+}
+
+inline QString boolToString(bool b)
+{
+ return b ? "true" : "false";
+}
+
+static bool fileTimeFromString(FILETIME& ft, const QString& str)
+{
+ int idx = str.indexOf("*");
+ if (idx <= 0)
+ return false;
+ bool ok;
+ ft.dwLowDateTime = str.left(idx).toULong(&ok);
+ if (!ok)
+ return false;
+ ft.dwHighDateTime = str.mid(idx+1).toULong(&ok);
+ return ok;
+}
+
+static QString fileTimeToString(FILETIME& ft)
+{
+ return QString::number(ft.dwLowDateTime) + "*" + QString::number(ft.dwHighDateTime);
+}
+
+bool CeTcpSyncConnection::copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists)
+{
+ QString cmd = ceTcpSyncProgram + " copyFileToDevice \"" + localSource + "\" \"" + deviceDest + "\" " + boolToString(failIfExists);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive)
+{
+ QString cmd = ceTcpSyncProgram + " copyDirectoryToDevice \"" + localSource + "\" \"" + deviceDest + "\" " + boolToString(recursive);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists)
+{
+ QString cmd = ceTcpSyncProgram + " copyFileFromDevice \"" + deviceSource + "\" \"" + localDest + "\" " + boolToString(failIfExists);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive)
+{
+ QString cmd = ceTcpSyncProgram + " copyDirectoryFromDevice \"" + deviceSource + "\" \"" + localDest + "\" " + boolToString(recursive);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::copyFile(const QString &srcFile, const QString &destFile, bool failIfExists)
+{
+ QString cmd = ceTcpSyncProgram + " copyFile \"" + srcFile + "\" \"" + destFile + "\" " + boolToString(failIfExists);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::copyDirectory(const QString &srcDirectory, const QString &destDirectory,
+ bool recursive)
+{
+ QString cmd = ceTcpSyncProgram + " copyDirectory \"" + srcDirectory + "\" \"" + destDirectory + "\" " + boolToString(recursive);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::deleteFile(const QString &fileName)
+{
+ QString cmd = ceTcpSyncProgram + " deleteFile \"" + fileName + "\"";
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::deleteDirectory(const QString &directory, bool recursive, bool failIfContentExists)
+{
+ QString cmd = ceTcpSyncProgram + " deleteDirectory \"" + directory + "\" " + boolToString(recursive) + " " + boolToString(failIfContentExists);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::execute(QString program, QString arguments, int timeout, int *returnValue)
+{
+ QString cmd = ceTcpSyncProgram + " execute \"" + program + "\" \"" + arguments + "\" " + QString::number(timeout);
+ int exitCode = system(qPrintable(cmd));
+ if (returnValue)
+ *returnValue = exitCode;
+ return true;
+}
+
+bool CeTcpSyncConnection::createDirectory(const QString &path, bool deleteBefore)
+{
+ QString cmd = ceTcpSyncProgram + " createDirectory \"" + path + "\" " + boolToString(deleteBefore);
+ return system(qPrintable(cmd)) == 0;
+}
+
+bool CeTcpSyncConnection::timeStampForLocalFileTime(FILETIME* fTime) const
+{
+ QString cmd = ceTcpSyncProgram + " timeStampForLocalFileTime " + fileTimeToString(*fTime) + " >qt_cetcpsyncdata.txt";
+ if (system(qPrintable(cmd)) != 0)
+ return false;
+
+ QFile file("qt_cetcpsyncdata.txt");
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+
+ bool result = fileTimeFromString(*fTime, file.readLine());
+ file.close();
+ file.remove();
+ return result;
+}
+
+bool CeTcpSyncConnection::fileCreationTime(const QString &fileName, FILETIME* deviceCreationTime) const
+{
+ QString cmd = ceTcpSyncProgram + " fileCreationTime \"" + fileName + "\" >qt_cetcpsyncdata.txt";
+ if (system(qPrintable(cmd)) != 0)
+ return false;
+
+ QFile file("qt_cetcpsyncdata.txt");
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+
+ bool result = fileTimeFromString(*deviceCreationTime, file.readLine());
+ file.close();
+ file.remove();
+ return result;
+}
+
+bool CeTcpSyncConnection::resetDevice()
+{
+ qWarning("CeTcpSyncConnection::resetDevice not implemented");
+ return false;
+}
+
+bool CeTcpSyncConnection::toggleDevicePower(int *returnValue)
+{
+ Q_UNUSED(returnValue);
+ qWarning("CeTcpSyncConnection::toggleDevicePower not implemented");
+ return false;
+}
+
+bool CeTcpSyncConnection::setDeviceAwake(bool activate, int *returnValue)
+{
+ Q_UNUSED(activate);
+ Q_UNUSED(returnValue);
+ qWarning("CeTcpSyncConnection::setDeviceAwake not implemented");
+ return false;
+}
diff --git a/src/qtestlib/wince/cetest/cetcpsyncconnection.h b/src/qtestlib/wince/cetest/cetcpsyncconnection.h
new file mode 100644
index 000000000..47150a11b
--- /dev/null
+++ b/src/qtestlib/wince/cetest/cetcpsyncconnection.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CETCPSYNC_REMOTECONNECTION_H
+#define CETCPSYNC_REMOTECONNECTION_H
+
+#include "remoteconnection.h"
+
+class CeTcpSyncConnection : public AbstractRemoteConnection
+{
+public:
+ CeTcpSyncConnection();
+ virtual ~CeTcpSyncConnection();
+
+ bool connect(QVariantList &list = QVariantList());
+ void disconnect();
+ bool isConnected() const;
+
+ // These functions are designed for transfer between desktop and device
+ // Caution: deviceDest path has to be device specific (eg. no drive letters for CE)
+ bool copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists = false);
+ bool copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive = true);
+ bool copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists = false);
+ bool copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive = true);
+
+ bool timeStampForLocalFileTime(FILETIME*) const;
+ bool fileCreationTime(const QString &fileName, FILETIME*) const;
+
+ // These functions only work on files existing on the device
+ bool copyFile(const QString&, const QString&, bool failIfExists = false);
+ bool copyDirectory(const QString&, const QString&, bool recursive = true);
+ bool deleteFile(const QString&);
+ bool deleteDirectory(const QString&, bool recursive = true, bool failIfContentExists = false);
+ bool moveFile(const QString&, const QString&, bool FailIfExists = false);
+ bool moveDirectory(const QString&, const QString&, bool recursive = true);
+
+ bool createDirectory(const QString&, bool deleteBefore=false);
+
+ bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL);
+ bool resetDevice();
+ bool toggleDevicePower(int *returnValue = NULL);
+ bool setDeviceAwake(bool activate, int *returnValue = NULL);
+private:
+ bool connected;
+};
+
+#endif
diff --git a/src/qtestlib/wince/cetest/cetest.pro b/src/qtestlib/wince/cetest/cetest.pro
new file mode 100644
index 000000000..82747dada
--- /dev/null
+++ b/src/qtestlib/wince/cetest/cetest.pro
@@ -0,0 +1,56 @@
+TEMPLATE = app
+TARGET = cetest
+DESTDIR = ../../../../bin
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+CONFIG += console no_batch
+CONFIG -= qt
+
+DEFINES += QT_BUILD_QMAKE QT_BOOTSTRAPPED QT_NO_CODECS QT_LITE_UNICODE QT_NO_LIBRARY \
+ QT_NO_STL QT_NO_COMPRESS QT_NO_DATASTREAM \
+ QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_NO_THREAD \
+ QT_NO_SYSTEMLOCALE QT_NO_GEOM_VARIANT \
+ QT_NODLL QT_NO_QOBJECT
+
+INCLUDEPATH = \
+ $$QT_SOURCE_TREE/tools/qtestlib/ce/cetest \
+ $$QT_SOURCE_TREE/qmake \
+ $$QT_SOURCE_TREE/qmake/generators/symbian \
+ $$QT_SOURCE_TREE/tools/shared \
+ $$QT_BUILD_TREE/include \
+ $$QT_BUILD_TREE/include/QtCore \
+ $$QT_BUILD_TREE/src/corelib/global
+
+VPATH += $$QT_SOURCE_TREE/tools/shared
+
+DEPENDPATH += $$QT_BUILD_TREE/src/corelib/tools $$QT_BUILD_TREE/src/corelib/io
+
+# Input
+HEADERS += \
+ remoteconnection.h \
+ deployment.h
+
+SOURCES += \
+ remoteconnection.cpp \
+ deployment.cpp \
+ main.cpp
+
+LIBS += ole32.lib advapi32.lib
+
+isEmpty(QT_CE_RAPI_INC) {
+ DEFINES += QT_CETEST_NO_ACTIVESYNC
+ HEADERS += cetcpsyncconnection.h
+ SOURCES += cetcpsyncconnection.cpp
+} else {
+ HEADERS += activesyncconnection.h
+ SOURCES += activesyncconnection.cpp
+ LIBS += rapi.lib
+ INCLUDEPATH += $$QT_CE_RAPI_INC
+ LIBS += -L$$QT_CE_RAPI_LIB
+}
+
+include(qmake_include.pri)
+include(bootstrapped.pri)
diff --git a/src/qtestlib/wince/cetest/deployment.cpp b/src/qtestlib/wince/cetest/deployment.cpp
new file mode 100644
index 000000000..cd6ce2806
--- /dev/null
+++ b/src/qtestlib/wince/cetest/deployment.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deployment.h"
+#include "remoteconnection.h"
+#include <option.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qstring.h>
+
+extern void debugOutput(const QString& text, int level);
+
+bool DeploymentHandler::deviceCopy(const DeploymentList &deploymentList)
+{
+ for (int i=0; i<deploymentList.size(); ++i) {
+ CopyItem item = deploymentList.at(i);
+ m_connection->createDirectory(item.to.left(item.to.lastIndexOf(QLatin1Char('\\'))));
+ if (!m_connection->copyFileToDevice(item.from , item.to)) {
+ debugOutput(QString::fromLatin1("Error while copy: %1 -> %2").arg(item.from).arg(item.to),0);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DeploymentHandler::deviceDeploy(const DeploymentList &deploymentList)
+{
+ DeploymentList copyList;
+ for (int i=0; i<deploymentList.size(); ++i) {
+#if defined(Q_OS_WIN)
+ HANDLE localHandle = CreateFile(deploymentList.at(i).from.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (localHandle == INVALID_HANDLE_VALUE) {
+ copyList.append(deploymentList.at(i));
+ continue;
+ }
+ FILETIME localCreationTime;
+ if (!GetFileTime(localHandle, NULL, NULL, &localCreationTime) || !m_connection->timeStampForLocalFileTime(&localCreationTime)) {
+ copyList.append(deploymentList.at(i));
+ CloseHandle(localHandle);
+ continue;
+ }
+ CloseHandle(localHandle);
+
+ FILETIME deviceCreationTime;
+ if (!m_connection->fileCreationTime(deploymentList.at(i).to , &deviceCreationTime)) {
+ copyList.append(deploymentList.at(i));
+ continue;
+ }
+
+ int res = CompareFileTime(&localCreationTime, &deviceCreationTime);
+ if (res != 0)
+ copyList.append(deploymentList.at(i));
+ else
+ debugOutput(QString::fromLatin1("Skipping File %1, already latest version").arg(deploymentList.at(i).from),0);
+#else
+ copyList.append(deploymentList.at(i));
+#endif
+ }
+ return deviceCopy(copyList);
+}
+
+void DeploymentHandler::cleanup(const DeploymentList &deploymentList)
+{
+ for (int i=0; i<deploymentList.size(); ++i) {
+ m_connection->deleteFile(deploymentList.at(i).to);
+#ifdef Q_OS_WIN
+ QString path = deploymentList.at(i).to;
+ int pos;
+ while ( (pos = path.lastIndexOf(QLatin1Char('\\'))) > 0) {
+ path = path.left(pos);
+ if (!m_connection->deleteDirectory(path, false, true))
+ break;
+ }
+#endif
+ }
+}
+
+void DeploymentHandler::initQtDeploy(QMakeProject *project, DeploymentList &deploymentList, const QString &testPath)
+{
+ QString targetPath = project->values("deploy.path").join(" ");
+ if (targetPath.isEmpty())
+ targetPath = testPath;
+ if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
+ targetPath = targetPath.mid(0,targetPath.size()-1);
+
+ // Only deploy Qt libs for shared build
+ if (!project->values("QMAKE_QT_DLL").isEmpty() && !project->values("QMAKE_LIBDIR").isEmpty()) {
+ QStringList libs = project->values("LIBS");
+ QStringList qtLibs;
+ QStringList libPaths;
+ foreach (QString item, libs) {
+
+ if (item.startsWith("-L")) {
+ // -L -> a directory containing DLLs
+ libPaths << item.mid(2);
+ continue;
+ }
+
+ QStringList libCandidates;
+
+ if (item.startsWith("-l")) {
+ // -l -> a library located within one of the standard library paths
+ QString lib = item.mid(2);
+
+ // Check if it's a Qt library first, then check in all paths given with -L.
+ // Note Qt libraries get a `4' appended to them, others don't.
+ libCandidates << project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + lib + QLatin1String("4.dll");
+ foreach (QString const& libPath, libPaths) {
+ libCandidates << libPath + QDir::separator() + lib + QLatin1String(".dll");
+ }
+ } else {
+ libCandidates << item.replace(".lib",".dll");
+ }
+
+ foreach (QString const& file, libCandidates) {
+ QFileInfo info(file);
+ if (info.exists()) {
+ qtLibs += info.dir().absoluteFilePath(info.fileName());
+ break;
+ }
+ }
+ }
+ for (QStringList::ConstIterator it = qtLibs.constBegin(); it != qtLibs.constEnd(); ++it) {
+ QString dllName = *it;
+ QFileInfo info(dllName);
+ if (!info.exists())
+ continue;
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absoluteFilePath()) ,
+ Option::fixPathToLocalOS(targetPath + "/" + info.fileName())));
+ }
+ }
+
+#ifndef QT_CETEST_NO_ACTIVESYNC
+ // QtRemote deployment. We always deploy to \Windows
+ if (!project->values("QMAKE_LIBDIR").isEmpty()) {
+ QString remoteLibName = QLatin1String("QtRemote.dll");
+ QString remoteLib = Option::fixPathToLocalOS(project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + remoteLibName);
+ if (QFile::exists(remoteLib))
+ deploymentList.append(CopyItem(remoteLib, QString::fromLatin1("\\Windows\\") + remoteLibName));
+ else
+ debugOutput(QString::fromLatin1("Could not find QtRemote. Might not be able to launch target executable"),0);
+ }
+#endif
+
+ // C-runtime deployment
+ QString runtime = project->values("QT_CE_C_RUNTIME").join(QLatin1String(" "));
+ debugOutput(QString::fromLatin1("Runtime:%1").arg(runtime), 2);
+ if (!runtime.isEmpty() && (runtime != QLatin1String("no"))) {
+ QString runtimeVersion = QLatin1String("msvcr");
+ const QString mkspec = project->values("QMAKESPEC").first();
+ if (mkspec.endsWith("2008"))
+ runtimeVersion.append("90");
+ else
+ runtimeVersion.append("80");
+ if (project->isActiveConfig("debug"))
+ runtimeVersion.append("d");
+ runtimeVersion.append(".dll");
+
+ if (runtime == "yes") {
+ // Auto-find C-runtime
+ QString vcInstallDir = qgetenv("VCINSTALLDIR");
+ if (!vcInstallDir.isEmpty()) {
+ vcInstallDir += "\\ce\\dll\\";
+ vcInstallDir += project->values("CE_ARCH").join(QLatin1String(" "));
+ if (!QFileInfo(vcInstallDir + QDir::separator() + runtimeVersion).exists())
+ runtime.clear();
+ else
+ runtime = vcInstallDir;
+ }
+ }
+
+ if (!runtime.isEmpty()) {
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(runtime + "/" + runtimeVersion ) ,
+ Option::fixPathToLocalOS(targetPath + "/" + runtimeVersion)));
+ }
+ }
+}
+
+void DeploymentHandler::initProjectDeploy(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath)
+{
+ QString targetPath = project->values("deploy.path").join(" ");
+ if (targetPath.isEmpty())
+ targetPath = testPath;
+ if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
+ targetPath = targetPath.mid(0,targetPath.size()-1);
+
+ QStringList& list = project->values("DEPLOYMENT");
+ if (list.isEmpty())
+ return;
+
+ for (int it = 0; it < list.size(); ++it) {
+ QString argSource = list.at(it);
+ QString argPath = list.at(it) + QString(".path");
+ if (((project->values(argSource + QString(".files")).isEmpty() && project->values(argSource + QString(".sources")).isEmpty()) || project->values(argPath).isEmpty()) && list.at(it) != "deploy") {
+ debugOutput(QString::fromLatin1("cannot deploy \"%1\" because of missing data.").arg(list.at(it)), 0);
+ continue;
+ }
+
+ QString addPath = project->values(argPath).join(QLatin1String(" "));
+ if (addPath == QLatin1String("."))
+ addPath.clear();
+ if (!addPath.startsWith("/") && !addPath.startsWith(QLatin1String("\\")))
+ addPath = targetPath + "/" + addPath;
+
+ QStringList addSources = project->values(argSource + QString(".files")) + project->values(argSource + QString(".sources"));
+ addSources.replaceInStrings(QLatin1String("/"), QLatin1String("\\"));
+ for(int index=0; index < addSources.size(); ++index) {
+ QString dirstr = qmake_getpwd();
+ QString filestr = Option::fixPathToLocalOS(addSources.at(index), false, false);
+ int slsh = filestr.lastIndexOf(Option::dir_sep);
+ if(slsh != -1) {
+ dirstr = filestr.left(slsh+1);
+ filestr = filestr.right(filestr.length() - slsh - 1);
+ }
+ if(dirstr.right(Option::dir_sep.length()) != Option::dir_sep)
+ dirstr += Option::dir_sep;
+ QFileInfo info(dirstr + filestr);
+
+ static int addQMakeDeployCounter = 0;
+ QStringList entryList = info.absoluteDir().entryList(QStringList() << info.fileName());
+ if (entryList.size() > 1) {
+ foreach(QString s, entryList) {
+ // We do not include directories when using wildcards
+ QFileInfo wildInfo(info.absolutePath() + "/" + s);
+ if (wildInfo.isDir()) {
+ continue;
+ }
+ QString appendedQmakeDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++);
+ project->parse(appendedQmakeDeploy + QLatin1String(".files = \"") + wildInfo.absoluteFilePath());
+ project->parse(appendedQmakeDeploy + QLatin1String(".path = \"") + addPath);
+ list.append(appendedQmakeDeploy);
+ }
+ continue;
+ }
+
+ if (info.isDir()) {
+ QDir additionalDir(dirstr + filestr);
+ QStringList additionalEntries = additionalDir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::NoSymLinks);
+ foreach(QString item, additionalEntries) {
+ QString appendedDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++);
+ project->parse(appendedDeploy + QLatin1String(".files = \"") + Option::fixPathToLocalOS(additionalDir.absoluteFilePath(item)) + QLatin1String("\""));
+ QString appendTargetPath = project->values(argPath).join(QLatin1String(" "));
+ if (appendTargetPath == QLatin1String("."))
+ appendTargetPath = filestr;
+ else
+ appendTargetPath.append(QLatin1String("\\") + filestr);
+ project->parse(appendedDeploy + QLatin1String(".path = ") + appendTargetPath);
+ list.append(appendedDeploy);
+ }
+ } else if (entryList.size() == 1)
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absolutePath() + "/" + entryList.at(0)) ,
+ Option::fixPathToLocalOS(addPath + "/" + entryList.at(0))));
+ }
+ }
+}
diff --git a/src/qtestlib/wince/cetest/deployment.h b/src/qtestlib/wince/cetest/deployment.h
new file mode 100644
index 000000000..9d0b9caec
--- /dev/null
+++ b/src/qtestlib/wince/cetest/deployment.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEPLOYMENT_INCL
+#define DEPLOYMENT_INCL
+
+#include <qstring.h>
+#include <qlist.h>
+#include <project.h>
+
+class AbstractRemoteConnection;
+
+struct CopyItem
+{
+ CopyItem(const QString& f, const QString& t) : from(f) , to(t) { }
+ QString from;
+ QString to;
+};
+typedef QList<CopyItem> DeploymentList;
+
+class DeploymentHandler
+{
+public:
+ inline void setConnection(AbstractRemoteConnection*);
+ inline AbstractRemoteConnection* connection() const;
+ bool deviceCopy(const DeploymentList &deploymentList);
+ bool deviceDeploy(const DeploymentList &deploymentList);
+ void cleanup(const DeploymentList &deploymentList);
+ static void initProjectDeploy(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath = "\\Program Files\\qt_test");
+ static void initQtDeploy(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath = "\\Program Files\\qt_test");
+private:
+ AbstractRemoteConnection* m_connection;
+};
+
+inline void DeploymentHandler::setConnection(AbstractRemoteConnection *connection) { m_connection = connection; }
+inline AbstractRemoteConnection* DeploymentHandler::connection() const { return m_connection; }
+#endif \ No newline at end of file
diff --git a/src/qtestlib/wince/cetest/main.cpp b/src/qtestlib/wince/cetest/main.cpp
new file mode 100644
index 000000000..7e9ea5dfb
--- /dev/null
+++ b/src/qtestlib/wince/cetest/main.cpp
@@ -0,0 +1,445 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef QT_CETEST_NO_ACTIVESYNC
+# include "cetcpsyncconnection.h"
+#else
+# include "activesyncconnection.h"
+#endif
+
+const int SLEEP_AFTER_RESET = 60000; // sleep for 1 minute
+const int SLEEP_RECONNECT = 2000; // sleep for 2 seconds before trying another reconnect
+
+#include "deployment.h"
+#include <option.h>
+#include <project.h>
+#include <property.h>
+#include <qstringlist.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <iostream>
+using namespace std;
+
+const int debugLevel = 0;
+void debugOutput(const QString& text, int level)
+{
+ if (level <= debugLevel)
+ cout << qPrintable(text) << endl;
+}
+
+// needed for QMake sources to compile
+QString project_builtin_regx() { return QString();}
+static QString pwd;
+QString qmake_getpwd()
+{
+ if(pwd.isNull())
+ pwd = QDir::currentPath();
+ return pwd;
+}
+bool qmake_setpwd(const QString &p)
+{
+ if(QDir::setCurrent(p)) {
+ pwd = QDir::currentPath();
+ return true;
+ }
+ return false;
+}
+
+namespace TestConfiguration {
+ QString localExecutable;
+ QString localQtConf;
+ QString remoteTestPath;
+ QString remoteLibraryPath;
+ QString remoteExecutable;
+ QString remoteResultFile;
+
+ bool testDebug;
+ void init()
+ {
+ testDebug = true;
+ localQtConf = QLatin1String("no");
+ remoteTestPath = QLatin1String("\\Program Files\\qt_test");
+ remoteLibraryPath = remoteTestPath;
+ remoteResultFile = QLatin1String("\\qt_test_results.txt");
+ }
+}
+
+void usage()
+{
+ cout <<
+ "QTestLib options\n"
+ " -functions : Returns a list of current testfunctions\n"
+ " -xml : Outputs results as XML document\n"
+ " -lightxml : Outputs results as stream of XML tags\n"
+ " -o filename: Writes all output into a file\n"
+ " -silent : Only outputs warnings and failures\n"
+ " -v1 : Print enter messages for each testfunction\n"
+ " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n"
+ " -vs : Print every signal emitted\n"
+ " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
+ " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
+ " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
+ " -keyevent-verbose : Turn on verbose messages for keyboard simulation\n"
+ " -maxwarnings n : Sets the maximum amount of messages to output.\n"
+ " 0 means unlimited, default: 2000\n"
+ " -help : This help\n";
+ cout <<
+ "cetest specific options\n"
+ " -debug : Test debug version[default]\n"
+ " -release : Test release version\n"
+ " -libpath <path> : Remote path to deploy Qt libraries to\n"
+ " -reset : Reset device before starting a test\n"
+ " -awake : Device does not go sleep mode\n"
+ " -qt-delete : Delete the Qt libraries after execution\n"
+ " -project-delete : Delete the project file(s) after execution\n"
+ " -delete : Delete everything deployed after execution\n"
+ " -conf : Specify location of qt.conf file\n"
+ " -f <file> : Specify project file\n"
+ " -cache <file> : Specify .qmake.cache file to use\n"
+ " -d : Increase qmake debugging \n"
+ " -timeout <value> : Specify a timeout value after which the test will be terminated\n"
+ " -1 specifies waiting forever (default)\n"
+ " 0 specifies starting the process detached\n"
+ " >0 wait <value> seconds\n"
+ "\n";
+}
+
+int main(int argc, char **argv)
+{
+ QStringList arguments;
+ for (int i=0; i<argc; ++i)
+ arguments.append(QString::fromLatin1(argv[i]));
+
+ TestConfiguration::init();
+
+ QStringList launchArguments;
+ QString resultFile;
+ QString proFile;
+ QString cacheFile;
+ int timeout = -1;
+ bool cleanupQt = false;
+ bool cleanupProject = false;
+ bool deviceReset = false;
+ bool keepAwake = false;
+
+ for (int i=1; i<arguments.size(); ++i) {
+ if (arguments.at(i).toLower() == QLatin1String("-help")
+ || arguments.at(i).toLower() == QLatin1String("--help")
+ || arguments.at(i).toLower() == QLatin1String("/?")) {
+ usage();
+ return 0;
+ } else if (arguments.at(i).toLower() == QLatin1String("-o")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No output file specified!" << endl;
+ return -1;
+ }
+ resultFile = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-eventdelay")
+ || arguments.at(i).toLower() == QLatin1String("-keydelay")
+ || arguments.at(i).toLower() == QLatin1String("-mousedelay")
+ || arguments.at(i).toLower() == QLatin1String("-maxwarnings")) {
+ launchArguments.append(arguments.at(i++));
+ if (i == arguments.size()) {
+ cout << "Please specify value for:" << qPrintable(arguments.at(i-1).mid(1)) << endl;
+ return -1;
+ }
+ launchArguments.append(arguments.at(i));
+ } else if (arguments.at(i).toLower() == QLatin1String("-debug")) {
+ TestConfiguration::testDebug = true;
+ Option::before_user_vars.append("CONFIG-=release");
+ Option::before_user_vars.append("CONFIG+=debug");
+ } else if (arguments.at(i).toLower() == QLatin1String("-release")) {
+ TestConfiguration::testDebug = false;
+ Option::before_user_vars.append("CONFIG-=debug");
+ Option::before_user_vars.append("CONFIG+=release");
+ } else if (arguments.at(i).toLower() == QLatin1String("-libpath")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No library path specified!" << endl;
+ return -1;
+ }
+ TestConfiguration::remoteLibraryPath = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-qt-delete")) {
+ cleanupQt = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-project-delete")) {
+ cleanupProject = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-delete")) {
+ cleanupQt = true;
+ cleanupProject = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-reset")) {
+ deviceReset = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-awake")) {
+ keepAwake = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-conf")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No qt.conf file specified!" << endl;
+ return -1;
+ }
+ if (!QFileInfo(arguments.at(i)).exists())
+ cout << "Warning: could not find qt.conf file at:" << qPrintable(arguments.at(i)) << endl;
+ else
+ TestConfiguration::localQtConf = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-f")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No output file specified!" << endl;
+ return -1;
+ }
+ proFile = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-cache")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No cache file specified!" << endl;
+ return -1;
+ }
+ cacheFile = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-d")) {
+ Option::debug_level++;
+ } else if (arguments.at(i).toLower() == QLatin1String("-timeout")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No timeout value specified!" << endl;
+ return -1;
+ }
+ timeout = QString(arguments.at(i)).toInt();
+ } else {
+ launchArguments.append(arguments.at(i));
+ }
+ }
+
+ // check for .pro file
+ if (proFile.isEmpty()) {
+ proFile = QDir::current().dirName() + QLatin1String(".pro");
+ if (!QFileInfo(proFile).exists()) {
+ cout << "Error: Could not find project file in current directory." << endl;
+ return -1;
+ }
+ debugOutput(QString::fromLatin1("Using Project File:").append(proFile),1);
+ }else {
+ if (!QFileInfo(proFile).exists()) {
+ cout << "Error: Project file does not exist " << qPrintable(proFile) << endl;
+ return -1;
+ }
+ }
+
+ Option::before_user_vars.append("CONFIG+=build_pass");
+
+ // read target and deployment rules passing the .pro to use instead of
+ // relying on qmake guessing the .pro to use
+ int qmakeArgc = 2;
+ QByteArray ba(QFile::encodeName(proFile));
+ char* proFileEncodedName = ba.data();
+ char* qmakeArgv[2] = { "qmake.exe", proFileEncodedName };
+
+ Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
+ Option::output_dir = qmake_getpwd();
+ if (!cacheFile.isEmpty())
+ Option::mkfile::cachefile = cacheFile;
+ int ret = Option::init(qmakeArgc, qmakeArgv);
+ if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
+ cout << "Error: could not parse " << qPrintable(proFile) << endl;
+ return -1;
+ }
+
+ QMakeProperty prop;
+ QMakeProject project(&prop);
+
+ project.read(proFile);
+ if (project.values("TEMPLATE").join(" ").toLower() != QString("app")) {
+ cout << "Error: Can only test executables!" << endl;
+ return -1;
+ }
+ // Check whether the project is still in debug/release mode after reading
+ // If .pro specifies to be one mode only, we need to accept this
+ if (project.isActiveConfig("debug") && !project.isActiveConfig("release")) {
+ TestConfiguration::testDebug = true;
+ debugOutput("ActiveConfig: debug only in .pro.", 1);
+ }
+ if (!project.isActiveConfig("debug") && project.isActiveConfig("release")) {
+ TestConfiguration::testDebug = false;
+ debugOutput("ActiveConfig: release only in .pro.", 1);
+ }
+
+ // determine what is the real mkspec to use if the default mkspec is being used
+ if (Option::mkfile::qmakespec.endsWith("/default"))
+ project.values("QMAKESPEC") = project.values("QMAKESPEC_ORIGINAL");
+ else
+ project.values("QMAKESPEC") = QStringList() << Option::mkfile::qmakespec;
+
+ // ensure that QMAKESPEC is non-empty .. to meet requirements of QList::at()
+ if (project.values("QMAKESPEC").isEmpty()){
+ cout << "Error: QMAKESPEC not set after parsing " << qPrintable(proFile) << endl;
+ return -1;
+ }
+
+ // ensure that QT_CE_C_RUNTIME is non-empty .. to meet requirements of QList::at()
+ if (project.values("QT_CE_C_RUNTIME").isEmpty()){
+ cout << "Error: QT_CE_C_RUNTIME not defined in mkspec/qconfig.pri " << qPrintable(project.values("QMAKESPEC").join(" "));
+ return -1;
+ }
+
+ QString destDir = project.values("DESTDIR").join(" ");
+ if (!destDir.isEmpty()) {
+ if (QDir::isRelativePath(destDir)) {
+ QFileInfo fi(proFile);
+ if (destDir == QLatin1String("."))
+ destDir = fi.absolutePath() + "/" + destDir + "/" + (TestConfiguration::testDebug ? "debug" : "release");
+ else
+ destDir = fi.absolutePath() + QDir::separator() + destDir;
+ }
+ } else {
+ QFileInfo fi(proFile);
+ destDir = fi.absolutePath();
+ destDir += QDir::separator() + QLatin1String(TestConfiguration::testDebug ? "debug" : "release");
+ }
+
+ DeploymentList qtDeploymentList;
+ DeploymentList projectDeploymentList;
+
+ TestConfiguration::localExecutable = Option::fixPathToLocalOS(destDir + QDir::separator() + project.values("TARGET").join(" ") + QLatin1String(".exe"));
+ TestConfiguration::remoteTestPath = QLatin1String("\\Program Files\\") + Option::fixPathToLocalOS(project.values("TARGET").join(QLatin1String(" ")));
+ if (!arguments.contains(QLatin1String("-libpath"), Qt::CaseInsensitive))
+ TestConfiguration::remoteLibraryPath = TestConfiguration::remoteTestPath;
+
+ QString targetExecutable = Option::fixPathToLocalOS(project.values("TARGET").join(QLatin1String(" ")));
+ int last = targetExecutable.lastIndexOf(QLatin1Char('\\'));
+ targetExecutable = targetExecutable.mid( last == -1 ? 0 : last+1 );
+ TestConfiguration::remoteExecutable = TestConfiguration::remoteTestPath + QDir::separator() + targetExecutable + QLatin1String(".exe");
+ projectDeploymentList.append(CopyItem(TestConfiguration::localExecutable , TestConfiguration::remoteExecutable));
+
+ // deploy
+#ifdef QT_CETEST_NO_ACTIVESYNC
+ CeTcpSyncConnection connection;
+#else
+ ActiveSyncConnection connection;
+#endif
+ if (!connection.connect()) {
+ cout << "Error: Could not connect to device!" << endl;
+ return -1;
+ }
+ DeploymentHandler deployment;
+ deployment.setConnection(&connection);
+
+ deployment.initQtDeploy(&project, qtDeploymentList, TestConfiguration::remoteLibraryPath);
+ deployment.initProjectDeploy(&project , projectDeploymentList, TestConfiguration::remoteTestPath);
+
+ // add qt.conf
+ if (TestConfiguration::localQtConf != QLatin1String("no")) {
+ QString qtConfOrigin = QFileInfo(TestConfiguration::localQtConf).absoluteFilePath();
+ QString qtConfTarget = Option::fixPathToLocalOS(TestConfiguration::remoteTestPath + QDir::separator() + QLatin1String("qt.conf"));
+ projectDeploymentList.append(CopyItem(qtConfOrigin, qtConfTarget));
+ }
+
+ if (!deployment.deviceDeploy(qtDeploymentList) || !deployment.deviceDeploy(projectDeploymentList)) {
+ cout << "Error: Could not copy file(s) to device" << endl;
+ return -1;
+ }
+ // device power mode
+ if (keepAwake)
+ {
+ int retVal = 0;
+ if (!connection.setDeviceAwake(true, &retVal)) {
+ cout << "Error: Could not set unattended mode on device" << endl;
+ return -1;
+ }
+ }
+
+ // reset device
+ if (deviceReset)
+ {
+ if (!connection.resetDevice()) {
+ //if (!connection.toggleDevicePower( &retVal)) {
+ cout << "Error: Could not reset the device" << endl;
+ return -1;
+ }
+ cout << " Entering sleep after reset for " << SLEEP_AFTER_RESET / 1000 << " seconds ... " << endl;
+ Sleep(SLEEP_AFTER_RESET);
+ cout << " ... woke up. " << endl;
+ connection.disconnect();
+ // reconnect after reset
+ int retryCount = 21;
+ while (--retryCount)
+ {
+ if (!connection.connect())
+ Sleep(SLEEP_RECONNECT);
+ else
+ break;
+ }
+ if (!connection.isConnected())
+ {
+ cout << "Error: Could not connect to device!" << endl;
+ return -1;
+ }
+ }
+
+ // launch
+ launchArguments.append("-o");
+ launchArguments.append(TestConfiguration::remoteResultFile);
+
+ cout << endl << "Remote Launch:" << qPrintable(TestConfiguration::remoteExecutable) << " " << qPrintable(launchArguments.join(" ")) << endl;
+ if (!connection.execute(TestConfiguration::remoteExecutable, launchArguments.join(" "), timeout)) {
+ cout << "Error: Could not execute target file" << endl;
+ return -1;
+ }
+
+
+ // copy result file
+ // show results
+ if (resultFile.isEmpty()) {
+ QString tempResultFile = Option::fixPathToLocalOS(QDir::tempPath() + "/qt_ce_temp_result_file.txt");
+ if (connection.copyFileFromDevice(TestConfiguration::remoteResultFile, tempResultFile)) {
+ QFile file(tempResultFile);
+ QByteArray arr;
+ if (file.open(QIODevice::ReadOnly)) {
+ arr = file.readAll();
+ cout << arr.constData() << endl;
+ }
+ file.close();
+ file.remove();
+ }
+ } else {
+ connection.copyFileFromDevice(TestConfiguration::remoteResultFile, resultFile);
+ }
+
+ // delete
+ connection.deleteFile(TestConfiguration::remoteResultFile);
+ if (cleanupQt)
+ deployment.cleanup(qtDeploymentList);
+ if (cleanupProject)
+ deployment.cleanup(projectDeploymentList);
+ return 0;
+}
diff --git a/src/qtestlib/wince/cetest/qmake_include.pri b/src/qtestlib/wince/cetest/qmake_include.pri
new file mode 100644
index 000000000..35fbc64a6
--- /dev/null
+++ b/src/qtestlib/wince/cetest/qmake_include.pri
@@ -0,0 +1,13 @@
+#qmake source files needed for cetest
+HEADERS += \
+ $$QT_SOURCE_TREE/qmake/option.h
+SOURCES += \
+ $$QT_SOURCE_TREE/qmake/option.cpp \
+ $$QT_SOURCE_TREE/qmake/project.cpp \
+ $$QT_SOURCE_TREE/qmake/property.cpp \
+ $$QT_SOURCE_TREE/qmake/generators/metamakefile.cpp \
+ $$QT_SOURCE_TREE/qmake/generators/symbian/initprojectdeploy_symbian.cpp \
+ $$QT_SOURCE_TREE/tools/shared/symbian/epocroot.cpp \
+ $$QT_SOURCE_TREE/tools/shared/windows/registry.cpp
+
+DEFINES += QT_QMAKE_PARSER_ONLY
diff --git a/src/qtestlib/wince/cetest/remoteconnection.cpp b/src/qtestlib/wince/cetest/remoteconnection.cpp
new file mode 100644
index 000000000..aa3059cd3
--- /dev/null
+++ b/src/qtestlib/wince/cetest/remoteconnection.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "remoteconnection.h"
+
+QByteArray strwinerror(DWORD errorcode)
+{
+ QByteArray out(512, 0);
+
+ DWORD ok = FormatMessageA(
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ errorcode,
+ 0,
+ out.data(),
+ out.size(),
+ 0
+ );
+
+ if (!ok) {
+ qsnprintf(out.data(), out.size(),
+ "(error %d; additionally, error %d while looking up error string)",
+ (int)errorcode, (int)GetLastError());
+ }
+ else {
+ out.resize(qstrlen(out.constData()));
+ if (out.endsWith("\r\n"))
+ out.chop(2);
+
+ /* Append error number to error message for good measure */
+ out.append(" (0x");
+ out.append(QByteArray::number(uint(errorcode), 16).rightJustified(8, '0'));
+ out.append(")");
+ }
+ return out;
+}
+
+AbstractRemoteConnection::AbstractRemoteConnection()
+{
+}
+
+AbstractRemoteConnection::~AbstractRemoteConnection()
+{
+}
+
+
+// Slow but should be ok...
+bool AbstractRemoteConnection::moveFile(const QString &src, const QString &dest, bool FailIfExists)
+{
+ bool result = copyFile(src, dest, FailIfExists);
+ deleteFile(src);
+ return result;
+}
+
+// Slow but should be ok...
+bool AbstractRemoteConnection::moveDirectory(const QString &src, const QString &dest, bool recursive)
+{
+ bool result = copyDirectory(src, dest, true);
+ deleteDirectory(src, recursive);
+ return result;
+}
+
diff --git a/src/qtestlib/wince/cetest/remoteconnection.h b/src/qtestlib/wince/cetest/remoteconnection.h
new file mode 100644
index 000000000..d2671397d
--- /dev/null
+++ b/src/qtestlib/wince/cetest/remoteconnection.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REMOTECONNECTION_H
+#define REMOTECONNECTION_H
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <windows.h>
+class AbstractRemoteConnection
+{
+public:
+ AbstractRemoteConnection();
+ virtual ~AbstractRemoteConnection();
+
+ virtual bool connect(QVariantList&) = 0;
+ virtual void disconnect() = 0;
+ virtual bool isConnected() const = 0;
+
+ // These functions are designed for transfer between desktop and device
+ // Caution: deviceDest path has to be device specific (eg. no drive letters for CE)
+ virtual bool copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists = false) = 0;
+ virtual bool copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive = true) = 0;
+ virtual bool copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists = false) = 0;
+ virtual bool copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive = true) = 0;
+
+ // For "intelligent deployment" we need to investigate on filetimes on the device
+ virtual bool timeStampForLocalFileTime(FILETIME*) const = 0;
+ virtual bool fileCreationTime(const QString &fileName, FILETIME*) const = 0;
+
+ // These functions only work on files existing on the device
+ virtual bool copyFile(const QString&, const QString&, bool failIfExists = false) = 0;
+ virtual bool copyDirectory(const QString&, const QString&, bool recursive = true) = 0;
+ virtual bool deleteFile(const QString&) = 0;
+ virtual bool deleteDirectory(const QString&, bool recursive = true, bool failIfContentExists = false) = 0;
+ bool moveFile(const QString&, const QString&, bool FailIfExists = false);
+ bool moveDirectory(const QString&, const QString&, bool recursive = true);
+
+ virtual bool createDirectory(const QString&, bool deleteBefore=false) = 0;
+
+ virtual bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL) = 0;
+};
+
+QByteArray strwinerror(DWORD);
+
+#endif
diff --git a/src/qtestlib/wince/remotelib/commands.cpp b/src/qtestlib/wince/remotelib/commands.cpp
new file mode 100644
index 000000000..32d6e33ae
--- /dev/null
+++ b/src/qtestlib/wince/remotelib/commands.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "commands.h"
+#include <Pm.h>
+#include <Pmpolicy.h>
+
+
+#define CLEAN_FAIL(a) {delete appName; \
+ delete arguments; \
+ return (a); }
+
+int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream)
+{
+ if (!stream)
+ return -1;
+
+ DWORD bytesRead;
+ int appLength;
+ wchar_t* appName = 0;
+ int argumentsLength;
+ wchar_t* arguments = 0;
+ int timeout = -1;
+ int returnValue = -2;
+ DWORD error = 0;
+
+ if (S_OK != stream->Read(&appLength, sizeof(appLength), &bytesRead))
+ CLEAN_FAIL(-2);
+ appName = (wchar_t*) malloc(sizeof(wchar_t)*(appLength + 1));
+ if (S_OK != stream->Read(appName, sizeof(wchar_t)*appLength, &bytesRead))
+ CLEAN_FAIL(-2);
+ appName[appLength] = '\0';
+
+ if (S_OK != stream->Read(&argumentsLength, sizeof(argumentsLength), &bytesRead))
+ CLEAN_FAIL(-2);
+ arguments = (wchar_t*) malloc(sizeof(wchar_t)*(argumentsLength + 1));
+ if (S_OK != stream->Read(arguments, sizeof(wchar_t)*argumentsLength, &bytesRead))
+ CLEAN_FAIL(-2);
+ arguments[argumentsLength] = '\0';
+
+ if (S_OK != stream->Read(&timeout, sizeof(timeout), &bytesRead))
+ CLEAN_FAIL(-2);
+
+ bool result = qRemoteExecute(appName, arguments, &returnValue, &error, timeout);
+
+ if (timeout != 0) {
+ if (S_OK != stream->Write(&returnValue, sizeof(returnValue), &bytesRead))
+ CLEAN_FAIL(-4);
+ if (S_OK != stream->Write(&error, sizeof(error), &bytesRead))
+ CLEAN_FAIL(-5);
+ }
+ delete appName;
+ delete arguments;
+ // We need to fail here for the execute, otherwise the calling application will wait
+ // forever for the returnValue.
+ if (!result)
+ return -3;
+ return S_OK;
+}
+
+
+bool qRemoteExecute(const wchar_t* program, const wchar_t* arguments, int *returnValue, DWORD* error, int timeout)
+{
+ *error = 0;
+
+ if (!program)
+ return false;
+
+ PROCESS_INFORMATION pid;
+ if (!CreateProcess(program, arguments, NULL, NULL, false, 0, NULL, NULL, NULL, &pid)) {
+ *error = GetLastError();
+ wprintf(L"Could not launch: %s\n", program);
+ return false;
+ }
+
+ // Timeout is in seconds
+ DWORD waitingTime = (timeout == -1) ? INFINITE : timeout * 1000;
+
+ if (waitingTime != 0) {
+ DWORD waitStatus = WaitForSingleObject(pid.hProcess, waitingTime);
+ if (waitStatus == WAIT_TIMEOUT) {
+ TerminateProcess(pid.hProcess, 2);
+ return false;
+ } else if (waitStatus == WAIT_OBJECT_0 && returnValue) {
+ *returnValue = 0;
+ DWORD exitCode;
+ if (GetExitCodeProcess(pid.hProcess, &exitCode))
+ *returnValue = exitCode;
+ }
+ }
+ return true;
+}
+/**
+\brief Reset the device.
+*/
+int qRemoteSoftReset(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream)
+{
+ //POWER_STATE_ON On state
+ //POWER_STATE_OFF Off state
+ //POWER_STATE_CRITICAL Critical state
+ //POWER_STATE_BOOT Boot state
+ //POWER_STATE_IDLE Idle state
+ //POWER_STATE_SUSPEND Suspend state
+ //POWER_STATE_RESET Reset state
+
+ DWORD returnValue = SetSystemPowerState(0, POWER_STATE_RESET, POWER_FORCE);
+ return returnValue;
+}
+
+/**
+\brief Toggle the unattended powermode of the device
+*/
+int qRemoteToggleUnattendedPowerMode(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream)
+{
+ if (!stream)
+ return -1;
+
+ DWORD bytesRead;
+ int toggleVal = 0;
+ int returnValue = S_OK;
+
+ if (S_OK != stream->Read(&toggleVal, sizeof(toggleVal), &bytesRead))
+ return -2;
+
+ //PPN_REEVALUATESTATE 0x0001 Reserved. Set dwData to zero (0).
+ //PPN_POWERCHANGE 0x0002 Reserved. Set dwData to zero (0).
+ //PPN_UNATTENDEDMODE 0x0003 Set dwData to TRUE or FALSE.
+ //PPN_SUSPENDKEYPRESSED or
+ //PPN_POWERBUTTONPRESSED 0x0004 Reserved. Set dwData to zero (0).
+ //PPN_SUSPENDKEYRELEASED 0x0005 Reserved. Set dwData to zero (0).
+ //PPN_APPBUTTONPRESSED 0x0006 Reserved. Set dwData to zero (0).
+ //PPN_OEMBASE Greater than or equal to 0x10000
+ //You can define higher values, such as 0x10001, 0x10002, and so on.
+ // Reserved. Set dwData to zero (0).
+ returnValue = PowerPolicyNotify(PPN_UNATTENDEDMODE, toggleVal);
+
+ if (S_OK != stream->Write(&returnValue, sizeof(returnValue), &bytesRead))
+ return -3;
+ else
+ return S_OK;
+}
+
+/**
+\brief Virtually press the power button of the device
+*/
+int qRemotePowerButton(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream)
+{
+ if (!stream)
+ return -1;
+
+ DWORD bytesRead;
+ int toggleVal = 0;
+ int returnValue = S_OK;
+
+ if (S_OK != stream->Read(&toggleVal, sizeof(toggleVal), &bytesRead))
+ return -2;
+
+ //PPN_REEVALUATESTATE 0x0001 Reserved. Set dwData to zero (0).
+ //PPN_POWERCHANGE 0x0002 Reserved. Set dwData to zero (0).
+ //PPN_UNATTENDEDMODE 0x0003 Set dwData to TRUE or FALSE.
+ //PPN_SUSPENDKEYPRESSED or
+ //PPN_POWERBUTTONPRESSED 0x0004 Reserved. Set dwData to zero (0).
+ //PPN_SUSPENDKEYRELEASED 0x0005 Reserved. Set dwData to zero (0).
+ //PPN_APPBUTTONPRESSED 0x0006 Reserved. Set dwData to zero (0).
+ //PPN_OEMBASE Greater than or equal to 0x10000
+ //You can define higher values, such as 0x10001, 0x10002, and so on.
+ // Reserved. Set dwData to zero (0).
+ returnValue = PowerPolicyNotify(PPN_POWERBUTTONPRESSED, 0);
+
+ if (S_OK != stream->Write(&returnValue, sizeof(returnValue), &bytesRead))
+ return -3;
+ else
+ return S_OK;
+}
+
diff --git a/src/qtestlib/wince/remotelib/commands.h b/src/qtestlib/wince/remotelib/commands.h
new file mode 100644
index 000000000..959aed625
--- /dev/null
+++ b/src/qtestlib/wince/remotelib/commands.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QREMOTECOMMANDS_H
+#define QREMOTECOMMANDS_H
+#include <winbase.h>
+#include <rapi.h>
+
+extern "C" {
+ int __declspec(dllexport) qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream*);
+ int __declspec(dllexport) qRemoteSoftReset(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream);
+ int __declspec(dllexport) qRemoteToggleUnattendedPowerMode(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream);
+ int __declspec(dllexport) qRemotePowerButton(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream);
+ bool __declspec(dllexport) qRemoteExecute(const wchar_t* program, const wchar_t* arguments = NULL, int *returnValue = NULL , DWORD* error = NULL, int timeout = -1);
+}
+
+#endif
diff --git a/src/qtestlib/wince/remotelib/remotelib.pro b/src/qtestlib/wince/remotelib/remotelib.pro
new file mode 100644
index 000000000..dc61c7ffd
--- /dev/null
+++ b/src/qtestlib/wince/remotelib/remotelib.pro
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+CONFIG += dll
+CONFIG -= staticlib
+TARGET = QtRemote
+DESTDIR = ../../../../lib
+DEPENDPATH += .
+INCLUDEPATH += .
+QT =
+# Input
+HEADERS += commands.h
+SOURCES += commands.cpp
+
+INCLUDEPATH += $$QT_CE_RAPI_INC
+LIBS += -L$$QT_CE_RAPI_LIB
+
diff --git a/src/qtestlib/wince/wince.pro b/src/qtestlib/wince/wince.pro
new file mode 100644
index 000000000..7c88d6572
--- /dev/null
+++ b/src/qtestlib/wince/wince.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+wince*:SUBDIRS = remotelib \ No newline at end of file