Skip to content

Commit

Permalink
[ssu] Make it easier to run testcases in-tree, contributes to JB#31688
Browse files Browse the repository at this point in the history
  • Loading branch information
Bernd Wachter committed Aug 21, 2015
1 parent cb27341 commit c687b53
Show file tree
Hide file tree
Showing 14 changed files with 230 additions and 28 deletions.
7 changes: 7 additions & 0 deletions libssu/sandbox.cpp
Expand Up @@ -125,6 +125,13 @@ QString Sandbox::map(const QString &fileName)
QFileInfo(fileName).absoluteFilePath()));
}

QString Sandbox::map(const QString &pathName, const QString &fileName)
{
return effectiveRootDir().filePath(
QDir::root().relativeFilePath(
QFileInfo(pathName + fileName).absoluteFilePath()));
}

/**
* Copies selected files into sandbox. Existing files in sandbox are not overwriten.
*
Expand Down
7 changes: 7 additions & 0 deletions libssu/sandbox_p.h
Expand Up @@ -12,6 +12,12 @@
#include <QtCore/QSet>
#include <QtCore/QString>

// use either environment variable SSU_TESTS_DATA_PATH or compile time
// TESTS_DATA_PATH to locate test data
#define LOCATE_DATA_PATH (getenv("SSU_TESTS_DATA_PATH") ? \
getenv("SSU_TESTS_DATA_PATH") : \
TESTS_DATA_PATH)

class Sandbox {
public:
enum Usage {
Expand All @@ -36,6 +42,7 @@ class Sandbox {

static QDir effectiveRootDir();
static QString map(const QString &fileName);
static QString map(const QString &pathName, const QString &fileName);

bool addWorldFiles(const QString &directory, QDir::Filters filters = QDir::NoFilter,
const QStringList &filterNames = QStringList(), bool recurse = true);
Expand Down
75 changes: 75 additions & 0 deletions run-tests
@@ -0,0 +1,75 @@
#!/bin/sh
#
# Simple script to run all tests either in-tree or after test RPM
# installation. Output will be nicely formatted if output formatter
# is available. All arguments to this script are passed to formatoutput.

prepareInTreeTestData(){
# this is a dirty hack to get most of the test data into a place
# usable for running tests without installation. Currently this
# causes some duplication
mkdir -p build/testdata
TESTDATA=`find tests -name testdata`

for t in $TESTDATA; do
test=`echo $t | sed 's,.*tests/,,' | sed 's,/.*,,'`
mkdir -p build/testdata/$test/
dirs=`find $t/* -prune -type f`
if [ -z "$dirs" ]; then
cp -a $t/* build/testdata/$test/
else
mkdir -p build/testdata/$test/configroot/usr/share/ssu/
mkdir -p build/testdata/$test/configroot/etc/ssu/
for ini in $t/*.ini; do
inifile=`echo $ini | sed 's,.*/,,'`
if [ $inifile = "ssu.ini" ]; then
cp $ini build/testdata/$test/configroot/etc/ssu/
elif [ $inifile = "board-mappings.ini" ]; then
mkdir -p build/testdata/$test/configroot/usr/share/ssu/board-mappings.d
cp $ini build/testdata/$test/configroot/usr/share/ssu/board-mappings.d/
else
cp $ini build/testdata/$test/configroot/usr/share/ssu/
fi
done
cp $t/* build/testdata/$test/configroot/
for key in $t/*.{key,crt}; do
cp $key build/testdata/$test/
done
fi
done
}

if [ -d "build" ]; then
BASE_DIR="`pwd`/build"
export LD_LIBRARY_PATH="$BASE_DIR/lib:${LD_LIBRARY_PATH}"
export SSU_SANDBOX_PATH="$BASE_DIR/lib/libsandboxhook.so"
prepareInTreeTestData
TESTS=`ls $BASE_DIR/bin/ut_*`
if [ -f "$BASE_DIR/bin/formatoutput" ]; then
FORMATOUTPUT="$BASE_DIR/bin/formatoutput"
fi
elif [ -d "/opt/tests/ssu" ]; then
BASE_DIR="/opt/tests/ssu"
export LD_LIBRARY_PATH="$BASE_DIR:${LD_LIBRARY_PATH}"
TESTS=`ls $BASE_DIR/ut_*`
if [ -f "$BASE_DIR/formatoutput" ]; then
FORMATOUTPUT="$BASE_DIR/formatoutput"
fi
else
echo "Neither ./build nor /opt/tests/ssu exist, exiting"
exit 1
fi

for test in $TESTS; do
if [ -d "./build/testdata/`basename $test`" ]; then
export SSU_TESTS_DATA_PATH="`pwd`/build/testdata/`basename $test`"
else
unset SSU_TESTS_DATA_PATH
fi

if [ -z "$FORMATOUTPUT" ]; then
$test | grep -v "^PASS"
else
$test | $FORMATOUTPUT $@
fi
done
4 changes: 4 additions & 0 deletions tests/formatoutput/formatoutput.pro
@@ -0,0 +1,4 @@
TARGET = formatoutput
include(../testapplication.pri)

SOURCES = main.cpp
96 changes: 96 additions & 0 deletions tests/formatoutput/main.cpp
@@ -0,0 +1,96 @@
/**
* @file main.cpp
* @copyright 2015 Jolla Ltd.
* @author Bernd Wachter <bernd.wachter@jolla.com>
* @date 2015
*/

