Commit 4e581b3e authored by Aard's avatar Aard

Add basic variable resolver and unit tests

parent d2188384
......@@ -6,11 +6,11 @@
*/
#include <QStringList>
#include <QRegExp>
#include <QStringRef>
#include "ssuvariables.h"
// TODO: Add a simple variable parser to allow variable substitution; it should
// get called in the resolve sections
SsuVariables::SsuVariables(): QObject() {
}
......@@ -25,3 +25,80 @@ void SsuVariables::resolveSection(QSettings *settings, QString section, QHash<QS
}
settings->endGroup();
}
QString SsuVariables::resolveString(QString pattern, QHash<QString, QString> *variables){
QRegExp regex("%\\\([^%]*\\\)", Qt::CaseSensitive, QRegExp::RegExp2);
regex.setMinimal(true);
int pos = 0;
while ((pos = regex.indexIn(pattern, pos)) != -1){
QString match = regex.cap(0);
if (match.contains(":")){
// variable is special, resolve before replacing
QString variable = resolveVariable(match, variables);
pattern.replace(match, variable);
pos += variable.length();
} else {
// look up variable name in hashmap, and replace it with stored value,
// if found, or ""
QString variableName = match;
variableName.remove(0,2);
variableName.chop(1);
if (variables->contains(variableName)){
pattern.replace(match, variables->value(variableName));
pos += variables->value(variableName).length();
} else
pattern.replace(match, "");
}
}
// check if string still contains variables, and recurse
if (regex.indexIn(pattern, 0) != -1)
pattern = resolveString(pattern, variables);
return pattern;
}
QString SsuVariables::resolveVariable(QString variable, QHash<QString, QString> *variables){
QString variableValue = "";
if (variable.endsWith(")"))
variable.chop(1);
if (variable.startsWith("%("))
variable.remove(0,2);
// hunt for your colon
int magic = variable.indexOf(":");
// seems you misplaced your colon
if (magic == -1) return variable;
QStringRef variableName(&variable, 0, magic);
QStringRef variableSub(&variable, magic + 2, variable.length() - magic - 2);
// Fill in variable value for later tests, if it exists
if (variables->contains(variableName.toString()))
variableValue = variables->value(variableName.toString());
// find the operator who's after your colon
QChar op;
if (variable.length() >= magic +1)
op = variable.at(magic + 1);
switch(op.toAscii()){
case '-':
// substitute default value if variable is empty
if (variableValue == "")
return variableSub.toString();
break;
case '+':
// substitute default value if variable is not empty
if (variableValue != "")
return variableSub.toString();
break;
}
// no proper substitution found -> return default value
return variableValue;
}
......@@ -23,6 +23,14 @@ class SsuVariables: public QObject {
* QHash
*/
void resolveSection(QSettings *settings, QString section, QHash<QString, QString> *storageHash);
/**
* Resolve a whole string, containing several variables. Variables inside variables are allowed
*/
QString resolveString(QString pattern, QHash<QString, QString> *variables);
/**
* Resolve variables; variable can be passed as %(var) or var
*/
QString resolveVariable(QString variable, QHash<QString, QString> *variables);
};
#endif
TEMPLATE = subdirs
CONFIG += qt ordered coverage debug
SUBDIRS = ut_urlresolver
SUBDIRS = ut_urlresolver ut_variables
!include( tests.pri ) { error("Unable to find tests include") }
......
......@@ -8,5 +8,10 @@
<step expected_result="0">/opt/tests/ssu/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>
</case>
</set>
</suite>
</testdefinition>
/**
* @file main.cpp
* @copyright 2012 Jolla Ltd.
* @author Bernd Wachter <bernd.wachter@jollamobile.com>
* @date 2012
*/
#include <QtTest/QtTest>
#include "variablestest.h"
int main(int argc, char **argv){
VariablesTest variablesTest;
if (QTest::qExec(&variablesTest, argc, argv))
return 1;
return 0;
}
HEADERS = variablestest.h
SOURCES = main.cpp \
variablestest.cpp
TEMPLATE = app
TARGET = ut_variables
LIBS += -lssu
CONFIG -= app_bundle
CONFIG += console qtestlib
QT -= gui
QT += network testlib
!include( ../tests.pri ) { error("Unable to find tests include") }
unix:target.path = $${PREFIX}/$$TESTS_PATH
INSTALLS += target
!include( ../../buildpath.pri ) { error("Unable to find build path specification") }
/**
* @file variablestest.cpp
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bwachter@lart.info>
* @date 2013
*/
#include "variablestest.h"
void VariablesTest::initTestCase(){
variables.insert("packagesDomain", "packages.example.com");
variables.insert("releaseDomain", "releases.example.com");
variables.insert("rndProtocol", "https");
variables.insert("release", "devel");
variables.insert("arch", "armv8");
variables.insert("flavourName", "flavour");
urls.insert("http://%(packagesDomain)/releases/%(release)/jolla/%(arch)/",
"http://packages.example.com/releases/devel/jolla/armv8/");
urls.insert("%(rndProtocol)://%(releaseDomain)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https://releases.example.com/nemo/devel-flavour/platform/armv8/");
// test missing operator, which should fall back to just variable value
urls.insert("%(rndProtocol)://%(unsetDomain:)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https:///nemo/devel-flavour/platform/armv8/");
urls.insert("%(rndProtocol)://%(releaseDomain:)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https://releases.example.com/nemo/devel-flavour/platform/armv8/");
urls.insert("%(rndProtocol)://%(releaseDomain:unset.example.com)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https://releases.example.com/nemo/devel-flavour/platform/armv8/");
// check if :- works
urls.insert("%(rndProtocol)://%(releaseDomain:-unset.example.com)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https://releases.example.com/nemo/devel-flavour/platform/armv8/");
urls.insert("%(rndProtocol)://%(unsetDomain:-unset.example.com)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https://unset.example.com/nemo/devel-flavour/platform/armv8/");
// test with empty replacement pattern
urls.insert("%(rndProtocol)://%(unsetDomain:-)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https:///nemo/devel-flavour/platform/armv8/");
// check if :+ works
// substitution of variable with set.example.com
urls.insert("%(rndProtocol)://%(releaseDomain:+set.example.com)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https://set.example.com/nemo/devel-flavour/platform/armv8/");
// substitution of variable with variable + /set
urls.insert("%(rndProtocol)://%(releaseDomain:+%(releaseDomain)/set)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https://releases.example.com/set/nemo/devel-flavour/platform/armv8/");
// substitution of variable with empty variable + /set -- should substitute to ""
urls.insert("%(rndProtocol)://%(unsetDomain:+%(unsetDomain)/set)/nemo/%(release)-%(flavourName)/platform/%(arch)/",
"https:///nemo/devel-flavour/platform/armv8/");
}
void VariablesTest::cleanupTestCase(){
}
void VariablesTest::checkResolveString(){
QHashIterator<QString, QString> i(urls);
while (i.hasNext()){
i.next();
QString result = var.resolveString(i.key(), &variables);
qDebug() << i.key() << " resolved to " << result;
QCOMPARE(result, i.value());
}
}
/**
* @file variablestest.h
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bwachter@lart.info>
* @date 2013
*/
#ifndef _VARIABLESTEST_H
#define _VARIABLESTEST_H
#include <QObject>
#include <QtTest/QtTest>
#include <QHash>
#include <ssu.h>
#include <ssuvariables.h>
class VariablesTest: public QObject {
Q_OBJECT
private slots:
void initTestCase();
void cleanupTestCase();
void checkResolveString();
private:
Ssu ssu;
SsuVariables var;
QHash <QString, QString> variables, urls;
};
#endif
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