diff --git a/libssu/sandbox.cpp b/libssu/sandbox.cpp index f14c549..b73a224 100644 --- a/libssu/sandbox.cpp +++ b/libssu/sandbox.cpp @@ -17,7 +17,6 @@ #include #include "libssu/ssucoreconfig.h" -// TODO: rename to ssuconstants.h? #include "constants.h" class Sandbox::FileEngineHandler : public QAbstractFileEngineHandler { @@ -37,20 +36,35 @@ class Sandbox::FileEngineHandler : public QAbstractFileEngineHandler { /** * @class Sandbox + * @brief Simple sandboxing with Qt file system abstraction. * - * Redirects all file operations on system configuration files to files under - * sandbox directory. When constructed without arguments, the directory is get - * from @c SSU_TESTS_SANDBOX environment variable. + * Redirects all file operations on selected files to files under sandbox + * directory. The term world files is used to reffer files outside + * sandbox. + * + * Its effect is controlled by activate() and deactivate() calls. Only one + * Sandbox instance can be active at any time. Active sandbox is automatically + * deactivated upon destruction. + * + * When constructed without arguments, path to sandbox directory is get from + * @c SSU_TESTS_SANDBOX environment variable. + * + * @attention When constructed without arguments, it is activated automatically + * and failure to do so is reported with @c qFatal(), i.e., application will be + * abort()ed. * * When constructed with @a usage UseAsSkeleton, it will first make temporary * copy of @a sandboxPath to work on and files in the original directory will - * stay untouched. + * stay untouched. Also see addWorldFiles(). * * The argument @scopes allows to control if the sandbox will be used by this * process, its children processes (@c SSU_TESTS_SANDBOX environment variable * will be exported), or both. * * Internally it is based on QAbstractFileEngineHandler. + * + * @attention QDir lists entries presented in the world directory. The behavior + * changed with Qt 4.8.0 (Qt commit b9b55234a777c3b206332bafbe227e1355ca9186) */ Sandbox *Sandbox::s_activeInstance = 0; @@ -71,15 +85,15 @@ Sandbox::Sandbox(const QString &sandboxPath, Usage usage, Scopes scopes) } Sandbox::~Sandbox(){ - delete m_handler; + if (isActive()){ + deactivate(); + } if (!m_tempDir.isEmpty() && QFileInfo(m_tempDir).exists()){ if (QProcess::execute("rm", QStringList() << "-rf" << m_tempDir) != 0){ qWarning("%s: Failed to remove temporary directory", Q_FUNC_INFO); } } - - s_activeInstance = 0; } bool Sandbox::isActive() const{ @@ -105,6 +119,20 @@ bool Sandbox::activate(){ return true; } +void Sandbox::deactivate(){ + Q_ASSERT(isActive()); + + if (m_scopes & ThisProcess){ + delete m_handler; + } + + if (m_scopes & ChildProcesses){ + unsetenv("SSU_TESTS_SANDBOX"); + } + + s_activeInstance = 0; +} + /** * Copies selected files into sandbox. Existing files in sandbox are not overwriten. * @@ -119,7 +147,6 @@ bool Sandbox::addWorldFiles(const QString &directory, QDir::Filters filters, Q_ASSERT(!directory.contains("/./") && !directory.endsWith("/.") && !directory.contains("/../") && !directory.endsWith("/..") && !directory.contains("//")); - Q_ASSERT_X(!(m_scopes & ChildProcesses), Q_FUNC_INFO, "Unimplemented case!"); if (!prepare()){ return false; @@ -191,6 +218,11 @@ bool Sandbox::addWorldFiles(const QString &directory, QDir::Filters filters, return true; } +bool Sandbox::addWorldFile(const QString &file){ + return addWorldFiles(QFileInfo(file).path(), QDir::NoFilter, + QStringList() << QFileInfo(file).fileName()); +} + bool Sandbox::prepare(){ Q_ASSERT(m_defaultConstructed || !m_sandboxPath.isEmpty()); diff --git a/libssu/sandbox_p.h b/libssu/sandbox_p.h index 9963812..db7e87d 100644 --- a/libssu/sandbox_p.h +++ b/libssu/sandbox_p.h @@ -33,10 +33,12 @@ class Sandbox { ~Sandbox(); bool activate(); + void deactivate(); bool isActive() const; bool addWorldFiles(const QString &directory, QDir::Filters filters = QDir::NoFilter, const QStringList &filterNames = QStringList()); + bool addWorldFile(const QString &file); private: bool prepare(); diff --git a/libssu/ssu.h b/libssu/ssu.h index 0b1e32d..3e7e566 100644 --- a/libssu/ssu.h +++ b/libssu/ssu.h @@ -23,6 +23,8 @@ class QNetworkReply; class Ssu: public QObject { Q_OBJECT + friend class UrlResolverTest; + public: Ssu(); /** diff --git a/libssu/ssuvariables.cpp b/libssu/ssuvariables.cpp index 4132e4f..9ad0d21 100644 --- a/libssu/ssuvariables.cpp +++ b/libssu/ssuvariables.cpp @@ -89,7 +89,7 @@ QString SsuVariables::resolveVariable(QString variable, QHash // find the operator who's after your colon QChar op; - if (variable.length() >= magic +1) + if (variable.length() > magic +1) op = variable.at(magic + 1); switch(op.toAscii()){ diff --git a/tests/testapplication.pri b/tests/testapplication.pri index 4d8955e..cfce5c1 100644 --- a/tests/testapplication.pri +++ b/tests/testapplication.pri @@ -3,6 +3,9 @@ include(tests_common.pri) QT += testlib +test_data.path = $${TESTS_DATA_PATH} +INSTALLS += test_data + test_data_etc.path = $${TESTS_DATA_PATH}/configroot/etc/ssu test_data_usr_share.path = $${TESTS_DATA_PATH}/configroot/usr/share/ssu INSTALLS += test_data_etc test_data_usr_share diff --git a/tests/tests.pro b/tests/tests.pro index c87ba44..a4c143b 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -3,7 +3,11 @@ CONFIG += ordered coverage debug SUBDIRS = \ testutils \ testutils/sandboxhook.pro \ + ut_coreconfig \ + ut_deviceinfo \ + ut_repomanager \ ut_rndssucli \ + ut_sandbox \ ut_settings \ ut_ssuurlresolver \ ut_urlresolver \ diff --git a/tests/tests.xml b/tests/tests.xml index a75f6a8..3905174 100644 --- a/tests/tests.xml +++ b/tests/tests.xml @@ -3,11 +3,31 @@ + + + /opt/tests/ssu/runtest.sh ut_coreconfig + + + + + /opt/tests/ssu/runtest.sh ut_deviceinfo + + + + + /opt/tests/ssu/runtest.sh ut_repomanager + + /opt/tests/ssu/runtest.sh ut_rndssucli + + + /opt/tests/ssu/runtest.sh ut_sandbox + + /opt/tests/ssu/runtest.sh ut_settings diff --git a/tests/testutils/process.cpp b/tests/testutils/process.cpp index f2f27d5..5141bdb 100644 --- a/tests/testutils/process.cpp +++ b/tests/testutils/process.cpp @@ -25,7 +25,7 @@ Process::Process() : m_expectFail(false), m_timedOut(false) {} QString Process::execute(const QString &program, const QStringList &arguments, bool expectedResult){ - Q_ASSERT(processStatus() == NotRunning); + Q_ASSERT(m_process.state() == QProcess::NotRunning); m_program = program; m_arguments = arguments; m_expectFail = expectedResult == ExpectFail; @@ -42,7 +42,9 @@ bool Process::hasError(){ } QString Process::fmtErrorMessage(){ - Q_ASSERT(hasError()); + if (!hasError()){ + return QString(); + } QStringList reasons; if (m_timedOut){ diff --git a/tests/ut_coreconfig/coreconfigtest.cpp b/tests/ut_coreconfig/coreconfigtest.cpp new file mode 100644 index 0000000..1847751 --- /dev/null +++ b/tests/ut_coreconfig/coreconfigtest.cpp @@ -0,0 +1,86 @@ +/** + * @file coreconfigtest.cpp + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#include "coreconfigtest.h" + +#include + +#include "libssu/ssucoreconfig.h" + +void CoreconfigTest::testCredentialsScope(){ + QCOMPARE(SsuCoreConfig::instance()->credentialsScope("/*ignored*/", false), QString("example")); + +} + +void CoreconfigTest::testCredentials(){ + QCOMPARE(SsuCoreConfig::instance()->credentials("example").first, QString("example_username")); + QCOMPARE(SsuCoreConfig::instance()->credentials("example").second, QString("example_password")); +} + +void CoreconfigTest::testCredentialsUrl(){ + QCOMPARE(SsuCoreConfig::instance()->credentialsUrl("example"), QString("http://creden.tia.ls/")); +} + +void CoreconfigTest::testFlavour(){ + QCOMPARE(SsuCoreConfig::instance()->flavour(), QString("testing")); + SsuCoreConfig::instance()->setFlavour("release"); + QCOMPARE(SsuCoreConfig::instance()->flavour(), QString("release")); +} + +void CoreconfigTest::testDeviceMode(){ + SsuCoreConfig::instance()->remove("deviceMode"); + QCOMPARE(SsuCoreConfig::instance()->deviceMode(), (int)Ssu::ReleaseMode); + SsuCoreConfig::instance()->setDeviceMode(Ssu::ReleaseMode, Ssu::Add); + QCOMPARE(SsuCoreConfig::instance()->deviceMode(), (int)Ssu::ReleaseMode); + SsuCoreConfig::instance()->setDeviceMode(Ssu::LenientMode, Ssu::Add); + QCOMPARE(SsuCoreConfig::instance()->deviceMode(), (int)Ssu::ReleaseMode | Ssu::LenientMode); + SsuCoreConfig::instance()->setDeviceMode(Ssu::ReleaseMode, Ssu::Remove); + QCOMPARE(SsuCoreConfig::instance()->deviceMode(), (int)Ssu::LenientMode); + SsuCoreConfig::instance()->setDeviceMode(Ssu::ReleaseMode, Ssu::Replace); + QCOMPARE(SsuCoreConfig::instance()->deviceMode(), (int)Ssu::ReleaseMode); +} + +void CoreconfigTest::testDomain(){ + QCOMPARE(SsuCoreConfig::instance()->domain(), QString("")); + SsuCoreConfig::instance()->setDomain("foo"); + QCOMPARE(SsuCoreConfig::instance()->domain(), QString("foo")); +} + +void CoreconfigTest::testRegistered(){ + QCOMPARE(SsuCoreConfig::instance()->isRegistered(), false); + SsuCoreConfig::instance()->setValue("registered", true); + QCOMPARE(SsuCoreConfig::instance()->isRegistered(), false); + SsuCoreConfig::instance()->setValue("privateKey", "fooKey"); + QCOMPARE(SsuCoreConfig::instance()->isRegistered(), false); + SsuCoreConfig::instance()->setValue("certificate", "fooCert"); + QCOMPARE(SsuCoreConfig::instance()->isRegistered(), true); +} + +void CoreconfigTest::testLastCredentialsUpdate(){ + QCOMPARE(SsuCoreConfig::instance()->lastCredentialsUpdate(), QDateTime()); + SsuCoreConfig::instance()->setValue("lastCredentialsUpdate", + QDateTime::fromString("2013-04-08", Qt::ISODate)); + QCOMPARE(SsuCoreConfig::instance()->lastCredentialsUpdate(), + QDateTime::fromString("2013-04-08", Qt::ISODate)); +} + +void CoreconfigTest::testRelease(){ + QCOMPARE(SsuCoreConfig::instance()->release(false), QString("latest")); + QCOMPARE(SsuCoreConfig::instance()->release(true), QString("next")); + SsuCoreConfig::instance()->setRelease("next", false); + QCOMPARE(SsuCoreConfig::instance()->release(false), QString("next")); + QCOMPARE(SsuCoreConfig::instance()->release(true), QString("next")); + SsuCoreConfig::instance()->setRelease("latest", true); + QCOMPARE(SsuCoreConfig::instance()->release(false), QString("next")); + QCOMPARE(SsuCoreConfig::instance()->release(true), QString("latest")); +} + +void CoreconfigTest::testSslVerify(){ + QCOMPARE(SsuCoreConfig::instance()->useSslVerify(), true); + SsuCoreConfig::instance()->setValue("ssl-verify", false); + QCOMPARE(SsuCoreConfig::instance()->useSslVerify(), false); +} diff --git a/tests/ut_coreconfig/coreconfigtest.h b/tests/ut_coreconfig/coreconfigtest.h new file mode 100644 index 0000000..1206d01 --- /dev/null +++ b/tests/ut_coreconfig/coreconfigtest.h @@ -0,0 +1,29 @@ +/** + * @file coreconfigtest.h + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#ifndef _CORECONFIGTEST_H +#define _CORECONFIGTEST_H + +#include + +class CoreconfigTest: public QObject { + Q_OBJECT + + private slots: + void testCredentialsScope(); + void testCredentials(); + void testCredentialsUrl(); + void testFlavour(); + void testDeviceMode(); + void testDomain(); + void testRegistered(); + void testLastCredentialsUpdate(); + void testRelease(); + void testSslVerify(); +}; + +#endif diff --git a/tests/ut_coreconfig/main.cpp b/tests/ut_coreconfig/main.cpp new file mode 100644 index 0000000..6fc2205 --- /dev/null +++ b/tests/ut_coreconfig/main.cpp @@ -0,0 +1,26 @@ +/** + * @file main.cpp + * @copyright 2012 Jolla Ltd. + * @author Martin Kampas + * @date 2012 + */ + +#include + +#include "libssu/sandbox_p.h" +#include "coreconfigtest.h" + +int main(int argc, char **argv){ + Sandbox sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH), + Sandbox::UseAsSkeleton, Sandbox::ThisProcess); + if (!sandbox.activate()){ + qFatal("Failed to activate sandbox"); + } + + CoreconfigTest coreconfigTest; + + if (QTest::qExec(&coreconfigTest, argc, argv)) + return 1; + + return 0; +} diff --git a/tests/ut_coreconfig/testdata/ssu-defaults.ini b/tests/ut_coreconfig/testdata/ssu-defaults.ini new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/tests/ut_coreconfig/testdata/ssu-defaults.ini @@ -0,0 +1 @@ +# empty diff --git a/tests/ut_coreconfig/testdata/ssu.ini b/tests/ut_coreconfig/testdata/ssu.ini new file mode 100644 index 0000000..2f87b9c --- /dev/null +++ b/tests/ut_coreconfig/testdata/ssu.ini @@ -0,0 +1,18 @@ +[General] +initialized=true +flavour=testing +registered=false +rndRelease=next +release=latest +adaptation= +ca-certificate= +credentials-scope=example +credentials-url-example = http://creden.tia.ls/ + +[credentials-example] +username = example_username +password = example_password + +[repository-urls] + +[repository-url-variables] diff --git a/tests/ut_coreconfig/ut_coreconfig.pro b/tests/ut_coreconfig/ut_coreconfig.pro new file mode 100644 index 0000000..45fecf9 --- /dev/null +++ b/tests/ut_coreconfig/ut_coreconfig.pro @@ -0,0 +1,16 @@ +TARGET = ut_coreconfig +include(../testapplication.pri) +include(ut_coreconfig_dependencies.pri) + +HEADERS = \ + coreconfigtest.h \ + +SOURCES = \ + main.cpp \ + coreconfigtest.cpp \ + +test_data_etc.files = \ + testdata/ssu.ini \ + +test_data_usr_share.files = \ + testdata/ssu-defaults.ini \ diff --git a/tests/ut_coreconfig/ut_coreconfig_dependencies.pri b/tests/ut_coreconfig/ut_coreconfig_dependencies.pri new file mode 100644 index 0000000..5e56454 --- /dev/null +++ b/tests/ut_coreconfig/ut_coreconfig_dependencies.pri @@ -0,0 +1,2 @@ +include(../../libssu/libssu.pri) +include(../testutils/testutils.pri) diff --git a/tests/ut_deviceinfo/deviceinfotest.cpp b/tests/ut_deviceinfo/deviceinfotest.cpp new file mode 100644 index 0000000..e51853d --- /dev/null +++ b/tests/ut_deviceinfo/deviceinfotest.cpp @@ -0,0 +1,71 @@ +/** + * @file deviceinfotest.cpp + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#include "deviceinfotest.h" + +#include + +#include "libssu/ssudeviceinfo.h" + +void DeviceInfoTest::testAdaptationVariables(){ + SsuDeviceInfo deviceInfo("N950"); + QHash variables; + QHash variablesExpected; + variablesExpected["adaptation"] = "n950-n9"; + variablesExpected["foo-n9"] = "foo-n9-val"; + variablesExpected["foo-n950-n9"] = "foo-n950-n9-val"; + + QString repoName = deviceInfo.adaptationVariables("adaptation1", &variables); + + QCOMPARE(variables, variablesExpected); + QCOMPARE(repoName, QString("adaptation")); +} + +void DeviceInfoTest::testDeviceUid(){ + QVERIFY2(!SsuDeviceInfo().deviceUid().isEmpty(), "No method to get device UID on this platform"); +} + +void DeviceInfoTest::testVariableSection(){ + SsuDeviceInfo deviceInfo; + + QHash fooVars; + QHash fooVarsExpected; + fooVarsExpected["foo1"] = "foo1Val"; + fooVarsExpected["foo2"] = "foo2Val"; + + deviceInfo.variableSection("foo", &fooVars); + + QCOMPARE(fooVars, fooVarsExpected); + + QHash barVars; + QHash barVarsExpected; + barVarsExpected["bar1"] = "bar1Val"; + barVarsExpected["bar2"] = "bar2Val"; + + deviceInfo.variableSection("bar", &barVars); + + QCOMPARE(barVars, barVarsExpected); + + QHash bazVars; + QHash bazVarsExpected; + bazVarsExpected["foo1"] = "foo1Val"; + bazVarsExpected["foo2"] = "foo2Val"; + bazVarsExpected["bar1"] = "bar1Val"; + bazVarsExpected["bar2"] = "bar2Val"; + + deviceInfo.variableSection("baz", &bazVars); + + QCOMPARE(bazVars, bazVarsExpected); +} + +void DeviceInfoTest::testValue(){ + SsuDeviceInfo deviceInfo("N950"); + QCOMPARE(deviceInfo.value("family").toString(), QString("n950-n9")); + QCOMPARE(deviceInfo.value("adaptation-repos").toStringList(), + QString("n9xx-common,n950-n9").split(',')); + QCOMPARE(deviceInfo.value("foo").toString(), QString("n950-foo")); +} diff --git a/tests/ut_deviceinfo/deviceinfotest.h b/tests/ut_deviceinfo/deviceinfotest.h new file mode 100644 index 0000000..58da514 --- /dev/null +++ b/tests/ut_deviceinfo/deviceinfotest.h @@ -0,0 +1,23 @@ +/** + * @file deviceinfotest.h + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#ifndef _DEVICEINFOTEST_H +#define _DEVICEINFOTEST_H + +#include + +class DeviceInfoTest: public QObject { + Q_OBJECT + + private slots: + void testAdaptationVariables(); + void testDeviceUid(); + void testVariableSection(); + void testValue(); +}; + +#endif diff --git a/tests/ut_deviceinfo/main.cpp b/tests/ut_deviceinfo/main.cpp new file mode 100644 index 0000000..1e363a9 --- /dev/null +++ b/tests/ut_deviceinfo/main.cpp @@ -0,0 +1,26 @@ +/** + * @file main.cpp + * @copyright 2012 Jolla Ltd. + * @author Martin Kampas + * @date 2012 + */ + +#include + +#include "libssu/sandbox_p.h" +#include "deviceinfotest.h" + +int main(int argc, char **argv){ + Sandbox sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH), + Sandbox::UseAsSkeleton, Sandbox::ThisProcess); + if (!sandbox.activate()){ + qFatal("Failed to activate sandbox"); + } + + DeviceInfoTest deviceinfoTest; + + if (QTest::qExec(&deviceinfoTest, argc, argv)) + return 1; + + return 0; +} diff --git a/tests/ut_deviceinfo/testdata/board-mappings.ini b/tests/ut_deviceinfo/testdata/board-mappings.ini new file mode 100644 index 0000000..4648fce --- /dev/null +++ b/tests/ut_deviceinfo/testdata/board-mappings.ini @@ -0,0 +1,53 @@ +[file.exists] +SDK=/mer-sdk-chroot + +[systeminfo.equals] + +[cpuinfo.contains] +N900=Nokia RX-51 board +N950=Nokia RM-680 board +N9=Nokia RM-696 board + +[arch.equals] +generic-x86=i586 + +[variants] +N950=N9 + +[N9] +family=n950-n9 +adaptation-repos=n9xx-common,n950-n9 +variables = n9 + +[var-n9] +foo-n9 = foo-n9-val + +[var-n950-n9] +foo-n950-n9 = foo-n950-n9-val + +[N900] +family=n900 +adaptation-repos=n9xx-common,n900 + +[N950] +foo = n950-foo + +[SDK] + +[generic-x86] +family=x86 +adaptation-repos=x86 + +[UNKNOWN] +family=UNKNOWN + +[var-foo] +foo1 = foo1Val +foo2 = foo2Val + +[var-bar] +bar1 = bar1Val +bar2 = bar2Val + +[var-baz] +variables = foo, bar diff --git a/tests/ut_deviceinfo/testdata/repos.ini b/tests/ut_deviceinfo/testdata/repos.ini new file mode 100644 index 0000000..60744db --- /dev/null +++ b/tests/ut_deviceinfo/testdata/repos.ini @@ -0,0 +1,32 @@ +[all] +credentials=jolla +credentials-url=https://%(ssuRegDomain)/%(ssuRegPath)/%1/credentials.xml +register-url=https://%(ssuRegDomain)/%(ssuRegPath)/%1/register.xml + +[release] +mer-core=https://%(packagesDomain)/%(release)/mer/%(arch)/%(debugSplit)/ + +[rnd] +mer-core=https://%(packagesDomain)/mer/%(release)/builds/%(arch)/%(debugSplit)/ + +[devel-flavour] +flavour-pattern= + +[release-flavour] +flavour-pattern=:/release + +[testing-flavour] +flavour-pattern=:/testing + +[example-domain] +dumpDomain=dump.example.com +packagesDomain=packages.example.com +ssuRegDomain=ssu.example.com +ssuRegPath=ssu/device + +# fallback if domain is not matched or not set +[default-domain] +dumpDomain=dump.testing.com +packagesDomain=packages.testing.com +ssuRegDomain=ssu.testing.com +ssuRegPath=ssu/device diff --git a/tests/ut_deviceinfo/testdata/ssu-defaults.ini b/tests/ut_deviceinfo/testdata/ssu-defaults.ini new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/tests/ut_deviceinfo/testdata/ssu-defaults.ini @@ -0,0 +1 @@ +# empty diff --git a/tests/ut_deviceinfo/testdata/ssu.ini b/tests/ut_deviceinfo/testdata/ssu.ini new file mode 100644 index 0000000..2f87b9c --- /dev/null +++ b/tests/ut_deviceinfo/testdata/ssu.ini @@ -0,0 +1,18 @@ +[General] +initialized=true +flavour=testing +registered=false +rndRelease=next +release=latest +adaptation= +ca-certificate= +credentials-scope=example +credentials-url-example = http://creden.tia.ls/ + +[credentials-example] +username = example_username +password = example_password + +[repository-urls] + +[repository-url-variables] diff --git a/tests/ut_deviceinfo/ut_deviceinfo.pro b/tests/ut_deviceinfo/ut_deviceinfo.pro new file mode 100644 index 0000000..02c0d4b --- /dev/null +++ b/tests/ut_deviceinfo/ut_deviceinfo.pro @@ -0,0 +1,18 @@ +TARGET = ut_deviceinfo +include(../testapplication.pri) +include(ut_deviceinfo_dependencies.pri) + +HEADERS = \ + deviceinfotest.h \ + +SOURCES = \ + main.cpp \ + deviceinfotest.cpp \ + +test_data_etc.files = \ + testdata/ssu.ini \ + +test_data_usr_share.files = \ + testdata/ssu-defaults.ini \ + testdata/board-mappings.ini \ + testdata/repos.ini \ diff --git a/tests/ut_deviceinfo/ut_deviceinfo_dependencies.pri b/tests/ut_deviceinfo/ut_deviceinfo_dependencies.pri new file mode 100644 index 0000000..37c741f --- /dev/null +++ b/tests/ut_deviceinfo/ut_deviceinfo_dependencies.pri @@ -0,0 +1 @@ +include(../../libssu/libssu.pri) diff --git a/tests/ut_repomanager/main.cpp b/tests/ut_repomanager/main.cpp new file mode 100644 index 0000000..bf999f6 --- /dev/null +++ b/tests/ut_repomanager/main.cpp @@ -0,0 +1,26 @@ +/** + * @file main.cpp + * @copyright 2012 Jolla Ltd. + * @author Martin Kampas + * @date 2012 + */ + +#include + +#include "libssu/sandbox_p.h" +#include "repomanagertest.h" + +int main(int argc, char **argv){ + Sandbox sandbox(QString("%1/configroot").arg(TESTS_DATA_PATH), + Sandbox::UseAsSkeleton, Sandbox::ThisProcess); + if (!sandbox.activate()){ + qFatal("Failed to activate sandbox"); + } + + RepoManagerTest repomanagerTest; + + if (QTest::qExec(&repomanagerTest, argc, argv)) + return 1; + + return 0; +} diff --git a/tests/ut_repomanager/repomanagertest.cpp b/tests/ut_repomanager/repomanagertest.cpp new file mode 100644 index 0000000..3160a30 --- /dev/null +++ b/tests/ut_repomanager/repomanagertest.cpp @@ -0,0 +1,91 @@ +/** + * @file repomanagertest.cpp + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#include "repomanagertest.h" + +#include + +#include "libssu/ssucoreconfig.h" +#include "libssu/ssurepomanager.h" + +void RepoManagerTest::testSettings(){ + SsuCoreConfig *const coreConfig = SsuCoreConfig::instance(); + SsuRepoManager repoManager; + + repoManager.add("repo1", "http://repo1"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + + repoManager.enable("repo1"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + + repoManager.add("repo1"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + + repoManager.disable("repo1"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(coreConfig->value("disabled-repos").toStringList().contains("repo1")); + + repoManager.enable("repo1"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + + repoManager.add("repo2", "http://repo2"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + QCOMPARE(coreConfig->value("repository-urls/repo2").toString(), QString("http://repo2")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo2")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo2")); + + repoManager.disable("repo2"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + QCOMPARE(coreConfig->value("repository-urls/repo2").toString(), QString("http://repo2")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo2")); + QVERIFY(coreConfig->value("disabled-repos").toStringList().contains("repo2")); + + repoManager.enable("repo2"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + QCOMPARE(coreConfig->value("repository-urls/repo2").toString(), QString("http://repo2")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo2")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo2")); + + repoManager.add("repo2"); + QCOMPARE(coreConfig->value("repository-urls/repo1").toString(), QString("http://repo1")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + QCOMPARE(coreConfig->value("repository-urls/repo2").toString(), QString("http://repo2")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo2")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo2")); + + repoManager.remove("repo1"); + QVERIFY(!coreConfig->contains("repository-urls/repo1")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + QCOMPARE(coreConfig->value("repository-urls/repo2").toString(), QString("http://repo2")); + QVERIFY(coreConfig->value("enabled-repos").toStringList().contains("repo2")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo2")); + + repoManager.remove("repo2"); + QVERIFY(!coreConfig->contains("repository-urls/repo1")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo1")); + QVERIFY(!coreConfig->contains("repository-urls/repo2")); + QVERIFY(!coreConfig->value("enabled-repos").toStringList().contains("repo2")); + QVERIFY(!coreConfig->value("disabled-repos").toStringList().contains("repo2")); +} diff --git a/tests/ut_repomanager/repomanagertest.h b/tests/ut_repomanager/repomanagertest.h new file mode 100644 index 0000000..3ff0d9a --- /dev/null +++ b/tests/ut_repomanager/repomanagertest.h @@ -0,0 +1,20 @@ +/** + * @file repomanagertest.h + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#ifndef _REPOMANAGERTEST_H +#define _REPOMANAGERTEST_H + +#include + +class RepoManagerTest: public QObject { + Q_OBJECT + + private slots: + void testSettings(); +}; + +#endif diff --git a/tests/ut_repomanager/testdata/ssu-defaults.ini b/tests/ut_repomanager/testdata/ssu-defaults.ini new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/tests/ut_repomanager/testdata/ssu-defaults.ini @@ -0,0 +1 @@ +# empty diff --git a/tests/ut_repomanager/testdata/ssu.ini b/tests/ut_repomanager/testdata/ssu.ini new file mode 100644 index 0000000..82346d1 --- /dev/null +++ b/tests/ut_repomanager/testdata/ssu.ini @@ -0,0 +1,14 @@ +[General] +initialized=true +flavour=testing +registered=false +rndRelease=next +release=latest +adaptation= +ca-certificate= +credentials-scope=example +credentials-url-example = http://creden.tia.ls/ + +[repository-urls] + +[repository-url-variables] diff --git a/tests/ut_repomanager/ut_repomanager.pro b/tests/ut_repomanager/ut_repomanager.pro new file mode 100644 index 0000000..30b9bef --- /dev/null +++ b/tests/ut_repomanager/ut_repomanager.pro @@ -0,0 +1,16 @@ +TARGET = ut_repomanager +include(../testapplication.pri) +include(ut_repomanager_dependencies.pri) + +HEADERS = \ + repomanagertest.h \ + +SOURCES = \ + main.cpp \ + repomanagertest.cpp \ + +test_data_etc.files = \ + testdata/ssu.ini \ + +test_data_usr_share.files = \ + testdata/ssu-defaults.ini \ diff --git a/tests/ut_repomanager/ut_repomanager_dependencies.pri b/tests/ut_repomanager/ut_repomanager_dependencies.pri new file mode 100644 index 0000000..37c741f --- /dev/null +++ b/tests/ut_repomanager/ut_repomanager_dependencies.pri @@ -0,0 +1 @@ +include(../../libssu/libssu.pri) diff --git a/tests/ut_rndssucli/rndssuclitest.h b/tests/ut_rndssucli/rndssuclitest.h index 1fc5617..aee55f4 100644 --- a/tests/ut_rndssucli/rndssuclitest.h +++ b/tests/ut_rndssucli/rndssuclitest.h @@ -15,6 +15,9 @@ class Sandbox; class RndSsuCliTest: public QObject { Q_OBJECT + public: + RndSsuCliTest(): m_sandbox(0) {} + private slots: void init(); void cleanup(); diff --git a/tests/ut_sandbox/main.cpp b/tests/ut_sandbox/main.cpp new file mode 100644 index 0000000..2dae6a3 --- /dev/null +++ b/tests/ut_sandbox/main.cpp @@ -0,0 +1,19 @@ +/** + * @file main.cpp + * @copyright 2012 Jolla Ltd. + * @author Martin Kampas + * @date 2012 + */ + +#include + +#include "sandboxtest.h" + +int main(int argc, char **argv){ + SandboxTest sandboxTest; + + if (QTest::qExec(&sandboxTest, argc, argv)) + return 1; + + return 0; +} diff --git a/tests/ut_sandbox/sandboxtest.cpp b/tests/ut_sandbox/sandboxtest.cpp new file mode 100644 index 0000000..72058cf --- /dev/null +++ b/tests/ut_sandbox/sandboxtest.cpp @@ -0,0 +1,79 @@ +/** + * @file sandboxtest.cpp + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#include "sandboxtest.h" + +#include + +#include "libssu/sandbox_p.h" + +void SandboxTest::test(){ + + const QDir::Filters noHidden = QDir::AllEntries | QDir::NoDotAndDotDot; + + QCOMPARE(QDir(TESTS_DATA_PATH "/world").entryList(noHidden, QDir::Name), + QStringList() + << "world-and-sandbox" + << "world-only" + << "world-only-to-be-copied-into-sandbox"); + + QVERIFY(!QFileInfo(TESTS_DATA_PATH "/world/world-only").isWritable()); + QCOMPARE(readAll(TESTS_DATA_PATH "/world/world-only").trimmed(), + QString("world/world-only")); + + QVERIFY(!QFileInfo(TESTS_DATA_PATH "/world/world-and-sandbox").isWritable()); + QCOMPARE(readAll(TESTS_DATA_PATH "/world/world-and-sandbox").trimmed(), + QString("world/world-and-sandbox")); + + QVERIFY(!QFileInfo(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox").isWritable()); + QCOMPARE(readAll(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox").trimmed(), + QString("world/world-only-to-be-copied-into-sandbox")); + + QVERIFY(!QFileInfo(TESTS_DATA_PATH "/world/sandbox-only").exists()); + + + Sandbox sandbox(TESTS_DATA_PATH "/sandbox", + Sandbox::UseAsSkeleton, Sandbox::ThisProcess | Sandbox::ChildProcesses); + sandbox.addWorldFiles(TESTS_DATA_PATH "/world", QDir::AllEntries, + QStringList() << "*-to-be-copied-into-sandbox"); + QVERIFY(sandbox.activate()); + + + QCOMPARE(QDir(TESTS_DATA_PATH "/world").entryList(noHidden, QDir::Name), + QStringList() + << "world-and-sandbox" + << "world-only" + << "world-only-to-be-copied-into-sandbox"); + + QVERIFY(!QFileInfo(TESTS_DATA_PATH "/world/world-only").isWritable()); + QCOMPARE(readAll(TESTS_DATA_PATH "/world/world-only").trimmed(), + QString("world/world-only")); + + QVERIFY(QFileInfo(TESTS_DATA_PATH "/world/world-and-sandbox").isWritable()); + QCOMPARE(readAll(TESTS_DATA_PATH "/world/world-and-sandbox").trimmed(), + QString("sandbox/world-and-sandbox")); + + QVERIFY(QFileInfo(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox").isWritable()); + QCOMPARE(readAll(TESTS_DATA_PATH "/world/world-only-to-be-copied-into-sandbox").trimmed(), + QString("world/world-only-to-be-copied-into-sandbox")); + + QVERIFY(QFileInfo(TESTS_DATA_PATH "/world/sandbox-only").exists()); + QVERIFY(QFileInfo(TESTS_DATA_PATH "/world/sandbox-only").isWritable()); + QCOMPARE(readAll(TESTS_DATA_PATH "/world/sandbox-only").trimmed(), + QString("sandbox/sandbox-only")); +} + +QString SandboxTest::readAll(const QString &fileName){ + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)){ + qWarning("%s: Failed to open file for reading: '%s': %s", Q_FUNC_INFO, qPrintable(fileName), + qPrintable(file.errorString())); + return QString(); + } + + return file.readAll(); +} diff --git a/tests/ut_sandbox/sandboxtest.h b/tests/ut_sandbox/sandboxtest.h new file mode 100644 index 0000000..dbb0e15 --- /dev/null +++ b/tests/ut_sandbox/sandboxtest.h @@ -0,0 +1,23 @@ +/** + * @file sandboxtest.h + * @copyright 2013 Jolla Ltd. + * @author Martin Kampas + * @date 2013 + */ + +#ifndef _SANDBOXTEST_H +#define _SANDBOXTEST_H + +#include + +class SandboxTest: public QObject { + Q_OBJECT + + private slots: + void test(); + + private: + static QString readAll(const QString &fileName); +}; + +#endif diff --git a/tests/ut_sandbox/testdata/sandbox/sandbox-only b/tests/ut_sandbox/testdata/sandbox/sandbox-only new file mode 100644 index 0000000..f34c895 --- /dev/null +++ b/tests/ut_sandbox/testdata/sandbox/sandbox-only @@ -0,0 +1 @@ +sandbox/sandbox-only diff --git a/tests/ut_sandbox/testdata/sandbox/world-and-sandbox b/tests/ut_sandbox/testdata/sandbox/world-and-sandbox new file mode 100644 index 0000000..cb58395 --- /dev/null +++ b/tests/ut_sandbox/testdata/sandbox/world-and-sandbox @@ -0,0 +1 @@ +sandbox/world-and-sandbox diff --git a/tests/ut_sandbox/testdata/world/world-and-sandbox b/tests/ut_sandbox/testdata/world/world-and-sandbox new file mode 100644 index 0000000..1e04375 --- /dev/null +++ b/tests/ut_sandbox/testdata/world/world-and-sandbox @@ -0,0 +1 @@ +world/world-and-sandbox diff --git a/tests/ut_sandbox/testdata/world/world-only b/tests/ut_sandbox/testdata/world/world-only new file mode 100644 index 0000000..43ddf9c --- /dev/null +++ b/tests/ut_sandbox/testdata/world/world-only @@ -0,0 +1 @@ +world/world-only diff --git a/tests/ut_sandbox/testdata/world/world-only-to-be-copied-into-sandbox b/tests/ut_sandbox/testdata/world/world-only-to-be-copied-into-sandbox new file mode 100644 index 0000000..d8b09bc --- /dev/null +++ b/tests/ut_sandbox/testdata/world/world-only-to-be-copied-into-sandbox @@ -0,0 +1 @@ +world/world-only-to-be-copied-into-sandbox diff --git a/tests/ut_sandbox/ut_sandbox.pro b/tests/ut_sandbox/ut_sandbox.pro new file mode 100644 index 0000000..03c34bb --- /dev/null +++ b/tests/ut_sandbox/ut_sandbox.pro @@ -0,0 +1,23 @@ +TARGET = ut_sandbox +include(../testapplication.pri) +include(ut_sandbox_dependencies.pri) + +HEADERS = \ + sandboxtest.h \ + +SOURCES = \ + main.cpp \ + sandboxtest.cpp \ + +test_data_world.path = $${TESTS_DATA_PATH}/world +test_data_world.files = \ + testdata/world/world-only \ + testdata/world/world-and-sandbox \ + testdata/world/world-only-to-be-copied-into-sandbox \ + +test_data_sandbox.path = $${TESTS_DATA_PATH}/sandbox/$${test_data_world.path} +test_data_sandbox.files = \ + testdata/sandbox/world-and-sandbox \ + testdata/sandbox/sandbox-only \ + +INSTALLS += test_data_world test_data_sandbox diff --git a/tests/ut_sandbox/ut_sandbox_dependencies.pri b/tests/ut_sandbox/ut_sandbox_dependencies.pri new file mode 100644 index 0000000..37c741f --- /dev/null +++ b/tests/ut_sandbox/ut_sandbox_dependencies.pri @@ -0,0 +1 @@ +include(../../libssu/libssu.pri) diff --git a/tests/ut_settings/settingstest.cpp b/tests/ut_settings/settingstest.cpp index 079103f..0fd8cfd 100644 --- a/tests/ut_settings/settingstest.cpp +++ b/tests/ut_settings/settingstest.cpp @@ -112,13 +112,13 @@ void SettingsTest::testUpgrade_data(){ const QString key = group.isEmpty() ? testCase.key() : group + '/' + testCase.key(); QTest::newRow(qPrintable(QString("%1%2:%3:%4") .arg(group.isEmpty() ? "" : group + "/") - .arg(testCase.history) - .arg(testCase.current) - .arg(testCase.expected))) + .arg(testCase.history()) + .arg(testCase.current()) + .arg(testCase.expected()))) << ssuSettings.contains(key) << testCase.keyShouldBeSet() << ssuSettings.value(key).toString() - << testCase.expected; + << testCase.expected(); } } } diff --git a/tests/ut_settings/upgradetesthelper.cpp b/tests/ut_settings/upgradetesthelper.cpp index 55e167d..3d80053 100644 --- a/tests/ut_settings/upgradetesthelper.cpp +++ b/tests/ut_settings/upgradetesthelper.cpp @@ -110,8 +110,8 @@ void UpgradeTestHelper::fillSettings(QSettings *settings, const QList settings->beginGroup(group); foreach (const TestCase &testCase, testCases){ - if (!testCase.current.isEmpty()){ - settings->setValue(testCase.key(), testCase.current); + if (!testCase.current().isEmpty()){ + settings->setValue(testCase.key(), testCase.current()); } } @@ -136,7 +136,7 @@ void UpgradeTestHelper::fillDefaultSettings(QSettings *defaultSettings, const QL defaultSettings->beginGroup(group); foreach (const TestCase &testCase, testCases){ - switch (testCase.history.at(revision - 1).toAscii()){ + switch (testCase.history().at(revision - 1).toAscii()){ case 'S': // (S)et value lastSetValue[testCase.key()] = QString("v%1-default").arg(revision); defaultSettings->setValue(testCase.key(), lastSetValue[testCase.key()]); @@ -144,7 +144,7 @@ void UpgradeTestHelper::fillDefaultSettings(QSettings *defaultSettings, const QL case 'K': // (K)eep value Q_ASSERT_X(!lastSetValue[testCase.key()].isEmpty(), Q_FUNC_INFO, - qPrintable(QString("Inalid TestCase::history: '%1'").arg(testCase.history))); + qPrintable(QString("Inalid TestCase::history: '%1'").arg(testCase.history()))); defaultSettings->setValue(testCase.key(), lastSetValue[testCase.key()]); break; @@ -159,8 +159,8 @@ void UpgradeTestHelper::fillDefaultSettings(QSettings *defaultSettings, const QL default: Q_ASSERT_X(false, Q_FUNC_INFO, qPrintable(QString( "Inalid TestCase::history: '%1': invalid command-code '%2'") - .arg(testCase.history) - .arg(testCase.history.at(revision - 1)))); + .arg(testCase.history()) + .arg(testCase.history().at(revision - 1)))); } } @@ -242,8 +242,8 @@ bool UpgradeTestHelper::generateSnapshotRecipe(QTextStream *out){ ? ssuSettings.value(testCase.key()).toString() : "@NOTSET@"; *out << QString("%1:%2:%3\n") - .arg(testCase.history) - .arg(testCase.current) + .arg(testCase.history()) + .arg(testCase.current()) .arg(expected); } diff --git a/tests/ut_settings/upgradetesthelper.h b/tests/ut_settings/upgradetesthelper.h index 13d3d7a..388cc5e 100644 --- a/tests/ut_settings/upgradetesthelper.h +++ b/tests/ut_settings/upgradetesthelper.h @@ -31,20 +31,24 @@ class UpgradeTestHelper { struct UpgradeTestHelper::TestCase { TestCase(const QString &history, const QString ¤t, const QString &expected) : - history(history), current(current), expected(expected){ + m_history(history), m_current(current), m_expected(expected){ } + QString history() const { return m_history; } + QString current() const { return m_current; } + QString expected() const { return m_expected; } + QString key() const{ - return QString("%1__%2").arg(history).arg(current); + return QString("%1__%2").arg(m_history).arg(m_current); } bool keyShouldBeSet() const{ - return expected != "@NOTSET@"; + return m_expected != "@NOTSET@"; } - const QString history; // Sequence of (S)et, (K)eep, (R)emove, (N)oop - const QString current; - const QString expected; + QString m_history; // Sequence of (S)et, (K)eep, (R)emove, (N)oop + QString m_current; + QString m_expected; }; #endif diff --git a/tests/ut_urlresolver/testdata/mycert.crt b/tests/ut_urlresolver/testdata/mycert.crt new file mode 100644 index 0000000..29bc4c5 --- /dev/null +++ b/tests/ut_urlresolver/testdata/mycert.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICzDCCAjWgAwIBAgIJAMEYl4q2VM7YMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNV +BAYTAkZJMRkwFwYDVQQIDBBTb3V0aGVybiBGaW5sYW5kMREwDwYDVQQHDAhIZWxz +aW5raTEUMBIGA1UECgwLRm9vIEJhciBMdGQxEDAOBgNVBAMMB0ZvbyBCYXIxGTAX +BgkqhkiG9w0BCQEWCmZvb0BiYXIuZmkwIBcNMTMwNDA5MDk0MTAyWhgPMjExMzAz +MTYwOTQxMDJaMH4xCzAJBgNVBAYTAkZJMRkwFwYDVQQIDBBTb3V0aGVybiBGaW5s +YW5kMREwDwYDVQQHDAhIZWxzaW5raTEUMBIGA1UECgwLRm9vIEJhciBMdGQxEDAO +BgNVBAMMB0ZvbyBCYXIxGTAXBgkqhkiG9w0BCQEWCmZvb0BiYXIuZmkwgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAK1eqDzjWRv/ZY6XyyR0NTEcGavs57qOfK3t +BJpOsEcOX7W0u904HlK8zMFiNUCoIAz1W09TC5s69GusgBOtsOemtMKctHhF+FBk +ybVTns5vF6t4yx3vY2RFgvQDjFGHDlwpVzWTEYmzHucP+FsPd19/Pvjz3CqeIzZH +IHfHdtY7AgMBAAGjUDBOMB0GA1UdDgQWBBQNHO0P6yfLNbp9y662aTuUlkfOMzAf +BgNVHSMEGDAWgBQNHO0P6yfLNbp9y662aTuUlkfOMzAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4GBAI7iH16ZtfncZ2+OUISdTzg3TlqlxOxnm5CEm0KCvAKy +kgDmvlXFJ3FjeNfSDwBqP0/hbONWaCIt1kXeMoosJc2B0zMNCIPRf8qJGXJacR+n +5sm+Vjgi2ofQ1dlsCI9jQbAMDJzQ0jHFX4a+Y9h8AwsmyxX/lOn4H3UOSNh1HNoS +-----END CERTIFICATE----- diff --git a/tests/ut_urlresolver/testdata/mykey.key b/tests/ut_urlresolver/testdata/mykey.key new file mode 100644 index 0000000..c9e7cc2 --- /dev/null +++ b/tests/ut_urlresolver/testdata/mykey.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK1eqDzjWRv/ZY6X +yyR0NTEcGavs57qOfK3tBJpOsEcOX7W0u904HlK8zMFiNUCoIAz1W09TC5s69Gus +gBOtsOemtMKctHhF+FBkybVTns5vF6t4yx3vY2RFgvQDjFGHDlwpVzWTEYmzHucP ++FsPd19/Pvjz3CqeIzZHIHfHdtY7AgMBAAECgYA/z8lor92KmpSMyX4x6rvxWYBx +cX9RgUSO1+CL0066uKWtwdor8I3osilDPJyRMdCqNFzpc42gEzEHuLRjidjEr9LO +74VyYGsZPehLUB9d6+SlWpa2BlDGTp60nUC4itLI/IxOjnG9ekIAFVF54w/OFmJo +dT3uAccRgf5PEahdEQJBANX/AwVCDmEWRKDcnmynsWvL/JMtDRhEfhDW5rl9QvcB +XDopJGur8qlbDgRX8B4JrM4GkOIHq63tHxmWc4BzudcCQQDPZjrYHeUhYYz/EKvr +7ME973zl3xgROjsimTY7zWil9mr7M3e/63A88fIkIB5QRFwiBz1N2frgc1rP5PpH +0yI9AkB7bIyqcLHobzZ/7R72njWnbcysejRuRbrMLZZ/b267Fi7CYM5fx5m68giA +mtOkD4J6hbD0nOX496WTVYIimRybAkAuLmRR9S4tJaygqxStHvXUlbwo72lLhLzg +Ml96J33y3pDpyIcUrBc86t7xHlnBo8ckKJqE+FG9otII0sLMNX49AkEAhorKyzXR +y9FfSstiuSpSubCRFFbCTYflgZhLk7vrBEPFhp3pVlWXszdiL07SoPPDvnEqdHlW +7VKuMhgxpp1rww== +-----END PRIVATE KEY----- diff --git a/tests/ut_urlresolver/urlresolvertest.cpp b/tests/ut_urlresolver/urlresolvertest.cpp index a344b50..a424564 100644 --- a/tests/ut_urlresolver/urlresolvertest.cpp +++ b/tests/ut_urlresolver/urlresolvertest.cpp @@ -6,6 +6,8 @@ */ #include "urlresolvertest.h" +#include "constants.h" +#include "testutils/process.h" void UrlResolverTest::initTestCase(){ #ifdef TARGET_ARCH @@ -124,4 +126,200 @@ void UrlResolverTest::checkReleaseRepoUrls(){ } } +void UrlResolverTest::checkRegisterDevice(){ + QDomDocument doc("foo"); + QDomElement root = doc.createElement("foo"); + doc.appendChild(root); + + QDomElement certificate = doc.createElement("certificate"); + root.appendChild(certificate); + + QVERIFY2(!ssu.registerDevice(&doc), + "Ssu::registerDevice() should fail when 'certificate' is empty"); + + QFile certificateFile(TESTS_DATA_PATH "/mycert.crt"); + QVERIFY(certificateFile.open(QIODevice::ReadOnly)); + + certificate.appendChild(doc.createTextNode(certificateFile.readAll())); + + QDomElement privateKey = doc.createElement("privateKey"); + root.appendChild(privateKey); + + QVERIFY2(!ssu.registerDevice(&doc), + "Ssu::registerDevice() should fail when 'privateKey' is empty"); + + QFile privateKeyFile(TESTS_DATA_PATH "/mykey.key"); + QVERIFY(privateKeyFile.open(QIODevice::ReadOnly)); + + privateKey.appendChild(doc.createTextNode(privateKeyFile.readAll())); + + QDomElement user = doc.createElement("user"); + root.appendChild(user); + user.appendChild(doc.createTextNode("john.doe")); + + QSignalSpy registrationStatusChanged_spy(&ssu, SIGNAL(registrationStatusChanged())); + + QVERIFY(ssu.registerDevice(&doc)); + + QVERIFY(registrationStatusChanged_spy.count() == 1); + QVERIFY(ssu.isRegistered()); + + ssu.unregister(); + + QVERIFY(registrationStatusChanged_spy.count() == 2); + QVERIFY(!ssu.isRegistered()); +} + +void UrlResolverTest::checkSetCredentials(){ + QDomDocument doc("foo"); + + QDomElement root = doc.createElement("foo"); + doc.appendChild(root); + + QDomElement credentials1 = doc.createElement("credentials"); + root.appendChild(credentials1); + + QVERIFY2(!ssu.setCredentials(&doc), + "Ssu::setCredentials() should fail when 'scope' is not defined"); + + credentials1.setAttribute("scope", "utscope1"); + + QVERIFY2(!ssu.setCredentials(&doc), + "Ssu::setCredentials() should fail when username/password is missing"); + + QDomElement username1 = doc.createElement("username"); + credentials1.appendChild(username1); + username1.appendChild(doc.createTextNode("john.doe1")); + + QVERIFY2(!ssu.setCredentials(&doc), + "Ssu::setCredentials() should fail when password is missing"); + + QDomElement password1 = doc.createElement("password"); + credentials1.appendChild(password1); + password1.appendChild(doc.createTextNode("SeCrEt1")); + + QVERIFY2(ssu.setCredentials(&doc), + qPrintable(QString("setCredentials() failed: %1").arg(ssu.lastError()))); + + QVERIFY2(ssu.lastCredentialsUpdate() > QDateTime::currentDateTime().addSecs(-5) && + ssu.lastCredentialsUpdate() <= QDateTime::currentDateTime(), + "Ssu::lastCredentialsUpdate was not updated"); + + //QVERIFY(ssu.credentialScopes().contains("utscope1")); + QCOMPARE(ssu.credentials("utscope1").first, QString("john.doe1")); + QCOMPARE(ssu.credentials("utscope1").second, QString("SeCrEt1")); + + + QDomElement credentials2 = doc.createElement("credentials"); + root.appendChild(credentials2); + credentials2.setAttribute("scope", "utscope2"); + + QDomElement username2 = doc.createElement("username"); + credentials2.appendChild(username2); + username2.appendChild(doc.createTextNode("john.doe2")); + + QDomElement password2 = doc.createElement("password"); + credentials2.appendChild(password2); + password2.appendChild(doc.createTextNode("SeCrEt2")); + + QVERIFY2(ssu.setCredentials(&doc), + qPrintable(QString("setCredentials() failed: %1").arg(ssu.lastError()))); + + QVERIFY2(ssu.lastCredentialsUpdate() > QDateTime::currentDateTime().addSecs(-5) && + ssu.lastCredentialsUpdate() <= QDateTime::currentDateTime(), + "Ssu::lastCredentialsUpdate was not updated"); + + //QVERIFY(ssu.credentialScopes().contains("utscope1")); + QCOMPARE(ssu.credentials("utscope1").first, QString("john.doe1")); + QCOMPARE(ssu.credentials("utscope1").second, QString("SeCrEt1")); + + //QVERIFY(ssu.credentialScopes().contains("utscope2")); + QCOMPARE(ssu.credentials("utscope2").first, QString("john.doe2")); + QCOMPARE(ssu.credentials("utscope2").second, QString("SeCrEt2")); +} + +void UrlResolverTest::checkStoreAuthorizedKeys(){ + struct Cleanup { + ~Cleanup(){ + if (!tempHomePath.isEmpty()){ + Process rmtemp; + rmtemp.execute("rm", QStringList() << "-rf" << tempHomePath); + if (rmtemp.hasError()){ + qWarning("%s: Failed to remove temporary directory '%s': %s", Q_FUNC_INFO, + tempHomePath.constData(), qPrintable(rmtemp.fmtErrorMessage())); + } + + if (!qputenv("HOME", originalHomePath)){ + qFatal("%s: Failed to restore HOME environment variable", Q_FUNC_INFO); + } + } + } + + QByteArray originalHomePath; + QByteArray tempHomePath; + } cleanup; + + // Temporarily change HOME path so Ssu::storeAuthorizedKeys() does not touch + // real home directory + cleanup.originalHomePath = qgetenv("HOME"); + QVERIFY(!cleanup.originalHomePath.isEmpty()); + + Process mktemp; + cleanup.tempHomePath = mktemp.execute("mktemp", + QStringList() << "-t" << "-d" << "ut_urlresolver.temp-home.XXX").trimmed().toLocal8Bit(); + QVERIFY2(!mktemp.hasError(), qPrintable(mktemp.fmtErrorMessage())); + + QVERIFY(qputenv("HOME", cleanup.tempHomePath)); + QVERIFY2(QDir::homePath() == QString(cleanup.tempHomePath), + "QDir::homePath() does not change after qputenv(\"HOME\", \"...\")"); + + // Here starts the test itself + QByteArray testData("# test data\n"); + ssu.storeAuthorizedKeys(testData); + + QFile authorizedKeys(QDir::home().filePath(".ssh/authorized_keys")); + QVERIFY(authorizedKeys.open(QIODevice::ReadOnly)); + + QVERIFY(authorizedKeys.readAll().split('\n').contains(testData.trimmed())); + + QByteArray testData2("# test data2\n"); + ssu.storeAuthorizedKeys(testData2); + + QEXPECT_FAIL("", "Ssu::storeAuthorizedKeys() does not modify existing authorized_keys", Continue); + authorizedKeys.seek(0); + QVERIFY(authorizedKeys.readAll().split('\n').contains(testData2.trimmed())); + + const QFile::Permissions go_rwx = + QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | + QFile::ReadOther | QFile::WriteOther | QFile::ExeOther; + QVERIFY((QFileInfo(QDir::home().filePath(".ssh")).permissions() & go_rwx) == 0); +} + +void UrlResolverTest::checkVerifyResponse(){ + QDomDocument doc("foo"); + + QDomElement root = doc.createElement("foo"); + doc.appendChild(root); + + QDomElement action = doc.createElement("action"); + root.appendChild(action); + action.appendChild(doc.createTextNode("register")); + + QDomElement deviceId = doc.createElement("deviceId"); + root.appendChild(deviceId); + deviceId.appendChild(doc.createTextNode("deadbeef-dead-beef-dead")); + + QDomElement protocolVersion = doc.createElement("protocolVersion"); + root.appendChild(protocolVersion); + + QDomText protocolVersionText = doc.createTextNode(SSU_PROTOCOL_VERSION); + protocolVersion.appendChild(protocolVersionText); + + QVERIFY(ssu.verifyResponse(&doc)); + + protocolVersionText.setData(SSU_PROTOCOL_VERSION ".invalid"); + + QVERIFY2(!ssu.verifyResponse(&doc), + "Ssu::verifyResponse() should fail when protocolVersion does not match SSU_PROTOCOL_VERSION"); +} diff --git a/tests/ut_urlresolver/urlresolvertest.h b/tests/ut_urlresolver/urlresolvertest.h index 158a410..40540bb 100644 --- a/tests/ut_urlresolver/urlresolvertest.h +++ b/tests/ut_urlresolver/urlresolvertest.h @@ -26,6 +26,10 @@ class UrlResolverTest: public QObject { void checkCleanUrl(); void simpleRepoUrlLookup(); void checkReleaseRepoUrls(); + void checkRegisterDevice(); + void checkSetCredentials(); + void checkStoreAuthorizedKeys(); + void checkVerifyResponse(); private: Ssu ssu; diff --git a/tests/ut_urlresolver/ut_urlresolver.pro b/tests/ut_urlresolver/ut_urlresolver.pro index 58efd40..8dee25c 100644 --- a/tests/ut_urlresolver/ut_urlresolver.pro +++ b/tests/ut_urlresolver/ut_urlresolver.pro @@ -2,10 +2,16 @@ TARGET = ut_urlresolver include(../testapplication.pri) include(ut_urlresolver_dependencies.pri) +QT += xml + HEADERS = urlresolvertest.h SOURCES = main.cpp \ urlresolvertest.cpp +test_data.files = \ + testdata/mycert.crt \ + testdata/mykey.key \ + test_data_etc.files = \ testdata/ssu.ini \ diff --git a/tests/ut_urlresolver/ut_urlresolver_dependencies.pri b/tests/ut_urlresolver/ut_urlresolver_dependencies.pri index 37c741f..5e56454 100644 --- a/tests/ut_urlresolver/ut_urlresolver_dependencies.pri +++ b/tests/ut_urlresolver/ut_urlresolver_dependencies.pri @@ -1 +1,2 @@ include(../../libssu/libssu.pri) +include(../testutils/testutils.pri)