summaryrefslogtreecommitdiff
path: root/src/qtestlib/wince/cetest
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/cetest
downloadqttools-50123887ba0f33cf47520bee7c419d68742af2d1.tar.gz
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/cetest')
-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
12 files changed, 2146 insertions, 0 deletions
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