Commit 8cfafdfb authored by Martin Kampas's avatar Martin Kampas

Extract some code into libtestutils

1. Un-inline SandboxFileEngineHandler (originally it was all implemented in
   single header file to avoid the need for a real library to be linked)
2. Extract RndSsuCliTest::Process
3. Keep all the stuff inside tests/testutils
parent 6213f19a
......@@ -16,6 +16,9 @@ UI_HEADERS_DIR = $$BUILD
UI_SOURCES_DIR = $$BUILD
RCC_DIR = $$BUILD
# This definitely needs to be refactorized somehow (the common module{.pro,.pri,_dependencies.pri}
# approach would do a good job here)
LIBS += -L$$PWD/build/libssu
LD_LIBRARY_PATH = $$PWD/build/libssu
LIBS += -L$$PWD/build/testutils
LD_LIBRARY_PATH = $$PWD/build/libssu:$$PWD/build/testutils
INCLUDEPATH += $$PWD/libssu
/**
* @file sandboxfileenginehandler.h
* @copyright 2013 Jolla Ltd.
* @author Martin Kampas <martin.kampas@tieto.com>
* @date 2013
*/
#ifndef _SANDBOXINGFILEENGINEHANDLER_H
#define _SANDBOXINGFILEENGINEHANDLER_H
#include <QtCore/QAbstractFileEngineHandler>
#include <QtCore/QDir>
#include <QtCore/QFSFileEngine>
#include <QtCore/QFileInfo>
#include <QtCore/QProcessEnvironment>
#include <QtCore/QSet>
#include <ssucoreconfig.h>
#include "../../constants.h"
/**
* Redirects all file operations on system configuration files to files under
* directory specified by SSU_TESTS_SANDBOX environment variable.
*/
class SandboxFileEngineHandler : public QAbstractFileEngineHandler {
public:
QAbstractFileEngine *create(const QString &fileName) const{
static bool enabled = false;
static bool firstCall = true;
if (!enabled && !firstCall){
return 0;
}
static QString sandboxPath =
QProcessEnvironment::systemEnvironment().value("SSU_TESTS_SANDBOX");
if (firstCall){
firstCall = false;
if (sandboxPath.isEmpty()){
return 0;
}
if (!QFileInfo(sandboxPath).exists()){
qFatal("%s: Invalid SSU_TESTS_SANDBOX value: No such file or directory",
qPrintable(sandboxPath));
}
if (!QFileInfo(sandboxPath).isDir()){
qFatal("%s: Invalid SSU_TESTS_SANDBOX value: Not a directory",
qPrintable(sandboxPath));
}
enabled = true;
}
if (!fileName.startsWith('/')){
return 0;
}
static QSet<QString> ssuConfigFiles = QSet<QString>()
<< SSU_CONFIGURATION
<< SSU_REPO_CONFIGURATION
<< SSU_DEFAULT_CONFIGURATION
<< SSU_BOARD_MAPPING_CONFIGURATION;
static QSet<QString> ssuConfigDirectories = QSet<QString>()
<< SSU_BOARD_MAPPING_CONFIGURATION_DIR;
if (!ssuConfigFiles.contains(fileName)){
bool match = false;
foreach (const QString &ssuConfigDirectory, ssuConfigDirectories){
if (fileName.startsWith(ssuConfigDirectory + '/')){
match = true;
break;
}
}
if (!match){
return 0;
}
}
const QString fileName_ = QDir(sandboxPath).absoluteFilePath(QString(fileName).remove(0, 1));
return new QFSFileEngine(fileName_);
}
};
#endif
DEPENDPATH *= $${PWD}/sandbox
DEPENDPATH *= $${PWD}/testutils
TESTS_PATH = /opt/tests/ssu
DEFINES += TESTS_PATH="'\"$${TESTS_PATH}\"'"
......
TEMPLATE = subdirs
CONFIG += qt ordered coverage debug
SUBDIRS = \
sandbox \
testutils \
testutils/sandboxhook.pro \
ut_rndssucli \
ut_settings \
ut_ssuurlresolver \
......
......@@ -5,27 +5,27 @@
<!-- At least one set per suite, name and description mandatory -->
<set name="rndssucli" description="Test to determine if ssu command line tool works properly" feature="rndssucli">
<case name="ut_rndssucli" type="Functional" description="SSU command line utility test" timeout="1000" subfeature="">
<step expected_result="0">/opt/tests/ssu/ut_rndssucli</step>
<step expected_result="0">/opt/tests/ssu/runtest.sh ut_rndssucli</step>
</case>
</set>
<set name="settings" description="Test to determine if configuration files processing works properly" feature="settings">
<case name="ut_settings" type="Functional" description="Settings processing test" timeout="1000" subfeature="">
<step expected_result="0">/opt/tests/ssu/ut_settings</step>
<step expected_result="0">/opt/tests/ssu/runtest.sh ut_settings</step>
</case>
</set>
<set name="ssuurlresolver" description="Test to determine if the UrlResolverPlugin works well with installed version of libzypp" feature="ssuurlresolver">
<case name="ut_ssuurlresolver" type="Functional" description="URL resolver plugin test" timeout="1000" subfeature="">
<step expected_result="0">/opt/tests/ssu/ut_ssuurlresolver</step>
<step expected_result="0">/opt/tests/ssu/runtest.sh ut_ssuurlresolver</step>
</case>
</set>
<set name="urlresolver" description="Test to determine if URL resolving works properly" feature="urlresolver">
<case name="ut_urlresolver" type="Functional" description="URL resolver tests" timeout="1000" subfeature="">
<step expected_result="0">/opt/tests/ssu/ut_urlresolver</step>
<step expected_result="0">/opt/tests/ssu/runtest.sh ut_urlresolver</step>
</case>
</set>
<set name="variables" description="Test to determine if variable resolving works properly" feature="variables">
<case name="ut_variables" type="Functional" description="Variable resolver tests" timeout="1000" subfeature="">
<step expected_result="0">/opt/tests/ssu/ut_variables</step>
<step expected_result="0">/opt/tests/ssu/runtest.sh ut_variables</step>
</case>
</set>
</suite>
......
/**
* @file process.cpp
* @copyright 2013 Jolla Ltd.
* @author Martin Kampas <martin.kampas@tieto.com>
* @date 2013
*/
#include "process.h"
/**
* @class Wraps QProcess for easier use within test code
*
* Example use:
*
* @code
* Process ssu;
* const QString output = ssu.execute("ssu", QStringList() << "mode");
* QVERIFY2(!ssu.hasError(), qPrintable(ssu.fmtErrorMessage()));
*
* QCOMPARE(output, "...");
* @endcode
*/
Process::Process() : m_expectFail(false), m_timedOut(false) {}
QString Process::execute(const QString &program, const QStringList &arguments,
bool expectedResult){
Q_ASSERT(processStatus() == NotRunning);
m_program = program;
m_arguments = arguments;
m_expectFail = expectedResult == ExpectFail;
m_process.start(program, arguments);
m_timedOut = !m_process.waitForFinished();
return m_process.readAllStandardOutput();
}
bool Process::hasError(){
return m_timedOut
|| m_process.error() != QProcess::UnknownError
|| m_process.exitStatus() != QProcess::NormalExit
|| (m_process.exitCode() != 0) != m_expectFail;
}
QString Process::fmtErrorMessage(){
Q_ASSERT(hasError());
QStringList reasons;
if (m_timedOut){
reasons.append("Timed out");
}else if (m_process.exitStatus() != QProcess::NormalExit){
reasons.append("Process crashed");
}else if (m_expectFail && (m_process.exitCode() == 0)){
reasons.append("Did not fail while it was expected to");
}else{
if (m_process.error() != QProcess::UnknownError){
reasons.append(m_process.errorString());
}
const QString errorOut = m_process.readAllStandardError();
if (!errorOut.isEmpty()){
reasons.append(errorOut);
}
}
return QString("Failed to execute `%1 %2`: %3")
.arg(m_program)
.arg(QStringList(m_arguments).replaceInStrings(QRegExp("^|$"), "\"").join(" "))
.arg(reasons.join(": "));
}
/**
* @file process.h
* @copyright 2013 Jolla Ltd.
* @author Martin Kampas <martin.kampas@tieto.com>
* @date 2013
*/
#ifndef _PROCESS_H
#define _PROCESS_H
#include <QtCore/QProcess>
class Process {
public:
enum ExpectedResult {
ExpectSuccess,
ExpectFail
};
public:
Process();
QString execute(const QString &program, const QStringList &arguments,
bool expectedResult = ExpectSuccess);
bool hasError();
QString fmtErrorMessage();
private:
QProcess m_process;
QString m_program;
QStringList m_arguments;
bool m_expectFail;
bool m_timedOut;
};
#endif
#!/bin/sh
export LD_LIBRARY_PATH="`dirname "$0"`:${LD_LIBRARY_PATH}"
exec "`dirname "$0"`/$1"
/**
* @file sandboxfileenginehandler.cpp
* @copyright 2013 Jolla Ltd.
* @author Martin Kampas <martin.kampas@tieto.com>
* @date 2013
*/
#include "sandboxfileenginehandler.h"
#include <QtCore/QDir>
#include <QtCore/QFSFileEngine>
#include <QtCore/QFileInfo>
#include <QtCore/QProcessEnvironment>
#include <QtCore/QSet>
#include <ssucoreconfig.h>
#include "../../constants.h"
/**
* @class SandboxFileEngineHandler
*
* Redirects all file operations on system configuration files to files under
* directory specified by SSU_TESTS_SANDBOX environment variable.
*/
SandboxFileEngineHandler::SandboxFileEngineHandler() {}
QAbstractFileEngine *SandboxFileEngineHandler::create(const QString &fileName) const{
static bool enabled = false;
static bool firstCall = true;
if (!enabled && !firstCall){
return 0;
}
static QString sandboxPath =
QProcessEnvironment::systemEnvironment().value("SSU_TESTS_SANDBOX");
if (firstCall){
firstCall = false;
if (sandboxPath.isEmpty()){
return 0;
}
if (!QFileInfo(sandboxPath).exists()){
qFatal("%s: Invalid SSU_TESTS_SANDBOX value: No such file or directory",
qPrintable(sandboxPath));
}
if (!QFileInfo(sandboxPath).isDir()){
qFatal("%s: Invalid SSU_TESTS_SANDBOX value: Not a directory",
qPrintable(sandboxPath));
}
enabled = true;
}
if (!fileName.startsWith('/')){
return 0;
}
static QSet<QString> ssuConfigFiles = QSet<QString>()
<< SSU_CONFIGURATION
<< SSU_REPO_CONFIGURATION
<< SSU_DEFAULT_CONFIGURATION
<< SSU_BOARD_MAPPING_CONFIGURATION;
static QSet<QString> ssuConfigDirectories = QSet<QString>()
<< SSU_BOARD_MAPPING_CONFIGURATION_DIR;
if (!ssuConfigFiles.contains(fileName)){
bool match = false;
foreach (const QString &ssuConfigDirectory, ssuConfigDirectories){
if (fileName.startsWith(ssuConfigDirectory + '/')){
match = true;
break;
}
}
if (!match){
return 0;
}
}
const QString fileName_ = QDir(sandboxPath).absoluteFilePath(QString(fileName).remove(0, 1));
return new QFSFileEngine(fileName_);
}
/**
* @file sandboxfileenginehandler.h
* @copyright 2013 Jolla Ltd.
* @author Martin Kampas <martin.kampas@tieto.com>
* @date 2013
*/
#ifndef _SANDBOXINGFILEENGINEHANDLER_H
#define _SANDBOXINGFILEENGINEHANDLER_H
#include <QtCore/QAbstractFileEngineHandler>
class SandboxFileEngineHandler : public QAbstractFileEngineHandler {
public:
SandboxFileEngineHandler();
QAbstractFileEngine *create(const QString &fileName) const;
};
#endif
......@@ -7,6 +7,8 @@ CONFIG += console qtestlib
QT -= gui
QT += network testlib
LIBS += -ltestutils
!include( ../tests.pri ) { error("Unable to find tests include") }
unix:target.path = $${PREFIX}/$$TESTS_PATH
......
HEADERS = \
process.h \
sandboxfileenginehandler.h \
SOURCES = \
process.cpp \
sandboxfileenginehandler.cpp \
TEMPLATE = lib
TARGET = testutils
CONFIG -= app_bundle
CONFIG += console qtestlib
QT -= gui
QT += network testlib
LIBS += -lssu
!include( ../tests.pri ) { error("Unable to find tests include") }
unix:target.path = $${PREFIX}/$$TESTS_PATH
INSTALLS += target
exec_wrapper.path = $${PREFIX}/$$TESTS_PATH
exec_wrapper.files = $${PWD}/runtest.sh
INSTALLS += exec_wrapper
!include( ../../buildpath.pri ) { error("Unable to find build path specification") }
......@@ -12,68 +12,9 @@
#include <QtTest/QtTest>
typedef QStringList Args; // improve readability
#include "../testutils/process.h"
class RndSsuCliTest::Process {
public:
enum ExpectedResult {
ExpectSuccess,
ExpectFail
};
Process() : m_expectFail(false), m_timedOut(false) {}
QString execute(const QString &program, const QStringList &arguments,
bool expectedResult = ExpectSuccess){
Q_ASSERT(processStatus() == NotRunning);
m_program = program;
m_arguments = arguments;
m_expectFail = expectedResult == ExpectFail;
m_process.start(program, arguments);
m_timedOut = !m_process.waitForFinished();
return m_process.readAllStandardOutput();
}
bool hasError(){
return m_timedOut
|| m_process.error() != QProcess::UnknownError
|| m_process.exitStatus() != QProcess::NormalExit
|| (m_process.exitCode() != 0) != m_expectFail;
}
QString fmtErrorMessage(){
Q_ASSERT(hasError());
QStringList reasons;
if (m_timedOut){
reasons.append("Timed out");
}else if (m_process.exitStatus() != QProcess::NormalExit){
reasons.append("Process crashed");
}else if (m_expectFail && (m_process.exitCode() == 0)){
reasons.append("Did not fail while it was expected to");
}else{
if (m_process.error() != QProcess::UnknownError){
reasons.append(m_process.errorString());
}
const QString errorOut = m_process.readAllStandardError();
if (!errorOut.isEmpty()){
reasons.append(errorOut);
}
}
return QString("Failed to execute `%1 %2`: %3")
.arg(m_program)
.arg(QStringList(m_arguments).replaceInStrings(QRegExp("^|$"), "\"").join(" "))
.arg(reasons.join(": "));
}
private:
QProcess m_process;
QString m_program;
QStringList m_arguments;
bool m_expectFail;
bool m_timedOut;
};
typedef QStringList Args; // improve readability
void RndSsuCliTest::initTestCase(){
Process mktemp;
......
......@@ -13,8 +13,6 @@
class RndSsuCliTest: public QObject {
Q_OBJECT
class Process;
private slots:
void initTestCase();
void cleanupTestCase();
......
......@@ -10,6 +10,7 @@ TARGET = ut_rndssucli
LIBS += \
-lssu \
-ltestutils \
CONFIG -= app_bundle
CONFIG += console qtestlib
......
......@@ -7,7 +7,7 @@
#include <QtTest/QtTest>
#include "../sandbox/sandboxfileenginehandler.h"
#include "../testutils/sandboxfileenginehandler.h"
#include "urlresolvertest.cpp"
int main(int argc, char **argv){
......
......@@ -3,7 +3,7 @@ SOURCES = main.cpp \
urlresolvertest.cpp
TEMPLATE = app
TARGET = ut_urlresolver
LIBS += -lssu
LIBS += -lssu -ltestutils
CONFIG -= app_bundle
CONFIG += console qtestlib
QT -= gui
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment