summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/scripting-api/packagemanagercore.qdoc7
-rw-r--r--src/libs/installer/elevatedexecuteoperation.cpp85
-rw-r--r--src/libs/installer/elevatedexecuteoperation.h8
-rw-r--r--src/libs/installer/extractarchiveoperation.cpp4
-rw-r--r--src/libs/installer/packagemanagercore.cpp15
-rw-r--r--src/libs/installer/packagemanagercore.h1
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp28
-rw-r--r--src/libs/installer/packagemanagercore_p.h12
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp7
-rw-r--r--src/libs/installer/packagemanagercoredata.h3
-rw-r--r--src/libs/kdtools/updateoperation.h6
-rw-r--r--tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro8
-rw-r--r--tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp67
-rw-r--r--tests/auto/installer/installer.pro3
14 files changed, 202 insertions, 52 deletions
diff --git a/doc/scripting-api/packagemanagercore.qdoc b/doc/scripting-api/packagemanagercore.qdoc
index 8a9d297a0..bacf50f27 100644
--- a/doc/scripting-api/packagemanagercore.qdoc
+++ b/doc/scripting-api/packagemanagercore.qdoc
@@ -728,6 +728,13 @@
*/
/*!
+ \qmlmethod string installer::key(string value)
+
+ Returns the installer key for \a value. If \a value is not known, empty string is
+ returned.
+*/
+
+/*!
\qmlmethod void installer::setValue(string key, string value)
Sets the installer value for \a key to \a value.
diff --git a/src/libs/installer/elevatedexecuteoperation.cpp b/src/libs/installer/elevatedexecuteoperation.cpp
index 39be98e6f..f81377ac4 100644
--- a/src/libs/installer/elevatedexecuteoperation.cpp
+++ b/src/libs/installer/elevatedexecuteoperation.cpp
@@ -61,7 +61,11 @@ private:
public:
void readProcessOutput();
- bool run(const QStringList &arguments);
+ int run(QStringList &arguments, const OperationType type);
+
+private:
+ bool needsRerunWithReplacedVariables(QStringList &arguments, const OperationType type);
+
QProcessWrapper *process;
bool showStandardError;
@@ -100,10 +104,10 @@ bool ElevatedExecuteOperation::performOperation()
PackageManagerCore *const core = packageManager();
args = core->replaceVariables(args);
}
- return d->run(args);
+ return d->run(args, Operation::Perform) ? false : true;
}
-bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
+int ElevatedExecuteOperation::Private::run(QStringList &arguments, const OperationType type)
{
QStringList args = arguments;
QString workingDirectory;
@@ -192,13 +196,17 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
success = process->waitForFinished(-1);
}
- bool returnValue = true;
+ int returnValue = NoError;
if (!success) {
q->setError(UserDefinedError);
//TODO: pass errorString() through the wrapper */
q->setErrorString(tr("Cannot start: \"%1\": %2").arg(callstr,
process->errorString()));
- returnValue = false;
+ if (!needsRerunWithReplacedVariables(arguments, type)) {
+ returnValue = Error;
+ } else {
+ returnValue = NeedsRerun;
+ }
}
if (QThread::currentThread() == qApp->thread()) {
@@ -213,26 +221,29 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
if (process->exitStatus() == QProcessWrapper::CrashExit) {
q->setError(UserDefinedError);
q->setErrorString(tr("Program crashed: \"%1\"").arg(callstr));
- returnValue = false;
+ returnValue = Error;
}
- if (!allowedExitCodes.contains(process->exitCode())) {
- q->setError(UserDefinedError);
- if (customErrorMessage.isEmpty()) {
- q->setErrorString(tr("Execution failed (Unexpected exit code: %1): \"%2\"")
- .arg(QString::number(process->exitCode()), callstr));
+ if (!allowedExitCodes.contains(process->exitCode()) && returnValue != NeedsRerun) {
+ if (!needsRerunWithReplacedVariables(arguments, type)) {
+ q->setError(UserDefinedError);
+ if (customErrorMessage.isEmpty()) {
+ q->setErrorString(tr("Execution failed (Unexpected exit code: %1): \"%2\"")
+ .arg(QString::number(process->exitCode()), callstr));
+ } else {
+ q->setErrorString(customErrorMessage);
+ }
+
+ QByteArray standardErrorOutput = process->readAllStandardError();
+ // in error case it would be useful to see something in verbose output
+ if (!standardErrorOutput.isEmpty())
+ qCWarning(QInstaller::lcInstallerInstallLog).noquote() << standardErrorOutput;
+
+ returnValue = Error;
} else {
- q->setErrorString(customErrorMessage);
+ returnValue = NeedsRerun;
}
-
- QByteArray standardErrorOutput = process->readAllStandardError();
- // in error case it would be useful to see something in verbose output
- if (!standardErrorOutput.isEmpty())
- qCWarning(QInstaller::lcInstallerInstallLog).noquote() << standardErrorOutput;
-
- returnValue = false;
}
-
Q_ASSERT(process);
Q_ASSERT(process->state() == QProcessWrapper::NotRunning);
delete process;
@@ -241,6 +252,28 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
return returnValue;
}
+bool ElevatedExecuteOperation::Private::needsRerunWithReplacedVariables(QStringList &arguments, const OperationType type)
+{
+ if (type != Operation::Undo)
+ return false;
+ bool rerun = false;
+ PackageManagerCore *const core = q->packageManager();
+ for (int i = 0; i < arguments.count(); i++) {
+ QString key = core->key(arguments.at(i));
+ if (!key.isEmpty() && key.endsWith(QLatin1String("_OLD"))) {
+ key.remove(key.length() - 4, 4);
+ if (core->containsValue(key)) {
+ key.prepend(QLatin1String("@"));
+ key.append(QLatin1String("@"));
+ QString value = core->replaceVariables(key);
+ arguments.replace(i, value);
+ rerun = true;
+ }
+ }
+ }
+ return rerun;
+}
+
/*!
Cancels the ElevatedExecuteOperation. This methods tries to terminate the process
gracefully by calling QProcessWrapper::terminate. After 10 seconds, the process gets killed.
@@ -285,7 +318,17 @@ bool ElevatedExecuteOperation::undoOperation()
PackageManagerCore *const core = packageManager();
args = core->replaceVariables(args);
}
- return d->run(args);
+
+ int returnValue = d->run(args, Operation::Undo);
+ if (returnValue == NeedsRerun) {
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote() << QString::fromLatin1("Failed to run "
+ "undo operation \"%1\" for component %2. Trying again with arguments %3").arg(name(),
+ value(QLatin1String("component")).toString(), args.join(QLatin1String(", ")));
+ setError(NoError);
+ setErrorString(QString());
+ returnValue = d->run(args, Operation::Undo);
+ }
+ return returnValue ? false : true;
}
bool ElevatedExecuteOperation::testOperation()
diff --git a/src/libs/installer/elevatedexecuteoperation.h b/src/libs/installer/elevatedexecuteoperation.h
index 5585e77a8..470d3e506 100644
--- a/src/libs/installer/elevatedexecuteoperation.h
+++ b/src/libs/installer/elevatedexecuteoperation.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -38,6 +38,12 @@ class INSTALLER_EXPORT ElevatedExecuteOperation : public QObject, public Operati
Q_OBJECT
public:
+ enum Error {
+ NoError = 0,
+ Error,
+ NeedsRerun
+ };
+
explicit ElevatedExecuteOperation(PackageManagerCore *core);
~ElevatedExecuteOperation();
diff --git a/src/libs/installer/extractarchiveoperation.cpp b/src/libs/installer/extractarchiveoperation.cpp
index 5b13b1f25..c2d541929 100644
--- a/src/libs/installer/extractarchiveoperation.cpp
+++ b/src/libs/installer/extractarchiveoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -163,7 +163,7 @@ bool ExtractArchiveOperation::performOperation()
// TODO: Use backups for rollback, too? Doesn't work for uninstallation though.
// delete all backups we can delete right now, remember the rest
- foreach (const Backup &i, callback.backupFiles())
+ foreach (const QInstaller::Backup &i, callback.backupFiles())
deleteFileNowOrLater(i.second);
if (!receiver.success()) {
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index ed513fb69..7eaae7b33 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -875,7 +875,7 @@ void PackageManagerCore::rollBackInstallation()
operation->setValue(QLatin1String("forceremoval"), false);
}
- PackageManagerCorePrivate::performOperationThreaded(operation, PackageManagerCorePrivate::Undo);
+ PackageManagerCorePrivate::performOperationThreaded(operation, Operation::Undo);
const QString componentName = operation->value(QLatin1String("component")).toString();
if (!componentName.isEmpty()) {
@@ -2963,7 +2963,7 @@ bool PackageManagerCore::performOperation(const QString &name, const QStringList
op->setArguments(replaceVariables(arguments));
op->backup();
if (!PackageManagerCorePrivate::performOperationThreaded(op.data())) {
- PackageManagerCorePrivate::performOperationThreaded(op.data(), PackageManagerCorePrivate::Undo);
+ PackageManagerCorePrivate::performOperationThreaded(op.data(), Operation::Undo);
return false;
}
return true;
@@ -3121,6 +3121,17 @@ QStringList PackageManagerCore::values(const QString &key, const QStringList &de
}
/*!
+ Returns the installer key for \a value. If \a value is not known, empty string is
+ returned.
+
+ \sa {installer::key}{installer.key}
+*/
+QString PackageManagerCore::key(const QString &value) const
+{
+ return d->m_data.key(value);
+}
+
+/*!
Sets the installer value for \a key to \a value.
\sa {installer::setValue}{installer.setValue}
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index b83d8f05a..5c480e1a9 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -169,6 +169,7 @@ public:
Q_INVOKABLE void setValue(const QString &key, const QString &value);
Q_INVOKABLE QString value(const QString &key, const QString &defaultValue = QString()) const;
Q_INVOKABLE QStringList values(const QString &key, const QStringList &defaultValue = QStringList()) const;
+ Q_INVOKABLE QString key(const QString &value) const;
QString replaceVariables(const QString &str) const;
QByteArray replaceVariables(const QByteArray &str) const;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 274ea017b..94e08018a 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -117,18 +117,18 @@ private:
Operation *m_operation;
};
-static bool runOperation(Operation *operation, PackageManagerCorePrivate::OperationType type)
+static bool runOperation(Operation *operation, Operation::OperationType type)
{
OperationTracer tracer(operation);
switch (type) {
- case PackageManagerCorePrivate::Backup:
+ case Operation::Backup:
tracer.trace(QLatin1String("backup"));
operation->backup();
return true;
- case PackageManagerCorePrivate::Perform:
+ case Operation::Perform:
tracer.trace(QLatin1String("perform"));
return operation->performOperation();
- case PackageManagerCorePrivate::Undo:
+ case Operation::Undo:
tracer.trace(QLatin1String("undo"));
return operation->undoOperation();
default:
@@ -368,7 +368,7 @@ bool PackageManagerCorePrivate::isProcessRunning(const QString &name,
}
/* static */
-bool PackageManagerCorePrivate::performOperationThreaded(Operation *operation, OperationType type)
+bool PackageManagerCorePrivate::performOperationThreaded(Operation *operation, Operation::OperationType type)
{
QFutureWatcher<bool> futureWatcher;
const QFuture<bool> future = QtConcurrent::run(runOperation, operation, type);
@@ -1254,7 +1254,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
// create the directory containing the maintenance tool (like a bundle structure on macOS...)
Operation *op = createOwnedOperation(QLatin1String("Mkdir"));
op->setArguments(QStringList() << targetAppDirPath);
- performOperationThreaded(op, Backup);
+ performOperationThreaded(op, Operation::Backup);
performOperationThreaded(op);
performedOperations.append(takeOwnedOperation(op));
}
@@ -1266,14 +1266,14 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
Operation *op = createOwnedOperation(QLatin1String("Copy"));
op->setArguments(QStringList() << (sourceAppDirPath + QLatin1String("/../PkgInfo"))
<< (targetAppDirPath + QLatin1String("/../PkgInfo")));
- performOperationThreaded(op, Backup);
+ performOperationThreaded(op, Operation::Backup);
performOperationThreaded(op);
// copy Info.plist to target directory
op = createOwnedOperation(QLatin1String("Copy"));
op->setArguments(QStringList() << (sourceAppDirPath + QLatin1String("/../Info.plist"))
<< (targetAppDirPath + QLatin1String("/../Info.plist")));
- performOperationThreaded(op, Backup);
+ performOperationThreaded(op, Operation::Backup);
performOperationThreaded(op);
// patch the Info.plist after copying it
@@ -1306,7 +1306,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
op = createOwnedOperation(QLatin1String("Mkdir"));
op->setArguments(QStringList() << (QFileInfo(targetAppDirPath).path() + QLatin1String("/Resources")));
- performOperationThreaded(op, Backup);
+ performOperationThreaded(op, Operation::Backup);
performOperationThreaded(op);
// copy application icons if it exists.
@@ -1315,7 +1315,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
op = createOwnedOperation(QLatin1String("Copy"));
op->setArguments(QStringList() << (sourceAppDirPath + QLatin1String("/../Resources/") + icon)
<< (targetAppDirPath + QLatin1String("/../Resources/") + icon));
- performOperationThreaded(op, Backup);
+ performOperationThreaded(op, Operation::Backup);
performOperationThreaded(op);
// finally, copy everything within Frameworks and plugins
@@ -1617,7 +1617,7 @@ bool PackageManagerCorePrivate::runInstaller()
mkdirOp->setValue(QLatin1String("forceremoval"), true);
mkdirOp->setValue(QLatin1String("uninstall-only"), true);
- performOperationThreaded(mkdirOp, Backup);
+ performOperationThreaded(mkdirOp, Operation::Backup);
if (!performOperationThreaded(mkdirOp)) {
// if we cannot create the target dir, we try to activate the admin rights
adminRightsGained = m_core->gainAdminRights();
@@ -2177,7 +2177,7 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
connectOperationCallMethodRequest(operation);
// allow the operation to backup stuff before performing the operation
- performOperationThreaded(operation, PackageManagerCorePrivate::Backup);
+ performOperationThreaded(operation, Operation::Backup);
bool ignoreError = false;
bool ok = performOperationThreaded(operation);
@@ -2412,7 +2412,7 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
qCDebug(QInstaller::lcInstallerInstallLog) << "undo operation=" << undoOperation->name();
bool ignoreError = false;
- bool ok = performOperationThreaded(undoOperation, PackageManagerCorePrivate::Undo);
+ bool ok = performOperationThreaded(undoOperation, Operation::Undo);
const QString componentName = undoOperation->value(QLatin1String("component")).toString();
@@ -2425,7 +2425,7 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
QMessageBox::Retry | QMessageBox::Ignore, QMessageBox::Ignore);
if (button == QMessageBox::Retry)
- ok = performOperationThreaded(undoOperation, Undo);
+ ok = performOperationThreaded(undoOperation, Operation::Undo);
else if (button == QMessageBox::Ignore)
ignoreError = true;
}
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 8983a95c2..858baf9eb 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -67,12 +67,6 @@ class PackageManagerCorePrivate : public QObject
Q_DISABLE_COPY(PackageManagerCorePrivate)
public:
- enum OperationType {
- Backup,
- Perform,
- Undo
- };
-
explicit PackageManagerCorePrivate(PackageManagerCore *core);
explicit PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
const QList<OperationBlob> &performedOperations);
@@ -80,8 +74,8 @@ public:
static bool isProcessRunning(const QString &name, const QList<ProcessInfo> &processes);
- static bool performOperationThreaded(Operation *op, PackageManagerCorePrivate::OperationType type
- = PackageManagerCorePrivate::Perform);
+ static bool performOperationThreaded(Operation *op, UpdateOperation::OperationType type
+ = UpdateOperation::Perform);
void initialize(const QHash<QString, QString> &params);
bool isOfflineOnly() const;
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index d488731df..2f3dd9204 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -244,6 +244,11 @@ QVariant PackageManagerCoreData::value(const QString &key, const QVariant &_defa
return m_settings.value(key, _default);
}
+QString PackageManagerCoreData::key(const QString &value) const
+{
+ return m_variables.key(value, QString());
+}
+
QString PackageManagerCoreData::replaceVariables(const QString &str) const
{
static const QChar at = QLatin1Char('@');
diff --git a/src/libs/installer/packagemanagercoredata.h b/src/libs/installer/packagemanagercoredata.h
index e112fea1c..4c954d943 100644
--- a/src/libs/installer/packagemanagercoredata.h
+++ b/src/libs/installer/packagemanagercoredata.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -52,6 +52,7 @@ public:
bool contains(const QString &key) const;
bool setValue(const QString &key, const QString &normalizedValue);
QVariant value(const QString &key, const QVariant &_default = QVariant()) const;
+ QString key(const QString &value) const;
QString replaceVariables(const QString &str) const;
QByteArray replaceVariables(const QByteArray &ba) const;
diff --git a/src/libs/kdtools/updateoperation.h b/src/libs/kdtools/updateoperation.h
index e05fc34d2..a8110791c 100644
--- a/src/libs/kdtools/updateoperation.h
+++ b/src/libs/kdtools/updateoperation.h
@@ -53,6 +53,12 @@ public:
UserDefinedError = 128
};
+ enum OperationType {
+ Backup,
+ Perform,
+ Undo
+ };
+
explicit UpdateOperation(QInstaller::PackageManagerCore *core);
virtual ~UpdateOperation();
diff --git a/tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro b/tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro
new file mode 100644
index 000000000..9ac3f260a
--- /dev/null
+++ b/tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro
@@ -0,0 +1,8 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib qml
+
+SOURCES = tst_elevatedexecuteoperation.cpp
+
+DEFINES += "QMAKE_BINARY=$$fromNativeSeparators($$QMAKE_BINARY)"
diff --git a/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp
new file mode 100644
index 000000000..aa2849559
--- /dev/null
+++ b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include <packagemanagercore.h>
+#include <elevatedexecuteoperation.h>
+
+#include <QTest>
+
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+
+using namespace QInstaller;
+
+class tst_elevatedexecuteoperation : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testExecuteOperation()
+ {
+ m_core.setValue(QLatin1String("QMAKE_BINARY"), QUOTE(QMAKE_BINARY));
+ m_core.setValue(QLatin1String("QMAKE_BINARY_OLD"), QLatin1String("FAKE_QMAKE"));
+ ElevatedExecuteOperation operation(&m_core);
+ operation.setArguments(QStringList() << QLatin1String("UNDOEXECUTE") << QLatin1String("FAKE_QMAKE"));
+
+ QTest::ignoreMessage(QtDebugMsg, "\"FAKE_QMAKE\" started, arguments: \"\"");
+ QString message = "Failed to run undo operation \"Execute\" for component . Trying again with arguments %1";
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY))));
+ message = "\"%1\" started, arguments: \"\"";
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY))));
+
+ QCOMPARE(operation.undoOperation(), true);
+ QCOMPARE(Operation::Error(operation.error()), Operation::NoError);
+ }
+
+private:
+ PackageManagerCore m_core;
+};
+
+QTEST_MAIN(tst_elevatedexecuteoperation)
+
+#include "tst_elevatedexecuteoperation.moc"
diff --git a/tests/auto/installer/installer.pro b/tests/auto/installer/installer.pro
index 2c55de40c..4421643b8 100644
--- a/tests/auto/installer/installer.pro
+++ b/tests/auto/installer/installer.pro
@@ -36,7 +36,8 @@ SUBDIRS += \
moveoperation \
environmentvariableoperation \
licenseagreement \
- globalsettingsoperation
+ globalsettingsoperation \
+ elevatedexecuteoperation
win32 {
SUBDIRS += registerfiletypeoperation \