#include <QTextStream>
#include <QRegExp>
#include <getopt.h>

void usage(){
QTextStream out(stderr);
out << "Parse QTest output on STDIN and make it shiny" << endl
<< endl
<< "Usage: formatoutput [options]" << endl
<< endl
<< "\t--skip-pass <yes|no> \tSkip PASS lines [yes]" << endl
<< "\t--skip-debug <yes|no> \tSkip QDEBUG lines [yes]" << endl
<< "\t--skip-warn <yes|no> \tSkip QWARN lines [no]" << endl
<< "\t--skip-config <yes|no> \tSkip Config: lines [yes]" << endl
<< endl
<< "\t--help \tThis help text" << endl
<< endl;
}

bool isTrue(char *argument){
if (!strcasecmp(argument, "yes") ||
!strcasecmp(argument, "true") ||
!strcmp(argument, "1"))
return true;
else return false;
}

int main(int argc, char **argv){
QTextStream in(stdin);
QTextStream out(stdout);
int c, option_index;

static struct option long_options[] = {
{"skip-pass", required_argument, 0, 0 },
{"skip-debug", required_argument, 0, 0 },
{"skip-warn", required_argument, 0, 0 },
{"skip-config", required_argument, 0, 0 },
{"help", no_argument, 0, 0 }
};

struct {
bool skip_pass = true;
bool skip_debug = true;
bool skip_warn = false;
bool skip_config = true;
} options;

while ((c=getopt_long_only(argc, argv, "",
long_options, &option_index)) != EOF){
switch(c){
case 0:
if (!strcmp(long_options[option_index].name, "help")){
usage();
exit(0);
} else if (!strcmp(long_options[option_index].name, "skip-pass")){
options.skip_pass = isTrue(optarg);
} else if (!strcmp(long_options[option_index].name, "skip-debug")){
options.skip_debug = isTrue(optarg);
} else if (!strcmp(long_options[option_index].name, "skip-warn")){
options.skip_warn = isTrue(optarg);
} else if (!strcmp(long_options[option_index].name, "skip-config")){
options.skip_config = isTrue(optarg);
}
break;
default:
usage();
exit(-1);
}
}

while (!in.atEnd()){
QString line = in.readLine();

if (line.startsWith("PASS") && options.skip_pass) continue;
if (line.startsWith("QDEBUG") && options.skip_debug) continue;
if (line.startsWith("QWARN") && options.skip_warn) continue;
if (line.startsWith("Config:") && options.skip_config) continue;

line.replace(QRegExp("^(\\*{3}.*\\*{3})"), "\033[0;36m\\1\033[0;0m");
line.replace(QRegExp("^(QDEBUG .*)"), "\033[0;90m\\1\033[0;0m");
line.replace(QRegExp("^(QWARN .*)"), "\033[0;34m\\1\033[0;0m");
line.replace(QRegExp("^FAIL!"), "\033[0;31mFAIL!\033[0;0m");
line.replace(QRegExp("^PASS"), "\033[0;32mPASS\033[0;0m");
line.replace(QRegExp("^Totals: (\\d{1,} passed), (\\d{1,} failed), (\\d{1,} skipped)"),
"Totals: \033[0;32m\\1\033[0;0m, \033[0;31m\\2\033[0;0m, \033[0;33m\\3\033[0;0m");
out << line << endl;
}

}
7 changes: 6 additions & 1 deletion tests/tests.pro
Expand Up @@ -2,6 +2,7 @@ TEMPLATE = subdirs
CONFIG += ordered coverage debug
SUBDIRS = \
testutils \
formatoutput \
testutils/sandboxhook.pro \
ut_coreconfig \
ut_deviceinfo \
Expand All @@ -16,4 +17,8 @@ SUBDIRS = \
include(tests_common.pri)
tests.files = tests.xml
tests.path = $$TESTS_PATH
INSTALLS += tests

scripts.files = ../run-tests
scripts.path = $$TESTS_PATH

INSTALLS += tests scripts
2 changes: 1 addition & 1 deletion tests/ut_coreconfig/main.cpp
Expand Up @@ -11,7 +11,7 @@
#include "coreconfigtest.h"

