summaryrefslogtreecommitdiffstats
path: root/tools/qtestlib
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:34:13 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:34:13 +0100
commit67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch)
tree1dbf50b3dff8d5ca7e9344733968c72704eb15ff /tools/qtestlib
Long live Qt!
Diffstat (limited to 'tools/qtestlib')
-rw-r--r--tools/qtestlib/qtestlib.pro4
-rw-r--r--tools/qtestlib/updater/main.cpp178
-rw-r--r--tools/qtestlib/updater/updater.pro10
-rw-r--r--tools/qtestlib/wince/cetest/activesyncconnection.cpp485
-rw-r--r--tools/qtestlib/wince/cetest/activesyncconnection.h86
-rw-r--r--tools/qtestlib/wince/cetest/bootstrapped.pri38
-rw-r--r--tools/qtestlib/wince/cetest/cetest.pro47
-rw-r--r--tools/qtestlib/wince/cetest/deployment.cpp267
-rw-r--r--tools/qtestlib/wince/cetest/deployment.h75
-rw-r--r--tools/qtestlib/wince/cetest/main.cpp351
-rw-r--r--tools/qtestlib/wince/cetest/qmake_include.pri7
-rw-r--r--tools/qtestlib/wince/cetest/remoteconnection.cpp68
-rw-r--r--tools/qtestlib/wince/cetest/remoteconnection.h82
-rw-r--r--tools/qtestlib/wince/remotelib/commands.cpp120
-rw-r--r--tools/qtestlib/wince/remotelib/commands.h51
-rw-r--r--tools/qtestlib/wince/remotelib/remotelib.pro15
-rw-r--r--tools/qtestlib/wince/wince.pro2
17 files changed, 1886 insertions, 0 deletions
diff --git a/tools/qtestlib/qtestlib.pro b/tools/qtestlib/qtestlib.pro
new file mode 100644
index 0000000000..da94e81ec1
--- /dev/null
+++ b/tools/qtestlib/qtestlib.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+!wince*: SUBDIRS += updater
+wince*: contains(QT_CONFIG, cetest): SUBDIRS += wince
+CONFIG += ordered
diff --git a/tools/qtestlib/updater/main.cpp b/tools/qtestlib/updater/main.cpp
new file mode 100644
index 0000000000..38628cffab
--- /dev/null
+++ b/tools/qtestlib/updater/main.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtCore>
+
+#include <stdio.h>
+
+QT_USE_NAMESPACE
+
+static void printHelp(char *argv[])
+{
+ qDebug("Usage: %s [-diff] FILES", argv[0] ? argv[0] : "qtest2to4");
+ qDebug("updates files from QtTestLib 2.x to QTestLib 4.1");
+ qDebug("\noptions:\n -diff Don't write any changes, output differences instead.");
+ exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+ bool printDiff = false;
+ int i = 1;
+
+ if (argc == 1)
+ printHelp(argv);
+ if (argv[1][0] == '-') {
+ if (qstrcmp(argv[1], "-diff") == 0) {
+ printDiff = true;
+ ++i;
+ } else {
+ qDebug("Unknown option: %s\n", argv[1]);
+ printHelp(argv);
+ }
+ }
+
+ QRegExp dataHeaderRx(QLatin1String("_data(\\s*)\\((\\s*)QtTestTable\\s*\\&\\s*\\w*\\s*\\)"));
+ QRegExp defElemRx(QLatin1String("\\w+\\.defineElement\\s*\\(\\s*\"(.+)\"\\s*,\\s*\"(.+)\"\\s*\\)"));
+ defElemRx.setMinimal(true);
+ QRegExp addDataRx(QLatin1String("\\*\\w+\\.newData(\\s*)(\\(\\s*\".*\"\\s*\\))"));
+ addDataRx.setMinimal(true);
+ QRegExp nsRx(QLatin1String("namespace(\\s+)QtTest"));
+ QRegExp callRx(QLatin1String("QtTest(\\s*)::"));
+
+ enum { MacroCount = 11 };
+ static const char *macroNames[MacroCount] = {
+ "VERIFY", "FAIL", "VERIFY2", "COMPARE", "SKIP", "VERIFY_EVENT",
+ "EXPECT_FAIL", "FETCH", "FETCH_GLOBAL", "TEST", "WARN"
+ };
+
+ for (; i < argc; ++i) {
+ QFile f(QString::fromLocal8Bit(argv[i]));
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ qFatal("Unable to open file '%s' for reading: %s", argv[i], qPrintable(f.errorString()));
+
+ if (printDiff)
+ printf("diff %s\n", argv[i]);
+
+ QStringList contents;
+ int lineNumber = 0;
+ int changedLines = 0;
+ while (!f.atEnd()) {
+ QString origLine = QString::fromLatin1(f.readLine());
+ QString line = origLine;
+ ++lineNumber;
+
+ if (dataHeaderRx.indexIn(line) != -1) {
+ QString ws = dataHeaderRx.cap(1);
+ line.replace(dataHeaderRx, QString::fromLatin1("_data%1()").arg(ws));
+ }
+ if (defElemRx.indexIn(line) != -1) {
+ QString type = defElemRx.cap(1);
+ QString name = defElemRx.cap(2);
+ if (type.endsWith(QLatin1Char('>')))
+ type.append(QLatin1Char(' '));
+ line.replace(defElemRx, QString::fromLatin1("QTest::addColumn<%1>(\"%2\")").arg(
+ type).arg(name));
+ }
+ if (addDataRx.indexIn(line) != -1) {
+ QString repl = QLatin1String("QTest::newRow");
+ repl += addDataRx.cap(1);
+ repl += addDataRx.cap(2);
+ line.replace(addDataRx, repl);
+ }
+ if (nsRx.indexIn(line) != -1)
+ line.replace(nsRx, QString::fromLatin1("namespace%1QTest").arg(nsRx.cap(1)));
+ int pos = 0;
+ while ((pos = callRx.indexIn(line, pos)) != -1) {
+ line.replace(callRx, QString::fromLatin1("QTest%1::").arg(callRx.cap(1)));
+ pos += callRx.matchedLength();
+ }
+
+ line.replace(QLatin1String("QTTEST_MAIN"), QLatin1String("QTEST_MAIN"));
+ line.replace(QLatin1String("QTTEST_APPLESS_MAIN"), QLatin1String("QTEST_APPLESS_MAIN"));
+ line.replace(QLatin1String("QTTEST_NOOP_MAIN"), QLatin1String("QTEST_NOOP_MAIN"));
+ line.replace(QLatin1String("QtTestEventLoop"), QLatin1String("QTestEventLoop"));
+ line.replace(QLatin1String("QtTestEventList"), QLatin1String("QTestEventList"));
+ line.replace(QLatin1String("QtTestAccessibility"), QLatin1String("QTestAccessibility"));
+ line.replace(QLatin1String("QTest::sleep"), QLatin1String("QTest::qSleep"));
+ line.replace(QLatin1String("QTest::wait"), QLatin1String("QTest::qWait"));
+
+ for (int m = 0; m < MacroCount; ++m) {
+ QRegExp macroRe(QString::fromLatin1("\\b%1(\\s*\\()").arg(
+ QLatin1String(macroNames[m])));
+ QString newMacroName = QLatin1Char('Q') + QString::fromLatin1(macroNames[m]);
+ int pos = 0;
+ while ((pos = macroRe.indexIn(line)) != -1) {
+ line.replace(macroRe, newMacroName + macroRe.cap(1));
+ pos += macroRe.matchedLength();
+ }
+ }
+
+ if (line != origLine) {
+ if (printDiff) {
+ printf("%dc%d\n", lineNumber, lineNumber);
+ printf("<%s", qPrintable(origLine));
+ printf("---\n");
+ printf(">%s", qPrintable(line));
+ }
+ ++changedLines;
+ }
+
+ contents.append(line);
+ }
+ f.close();
+
+ if (printDiff)
+ continue;
+ qDebug("%s: %d change%s made.", argv[i], changedLines, changedLines == 1 ? "" : "s");
+ if (!changedLines)
+ continue;
+
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
+ qFatal("Unable to open file '%s' for writing: %s", argv[i], qPrintable(f.errorString()));
+ foreach (QString s, contents)
+ f.write(s.toLatin1());
+ f.close();
+ }
+
+ return 0;
+}
+
diff --git a/tools/qtestlib/updater/updater.pro b/tools/qtestlib/updater/updater.pro
new file mode 100644
index 0000000000..42e1b74bdf
--- /dev/null
+++ b/tools/qtestlib/updater/updater.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET +=
+DEPENDPATH += .
+INCLUDEPATH += .
+
+SOURCES += main.cpp
+
+QT = core
+
+DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp
new file mode 100644
index 0000000000..fc0e7b43b2
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp
@@ -0,0 +1,485 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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;
+ }
+ }
+ return false;
+ }
+
+ deleteFile(deviceDest);
+ HANDLE deviceHandle = CeCreateFile(deviceDest.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (deviceHandle == INVALID_HANDLE_VALUE) {
+ debugOutput(QString::fromLatin1(" Could not create target file"), 2);
+ 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)) {
+ debugOutput(QString::fromLatin1(" Could not write File"), 2);
+ 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 occured 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::fromUtf16(data.cFileName);
+ QString destFile = localDest + "\\" + QString::fromUtf16(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::fromUtf16(data.cFileName);
+ QString destFile = destDirectory + "\\" + QString::fromUtf16(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::fromUtf16(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;
+ HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0);
+ if (S_OK != res) {
+ if (S_OK != CeGetLastError())
+ debugOutput(QString::fromLatin1("Error: Could not invoke method on QtRemote"),1);
+ else
+ debugOutput(QString::fromLatin1("Error: QtRemote return unexpectedly with error Code %1").arg(res), 1);
+ } 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");
+ }
+ 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::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/tools/qtestlib/wince/cetest/activesyncconnection.h b/tools/qtestlib/wince/cetest/activesyncconnection.h
new file mode 100644
index 0000000000..44ff356b6f
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/activesyncconnection.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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);
+private:
+ bool connected;
+};
+
+#endif
diff --git a/tools/qtestlib/wince/cetest/bootstrapped.pri b/tools/qtestlib/wince/cetest/bootstrapped.pri
new file mode 100644
index 0000000000..39f24c2577
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/bootstrapped.pri
@@ -0,0 +1,38 @@
+# 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/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/qfsfileengine_iterator_win.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/qlistdata.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
diff --git a/tools/qtestlib/wince/cetest/cetest.pro b/tools/qtestlib/wince/cetest/cetest.pro
new file mode 100644
index 0000000000..d66fa33182
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/cetest.pro
@@ -0,0 +1,47 @@
+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_BUILD_TREE/include \
+ $$QT_BUILD_TREE/include/QtCore \
+ $$QT_BUILD_TREE/include/QtScript \
+ $$QT_BUILD_TREE/src/corelib/global
+
+DEPENDPATH += $$QT_BUILD_TREE/src/corelib/tools $$QT_BUILD_TREE/src/corelib/io
+
+# Input
+HEADERS += \
+ remoteconnection.h \
+ activesyncconnection.h \
+ deployment.h
+
+SOURCES += \
+ remoteconnection.cpp \
+ activesyncconnection.cpp \
+ deployment.cpp \
+ main.cpp
+
+win32-msvc*:LIBS += ole32.lib advapi32.lib rapi.lib
+
+include(qmake_include.pri)
+include(bootstrapped.pri)
+include($$QT_SOURCE_TREE/src/script/script.pri)
+
+INCLUDEPATH += $$QT_CE_RAPI_INC
+LIBS += -L$$QT_CE_RAPI_LIB
diff --git a/tools/qtestlib/wince/cetest/deployment.cpp b/tools/qtestlib/wince/cetest/deployment.cpp
new file mode 100644
index 0000000000..99ea532161
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/deployment.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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;
+ foreach (QString item, libs) {
+ if (item.startsWith("-lQt")) {
+ qtLibs += project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + item.mid(2) + QLatin1String("4.dll");
+ } else {
+ QFileInfo info(item);
+ if (info.exists() && info.isAbsolute() && info.fileName().startsWith(QLatin1String("Qt")))
+ qtLibs += info.dir().absoluteFilePath(info.fileName().replace(QLatin1String(".lib"), QLatin1String(".dll")));
+ }
+ }
+ 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())));
+ }
+ }
+
+ // 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);
+ }
+
+ // 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(".sources");
+ QString argPath = list.at(it) + QString(".path");
+ if ((project->values(argSource).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);
+ 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(".sources = \"") + 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(".sources = \"") + 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/tools/qtestlib/wince/cetest/deployment.h b/tools/qtestlib/wince/cetest/deployment.h
new file mode 100644
index 0000000000..aa994ef6a9
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/deployment.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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/tools/qtestlib/wince/cetest/main.cpp b/tools/qtestlib/wince/cetest/main.cpp
new file mode 100644
index 0000000000..17f681070e
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/main.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "activesyncconnection.h"
+#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"
+ " -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"
+ " -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;
+
+ 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("-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("-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);
+ }
+
+ // read target and deployment rules
+ int qmakeArgc = 1;
+ char* qmakeArgv[] = { "qmake.exe" };
+ 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 wether 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"))
+ TestConfiguration::testDebug = true;
+ else
+ TestConfiguration::testDebug = false;
+
+ 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
+ ActiveSyncConnection connection;
+ 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;
+ }
+
+ // 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;
+ }
+
+
+ // 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/tools/qtestlib/wince/cetest/qmake_include.pri b/tools/qtestlib/wince/cetest/qmake_include.pri
new file mode 100644
index 0000000000..383163419a
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/qmake_include.pri
@@ -0,0 +1,7 @@
+#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
diff --git a/tools/qtestlib/wince/cetest/remoteconnection.cpp b/tools/qtestlib/wince/cetest/remoteconnection.cpp
new file mode 100644
index 0000000000..7033ed61d1
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/remoteconnection.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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/tools/qtestlib/wince/cetest/remoteconnection.h b/tools/qtestlib/wince/cetest/remoteconnection.h
new file mode 100644
index 0000000000..8e8b3fd9c6
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/remoteconnection.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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/tools/qtestlib/wince/remotelib/commands.cpp b/tools/qtestlib/wince/remotelib/commands.cpp
new file mode 100644
index 0000000000..f6113174db
--- /dev/null
+++ b/tools/qtestlib/wince/remotelib/commands.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "commands.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;
+
+ 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, timeout);
+
+ if (timeout != 0) {
+ if (S_OK != stream->Write(&returnValue, sizeof(returnValue), &bytesRead))
+ CLEAN_FAIL(-4);
+ }
+ 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, int timeout)
+{
+ if (!program)
+ return false;
+
+ PROCESS_INFORMATION pid;
+ if (!CreateProcess(program, arguments, NULL, NULL, false, 0, NULL, NULL, NULL, &pid)) {
+ 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;
+}
diff --git a/tools/qtestlib/wince/remotelib/commands.h b/tools/qtestlib/wince/remotelib/commands.h
new file mode 100644
index 0000000000..80a6f13a99
--- /dev/null
+++ b/tools/qtestlib/wince/remotelib/commands.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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*);
+ bool __declspec(dllexport) qRemoteExecute(const wchar_t* program, const wchar_t* arguments = NULL, int *returnValue = NULL , int timeout = -1);
+}
+
+#endif
diff --git a/tools/qtestlib/wince/remotelib/remotelib.pro b/tools/qtestlib/wince/remotelib/remotelib.pro
new file mode 100644
index 0000000000..dc61c7ffd9
--- /dev/null
+++ b/tools/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/tools/qtestlib/wince/wince.pro b/tools/qtestlib/wince/wince.pro
new file mode 100644
index 0000000000..7c88d6572c
--- /dev/null
+++ b/tools/qtestlib/wince/wince.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+wince*:SUBDIRS = remotelib \ No newline at end of file