Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add basic variable resolver and unit tests
  • Loading branch information
Bernd Wachter committed Mar 22, 2013
1 parent d218838 commit 4e581b3
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 3 deletions.
81 changes: 79 additions & 2 deletions libssu/ssuvariables.cpp
Expand Up @@ -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() {

}
Expand All @@ -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;
}
8 changes: 8 additions & 0 deletions libssu/ssuvariables.h
Expand Up @@ -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
2 changes: 1 addition & 1 deletion tests/tests.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
CONFIG += qt ordered coverage debug
SUBDIRS = ut_urlresolver
SUBDIRS = ut_urlresolver ut_variables

!include( tests.pri ) { error("Unable to find tests include") }

Expand Down
5 changes: 5 additions & 0 deletions tests/tests.xml
Expand Up @@ -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>
19 changes: 19 additions & 0 deletions tests/ut_variables/main.cpp
@@ -0,0 +1,19 @@
/**
* @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;
}
17 changes: 17 additions & 0 deletions tests/ut_variables/ut_variables.pro
@@ -0,0 +1,17 @@
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") }
63 changes: 63 additions & 0 deletions tests/ut_variables/variablestest.cpp
@@ -0,0 +1,63 @@
/**
* @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());
}
}
33 changes: 33 additions & 0 deletions tests/ut_variables/variablestest.h
@@ -0,0 +1,33 @@
/**
* @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

0 comments on commit 4e581b3

Please sign in to comment.