int main(int argc, char **argv){
Sandbox sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH),
Sandbox sandbox(QString("%1/configroot").arg(LOCATE_DATA_PATH),
Sandbox::UseAsSkeleton, Sandbox::ThisProcess);
if (!sandbox.activate()){
qFatal("Failed to activate sandbox");
Expand Down
2 changes: 1 addition & 1 deletion tests/ut_deviceinfo/main.cpp
Expand Up @@ -11,7 +11,7 @@
#include "deviceinfotest.h"

int main(int argc, char **argv){
Sandbox sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH),
Sandbox sandbox(QString("%1/configroot").arg(LOCATE_DATA_PATH),
Sandbox::UseAsSkeleton, Sandbox::ThisProcess);
if (!sandbox.activate()){
qFatal("Failed to activate sandbox");
Expand Down
2 changes: 1 addition & 1 deletion tests/ut_repomanager/main.cpp
Expand Up @@ -11,7 +11,7 @@
#include "repomanagertest.h"

int main(int argc, char **argv){
Sandbox sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH),
Sandbox sandbox(QString("%1/configroot").arg(LOCATE_DATA_PATH),
Sandbox::UseAsSkeleton, Sandbox::ThisProcess);
if (!sandbox.activate()){
qFatal("Failed to activate sandbox");
Expand Down
38 changes: 19 additions & 19 deletions tests/ut_sandbox/sandboxtest.cpp
Expand Up @@ -15,55 +15,55 @@ void SandboxTest::test(){

const QDir::Filters noHidden = QDir::AllEntries | QDir::NoDotAndDotDot;

QCOMPARE(QDir(Sandbox::map(TESTS_DATA_PATH "/world")).entryList(noHidden, QDir::Name),
QCOMPARE(QDir(Sandbox::map(LOCATE_DATA_PATH, "/world")).entryList(noHidden, QDir::Name),
QStringList()
<< "world-and-sandbox"
<< "world-only"
<< "world-only-to-be-copied-into-sandbox");

QVERIFY(!QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/world-only")).isWritable());
QCOMPARE(readAll(Sandbox::map(TESTS_DATA_PATH "/world/world-only")).trimmed(),
QVERIFY(!QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/world-only")).isWritable());
QCOMPARE(readAll(Sandbox::map(LOCATE_DATA_PATH, "/world/world-only")).trimmed(),
QString("world/world-only"));

QVERIFY(!QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/world-and-sandbox")).isWritable());
QCOMPARE(readAll(Sandbox::map(TESTS_DATA_PATH "/world/world-and-sandbox")).trimmed(),
QVERIFY(!QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/world-and-sandbox")).isWritable());
QCOMPARE(readAll(Sandbox::map(LOCATE_DATA_PATH, "/world/world-and-sandbox")).trimmed(),
QString("world/world-and-sandbox"));

QVERIFY(!QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox"))
QVERIFY(!QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/world-only-to-be-copied-into-sandbox"))
.isWritable());
QCOMPARE(readAll(Sandbox::map(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox"))
QCOMPARE(readAll(Sandbox::map(LOCATE_DATA_PATH, "/world/world-only-to-be-copied-into-sandbox"))
.trimmed(), QString("world/world-only-to-be-copied-into-sandbox"));

QVERIFY(!QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/sandbox-only")).exists());
QVERIFY(!QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/sandbox-only")).exists());


Sandbox sandbox(Sandbox::map(TESTS_DATA_PATH "/sandbox"),
Sandbox sandbox(Sandbox::map(LOCATE_DATA_PATH, "/sandbox"),
Sandbox::UseAsSkeleton, Sandbox::ThisProcess | Sandbox::ChildProcesses);
sandbox.addWorldFiles(Sandbox::map(TESTS_DATA_PATH "/world"), QDir::AllEntries,
sandbox.addWorldFiles(Sandbox::map(LOCATE_DATA_PATH, "/world"), QDir::AllEntries,
QStringList() << "*-to-be-copied-into-sandbox");
QVERIFY(sandbox.activate());


QCOMPARE(QDir(Sandbox::map(TESTS_DATA_PATH "/world")).entryList(noHidden, QDir::Name),
QCOMPARE(QDir(Sandbox::map(LOCATE_DATA_PATH, "/world")).entryList(noHidden, QDir::Name),
QStringList()
<< "sandbox-only"
<< "world-and-sandbox"
<< "world-only-to-be-copied-into-sandbox");

QVERIFY(!QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/world-only")).exists());
QVERIFY(!QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/world-only")).exists());

QVERIFY(QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/world-and-sandbox")).isWritable());
QCOMPARE(readAll(Sandbox::map(TESTS_DATA_PATH "/world/world-and-sandbox")).trimmed(),
QVERIFY(QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/world-and-sandbox")).isWritable());
QCOMPARE(readAll(Sandbox::map(LOCATE_DATA_PATH, "/world/world-and-sandbox")).trimmed(),
QString("sandbox/world-and-sandbox"));

QVERIFY(QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox"))
QVERIFY(QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/world-only-to-be-copied-into-sandbox"))
.isWritable());
QCOMPARE(readAll(Sandbox::map(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox"))
QCOMPARE(readAll(Sandbox::map(LOCATE_DATA_PATH, "/world/world-only-to-be-copied-into-sandbox"))
.trimmed(), QString("world/world-only-to-be-copied-into-sandbox"));

QVERIFY(QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/sandbox-only")).exists());
QVERIFY(QFileInfo(Sandbox::map(TESTS_DATA_PATH "/world/sandbox-only")).isWritable());
QCOMPARE(readAll(Sandbox::map(TESTS_DATA_PATH "/world/sandbox-only")).trimmed(),
QVERIFY(QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/sandbox-only")).exists());
QVERIFY(QFileInfo(Sandbox::map(LOCATE_DATA_PATH, "/world/sandbox-only")).isWritable());
QCOMPARE(readAll(Sandbox::map(LOCATE_DATA_PATH, "/world/sandbox-only")).trimmed(),
QString("sandbox/sandbox-only"));
}

Expand Down
6 changes: 5 additions & 1 deletion tests/ut_ssucli/ssuclitest.cpp
Expand Up @@ -20,11 +20,15 @@ typedef QStringList Args; // improve readability
void SsuCliTest::init(){
Q_ASSERT(m_sandbox == 0);

m_sandbox = new Sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH),
m_sandbox = new Sandbox(QString("%1/configroot").arg(LOCATE_DATA_PATH),
Sandbox::UseAsSkeleton, Sandbox::ChildProcesses);
if (!m_sandbox->activate()){
QFAIL("Failed to activate sandbox");
}
if (getenv("SSU_SANDBOX_PATH")){
qDebug() << "Using in-tree sandbox";
setenv("LD_PRELOAD", getenv("SSU_SANDBOX_PATH"), 1);
} else
setenv("LD_PRELOAD", qPrintable(QString("%1/libsandboxhook.so").arg(TESTS_PATH)), 1);

m_bus = new QProcess(this);
Expand Down
6 changes: 5 additions & 1 deletion tests/ut_ssuurlresolver/ssuurlresolvertest.cpp
Expand Up @@ -22,11 +22,15 @@
*/

void SsuUrlResolverTest::initTestCase(){
m_sandbox = new Sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH),
m_sandbox = new Sandbox(QString("%1/configroot").arg(LOCATE_DATA_PATH),
Sandbox::UseDirectly, Sandbox::ChildProcesses);
if (!m_sandbox->activate()){
QFAIL("Failed to activate sandbox");
}
if (getenv("SSU_SANDBOX_PATH")){
qDebug() << "Using in-tree sandbox";
setenv("LD_PRELOAD", getenv("SSU_SANDBOX_PATH"), 1);
} else
setenv("LD_PRELOAD", qPrintable(QString("%1/libsandboxhook.so").arg(TESTS_PATH)), 1);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ut_urlresolver/main.cpp
Expand Up @@ -11,7 +11,7 @@
#include "urlresolvertest.cpp"

int main(int argc, char **argv){
Sandbox sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH),
Sandbox sandbox(QString("%1/configroot").arg(LOCATE_DATA_PATH),
Sandbox::UseAsSkeleton, Sandbox::ThisProcess);
if (!sandbox.activate()){
qFatal("Failed to activate sandbox");
Expand Down
4 changes: 2 additions & 2 deletions tests/ut_urlresolver/urlresolvertest.cpp
Expand Up @@ -142,7 +142,7 @@ void UrlResolverTest::checkRegisterDevice(){
QVERIFY2(!ssu.registerDevice(&doc),
"Ssu::registerDevice() should fail when 'certificate' is empty");

QFile certificateFile(TESTS_DATA_PATH "/mycert.crt");
QFile certificateFile(QString("%1/mycert.crt").arg(LOCATE_DATA_PATH));
QVERIFY(certificateFile.open(QIODevice::ReadOnly));

certificate.appendChild(doc.createTextNode(certificateFile.readAll()));
Expand All @@ -153,7 +153,7 @@ void UrlResolverTest::checkRegisterDevice(){
QVERIFY2(!ssu.registerDevice(&doc),
"Ssu::registerDevice() should fail when 'privateKey' is empty");

QFile privateKeyFile(TESTS_DATA_PATH "/mykey.key");
QFile privateKeyFile(QString("%1/mykey.key").arg(LOCATE_DATA_PATH));
QVERIFY(privateKeyFile.open(QIODevice::ReadOnly));

privateKey.appendChild(doc.createTextNode(privateKeyFile.readAll()));
Expand Down

0 comments on commit c687b53

Please sign in to comment.