Browse Source

added service registry tests

pull/2/head
Skycoder42 7 years ago
parent
commit
7aa86f6b2b
No known key found for this signature in database GPG Key ID: 8E01AD9EF0578D2B
  1. 1
      src/mvvmcore/serviceregistry.h
  2. 6
      tests/auto/mvvmcore/mvvmcore.pro
  3. 19
      tests/auto/mvvmcore/serviceregistry/plugintestinterface.h
  4. 22
      tests/auto/mvvmcore/serviceregistry/serviceregistry.pro
  5. 17
      tests/auto/mvvmcore/serviceregistry/testinterface.h
  6. 1
      tests/auto/mvvmcore/serviceregistry/testobject.cpp
  7. 56
      tests/auto/mvvmcore/serviceregistry/testobject.h
  8. 9
      tests/auto/mvvmcore/serviceregistry/testservice.cpp
  9. 24
      tests/auto/mvvmcore/serviceregistry/testservice.h
  10. 262
      tests/auto/mvvmcore/serviceregistry/tst_serviceregistry.cpp
  11. 3
      tests/auto/mvvmcore/serviceregistrytestplugin/serviceregistrytestplugin.json
  12. 18
      tests/auto/mvvmcore/serviceregistrytestplugin/serviceregistrytestplugin.pro
  13. 10
      tests/auto/mvvmcore/serviceregistrytestplugin/testplugin.cpp
  14. 18
      tests/auto/mvvmcore/serviceregistrytestplugin/testplugin.h
  15. 2
      tests/auto/mvvmcore/settingsgenerator/settingsgenerator.pro

1
src/mvvmcore/serviceregistry.h

@ -47,6 +47,7 @@ public:
//! Register a service for its interface via an already existing instance
template <typename TInterface, typename TService>
void registerInterface(TService *service, DestructionScope scope = DestroyOnAppDestroy, bool weak = false);
//! Register a service via its type
template <typename TService>
void registerObject(DestructionScope scope = DestroyOnAppDestroy, bool weak = false);

6
tests/auto/mvvmcore/mvvmcore.pro

@ -1,4 +1,8 @@
TEMPLATE = subdirs
SUBDIRS += \
settingsgenerator
settingsgenerator \
serviceregistry \
serviceregistrytestplugin
serviceregistry.depends += serviceregistrytestplugin

19
tests/auto/mvvmcore/serviceregistry/plugintestinterface.h

@ -0,0 +1,19 @@
#ifndef PLUGINTESTINTERFACE_H
#define PLUGINTESTINTERFACE_H
#include <QtCore/QObject>
class PluginTestInterface
{
Q_DISABLE_COPY(PluginTestInterface)
public:
inline PluginTestInterface() = default;
virtual inline ~PluginTestInterface() = default;
virtual int magicNumber() const = 0;
};
#define PluginTestInterfaceIId "de.skycoder42.qtmvvm.core.tests.PluginTestInterface"
Q_DECLARE_INTERFACE(PluginTestInterface, PluginTestInterfaceIId)
#endif // PLUGINTESTINTERFACE_H

22
tests/auto/mvvmcore/serviceregistry/serviceregistry.pro

@ -0,0 +1,22 @@
TEMPLATE = app
QT += testlib mvvmcore
QT -= gui
CONFIG += console
CONFIG -= app_bundle
TARGET = tst_serviceregistry
SOURCES += \
tst_serviceregistry.cpp \
testservice.cpp \
testobject.cpp
HEADERS += \
testinterface.h \
testservice.h \
testobject.h \
plugintestinterface.h
load(qt_build_paths)
DEFINES += PLUGIN_TESTDIR=\\\"$$MODULE_BASE_OUTDIR/tests/plugins\\\"

17
tests/auto/mvvmcore/serviceregistry/testinterface.h

@ -0,0 +1,17 @@
#ifndef TESTINTERFACE_H
#define TESTINTERFACE_H
#include <QtCore/QObject>
class TestInterface
{
Q_DISABLE_COPY(TestInterface)
public:
inline TestInterface() = default;
virtual inline ~TestInterface() = default;
};
#define TestInterfaceIId "de.skycoder42.qtmvvm.core.tests.TestInterface"
Q_DECLARE_INTERFACE(TestInterface, TestInterfaceIId)
#endif // TESTINTERFACE_H

1
tests/auto/mvvmcore/serviceregistry/testobject.cpp

@ -0,0 +1 @@
#include "testobject.h"

56
tests/auto/mvvmcore/serviceregistry/testobject.h

@ -0,0 +1,56 @@
#ifndef TESTOBJECT_H
#define TESTOBJECT_H
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include <QtMvvmCore/Injection>
#define CREATE_TEST_OBJECT(index, ...) \
class TestObject ## index : public QObject \
{ \
Q_OBJECT \
\
public: \
__VA_ARGS__ \
\
Q_INVOKABLE explicit inline TestObject ## index(QObject *parent = nullptr) : \
QObject{parent} \
{} \
};
#define DEP(index) \
TestObject ## index *dep = nullptr; \
QTMVVM_INJECT_PROP(TestObject ## index *, dep, dep)
#define DESTROYER \
QSharedPointer<TestObject0> holder;
#define SOMETIME_DESTROYER(index) \
DESTROYER \
inline ~TestObject ## index() { qDebug(Q_FUNC_INFO); }
#define NEVER_DESTROYER(index) \
DESTROYER \
inline ~TestObject ## index() { Q_ASSERT_X(false, Q_FUNC_INFO, "destructor of never-destroy-object called"); }
CREATE_TEST_OBJECT(0)
CREATE_TEST_OBJECT(1, int data = 42;)
CREATE_TEST_OBJECT(2, int data = 42;)
CREATE_TEST_OBJECT(3, int data = 42;)
CREATE_TEST_OBJECT(4)
CREATE_TEST_OBJECT(5)
CREATE_TEST_OBJECT(6, DEP(4))
CREATE_TEST_OBJECT(7, DEP(5))
CREATE_TEST_OBJECT(8, bool hasBoth = false;)
CREATE_TEST_OBJECT(9, DEP(0))
CREATE_TEST_OBJECT(10, DEP(9))
CREATE_TEST_OBJECT(11, SOMETIME_DESTROYER(11))
CREATE_TEST_OBJECT(12, SOMETIME_DESTROYER(12))
CREATE_TEST_OBJECT(13, SOMETIME_DESTROYER(13))
CREATE_TEST_OBJECT(14, NEVER_DESTROYER(14))
#endif // TESTOBJECT_H

9
tests/auto/mvvmcore/serviceregistry/testservice.cpp

@ -0,0 +1,9 @@
#include "testservice.h"
TestService::TestService(QObject *parent) :
QObject{parent}
{}
WeakTestService::WeakTestService(QObject *parent) :
TestService{parent}
{}

24
tests/auto/mvvmcore/serviceregistry/testservice.h

@ -0,0 +1,24 @@
#ifndef TESTSERVICE_H
#define TESTSERVICE_H
#include <QtCore/QObject>
#include "testinterface.h"
class TestService : public QObject, public TestInterface
{
Q_OBJECT
Q_INTERFACES(TestInterface)
public:
Q_INVOKABLE explicit TestService(QObject *parent = nullptr);
};
class WeakTestService : public TestService
{
Q_OBJECT
public:
Q_INVOKABLE explicit WeakTestService(QObject *parent = nullptr);
};
#endif // TESTSERVICE_H

262
tests/auto/mvvmcore/serviceregistry/tst_serviceregistry.cpp

@ -0,0 +1,262 @@
#include <QString>
#include <QtTest>
#include <QCoreApplication>
#include <QtMvvmCore/ServiceRegistry>
#include "testinterface.h"
#include "testservice.h"
#include "testobject.h"
#include "plugintestinterface.h"
using namespace QtMvvm;
class ServiceRegistryTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testRegistrations();
void testPlainConstructions();
void testDepedencyConstructions();
void testInjection();
void testPluginRegistration();
void testDestructionScopes();
public:
static QWeakPointer<TestObject0> weak0;
static QWeakPointer<TestObject0> weak1;
static QWeakPointer<TestObject0> weak2;
static QWeakPointer<TestObject0> weak3;
};
QWeakPointer<TestObject0> ServiceRegistryTest::weak0;
QWeakPointer<TestObject0> ServiceRegistryTest::weak1;
QWeakPointer<TestObject0> ServiceRegistryTest::weak2;
QWeakPointer<TestObject0 >ServiceRegistryTest::weak3;
void ServiceRegistryTest::testRegistrations()
{
try {
QVERIFY(!ServiceRegistry::instance()->isRegistered<TestInterface>());
QVERIFY(!ServiceRegistry::instance()->isRegistered<TestService>());
QVERIFY(!ServiceRegistry::instance()->isRegistered<TestObject0>());
QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->service<TestInterface>(), ServiceDependencyException);
QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->service<TestObject0>(), ServiceDependencyException);
//register service
ServiceRegistry::instance()->registerInterface<TestInterface, WeakTestService>(ServiceRegistry::DestroyOnAppDestroy, true);
QVERIFY(ServiceRegistry::instance()->isRegistered<TestInterface>());
QVERIFY(ServiceRegistry::instance()->isRegistered(TestInterfaceIId));
QVERIFY(!ServiceRegistry::instance()->isRegistered<WeakTestService>());
QVERIFY(!ServiceRegistry::instance()->isRegistered<TestService>());
ServiceRegistry::instance()->registerInterface<TestInterface, TestService>();
QVERIFY(ServiceRegistry::instance()->isRegistered<TestInterface>());
QVERIFY(!ServiceRegistry::instance()->isRegistered<TestService>());
#define TMP_REGISTER ServiceRegistry::instance()->registerInterface<TestInterface, WeakTestService>()
QVERIFY_EXCEPTION_THROWN(TMP_REGISTER, ServiceExistsException);
#undef TMP_REGISTER
QVERIFY(ServiceRegistry::instance()->service<TestInterface>());
QVERIFY(ServiceRegistry::instance()->serviceObj(TestInterfaceIId));
QVERIFY(dynamic_cast<TestService*>(ServiceRegistry::instance()->service<TestInterface>()));
//register object
ServiceRegistry::instance()->registerObject<TestObject0>();
QVERIFY(ServiceRegistry::instance()->isRegistered<TestObject0>());
QVERIFY(ServiceRegistry::instance()->service<TestObject0>());
} catch(QException &e) {
QFAIL(e.what());
}
}
void ServiceRegistryTest::testPlainConstructions()
{
try {
// test default (meta) construction
ServiceRegistry::instance()->registerObject<TestObject1>();
auto obj1 = ServiceRegistry::instance()->service<TestObject1>();
QVERIFY(obj1);
QCOMPARE(obj1->data, 42);
// test function construction
ServiceRegistry::instance()->registerObject<TestObject2>([](){
auto obj = new TestObject2{};
obj->data = 13;
return obj;
});
auto obj2 = ServiceRegistry::instance()->service<TestObject2>();
QVERIFY(obj2);
QCOMPARE(obj2->data, 13);
// test instance construction
auto obj3Instance = new TestObject3{};
ServiceRegistry::instance()->registerObject(obj3Instance);
auto obj3 = ServiceRegistry::instance()->service<TestObject3>();
QCOMPARE(obj3, obj3Instance);
} catch(QException &e) {
QFAIL(e.what());
}
}
void ServiceRegistryTest::testDepedencyConstructions()
{
try {
//try valid (inverse order must work)
ServiceRegistry::instance()->registerObject<TestObject6>();
ServiceRegistry::instance()->registerObject<TestObject4>();
auto obj = ServiceRegistry::instance()->service<TestObject6>();
QVERIFY(obj);
QVERIFY(obj->dep);
//try without dep
ServiceRegistry::instance()->registerObject<TestObject7>();
QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->service<TestObject7>(), ServiceDependencyException);
ServiceRegistry::instance()->registerObject<TestObject5>();
QVERIFY(ServiceRegistry::instance()->service<TestObject7>());
// try with fn
ServiceRegistry::instance()->registerObject<TestObject8>([](TestObject6 *obj1, TestObject0 *obj2){
auto retObj = new TestObject8{};
retObj->hasBoth = obj1 && obj2;
return retObj;
});
auto fnObj = ServiceRegistry::instance()->service<TestObject8>();
QVERIFY(fnObj);
QVERIFY(fnObj->hasBoth);
} catch(QException &e) {
QFAIL(e.what());
}
}
void ServiceRegistryTest::testInjection()
{
try {
// try normal injection
auto obj1 = new TestObject9{this};
QVERIFY(!obj1->dep);
ServiceRegistry::instance()->injectServices(obj1);
QVERIFY(obj1->dep);
obj1->deleteLater();
//try construct injection
auto obj2 = ServiceRegistry::instance()->constructInjected<TestObject9>(this);
QVERIFY(obj2);
QVERIFY(obj2->dep);
obj2->deleteLater();
//try invalid injection
QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->constructInjected<TestObject10>(this), ServiceDependencyException);
auto obj3 = new TestObject10{this};
QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->injectServices(obj3), ServiceDependencyException);
obj3->deleteLater();
} catch(QException &e) {
QFAIL(e.what());
}
}
void ServiceRegistryTest::testPluginRegistration()
{
try {
#ifdef Q_OS_LINUX
QVERIFY(QFile::exists(QStringLiteral(PLUGIN_TESTDIR "/serviceregistry/libserviceregistry_testplugin.so")));
#elif defined(Q_OS_DARWIN)
QVERIFY(QFile::exists(QStringLiteral(PLUGIN_TESTDIR "/serviceregistry/libserviceregistry_testplugin.dylib")));
QVERIFY(QFile::exists(QStringLiteral(PLUGIN_TESTDIR "/serviceregistry/libserviceregistry_testplugin_debug.dylib")));
#elif defined(Q_OS_WIN)
QVERIFY(QFile::exists(QStringLiteral(PLUGIN_TESTDIR "/serviceregistry/libserviceregistry_testplugin.dll")));
QVERIFY(QFile::exists(QStringLiteral(PLUGIN_TESTDIR "/serviceregistry/libserviceregistry_testplugind.dll")));
#endif
qputenv("QT_PLUGIN_PATH", PLUGIN_TESTDIR);
ServiceRegistry::instance()->registerPlugin<PluginTestInterface>(QStringLiteral("serviceregistry"), QStringLiteral("test2"));
QVERIFY(ServiceRegistry::instance()->isRegistered<PluginTestInterface>());
QVERIFY(ServiceRegistry::instance()->service<PluginTestInterface>());
QCOMPARE(ServiceRegistry::instance()->service<PluginTestInterface>()->magicNumber(), 72);
} catch(QException &e) {
QFAIL(e.what());
}
}
void ServiceRegistryTest::testDestructionScopes()
{
try {
{
auto holder0 = QSharedPointer<TestObject0>::create();
auto holder1 = QSharedPointer<TestObject0>::create();
auto holder2 = QSharedPointer<TestObject0>::create();
auto holder3 = QSharedPointer<TestObject0>::create();
weak0 = holder0;
weak1 = holder1;
weak2 = holder2;
weak3 = holder3;
//register and create all destruction instances
ServiceRegistry::instance()->registerObject<TestObject11>(ServiceRegistry::DestroyOnAppQuit);
QVERIFY(ServiceRegistry::instance()->service<TestObject11>());
ServiceRegistry::instance()->service<TestObject11>()->holder = holder0;
ServiceRegistry::instance()->registerObject<TestObject12>(ServiceRegistry::DestroyOnAppDestroy);
QVERIFY(ServiceRegistry::instance()->service<TestObject12>());
ServiceRegistry::instance()->service<TestObject12>()->holder = holder1;
ServiceRegistry::instance()->registerObject<TestObject13>(ServiceRegistry::DestroyOnRegistryDestroy);
QVERIFY(ServiceRegistry::instance()->service<TestObject13>());
ServiceRegistry::instance()->service<TestObject13>()->holder = holder2;
ServiceRegistry::instance()->registerObject<TestObject14>(ServiceRegistry::DestroyNever);
QVERIFY(ServiceRegistry::instance()->service<TestObject14>());
ServiceRegistry::instance()->service<TestObject14>()->holder = holder3;
}
QVERIFY(weak0);
QVERIFY(weak1);
QVERIFY(weak2);
QVERIFY(weak3);
bool called = false;
connect(qApp, &QCoreApplication::aboutToQuit, [&](){ //called after the method destructor
QVERIFY(!weak0);
QVERIFY(weak1);
QVERIFY(weak2);
QVERIFY(weak3);
called = true;
});
// "run" the main eventloop to test the signal
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
QCoreApplication::exec();
QVERIFY(called);
QVERIFY(!weak0);
QVERIFY(weak1);
QVERIFY(weak2);
QVERIFY(weak3);
} catch(QException &e) {
QFAIL(e.what());
}
}
// manual main for testing destruction
int main(int argc, char *argv[])
{
int res = EXIT_FAILURE;
{
QCoreApplication app(argc, argv);
app.setAttribute(Qt::AA_Use96Dpi, true);
ServiceRegistryTest tc;
QTEST_SET_MAIN_SOURCE_PATH
res = QTest::qExec(&tc, argc, argv);
Q_ASSERT(!ServiceRegistryTest::weak0);
Q_ASSERT(ServiceRegistryTest::weak1);
Q_ASSERT(ServiceRegistryTest::weak2);
Q_ASSERT(ServiceRegistryTest::weak3);
}
Q_ASSERT(!ServiceRegistryTest::weak0);
Q_ASSERT(!ServiceRegistryTest::weak1);
Q_ASSERT(ServiceRegistryTest::weak2);
Q_ASSERT(ServiceRegistryTest::weak3);
return res;
}
#include "tst_serviceregistry.moc"

3
tests/auto/mvvmcore/serviceregistrytestplugin/serviceregistrytestplugin.json

@ -0,0 +1,3 @@
{
"Keys" : [ "test1", "test2" ]
}

18
tests/auto/mvvmcore/serviceregistrytestplugin/serviceregistrytestplugin.pro

@ -0,0 +1,18 @@
TEMPLATE = lib
CONFIG += plugin
QT = core mvvmcore
load(qt_build_paths)
TARGET = serviceregistry_testplugin
DESTDIR = $$MODULE_BASE_OUTDIR/tests/plugins/serviceregistry
HEADERS += \
testplugin.h \
../serviceregistry/plugintestinterface.h
SOURCES += \
testplugin.cpp
DISTFILES += serviceregistrytestplugin.json

10
tests/auto/mvvmcore/serviceregistrytestplugin/testplugin.cpp

@ -0,0 +1,10 @@
#include "testplugin.h"
TestPlugin::TestPlugin(QObject *parent) :
QObject{parent}
{}
int TestPlugin::magicNumber() const
{
return 72;
}

18
tests/auto/mvvmcore/serviceregistrytestplugin/testplugin.h

@ -0,0 +1,18 @@
#ifndef TESTPLUGIN_H
#define TESTPLUGIN_H
#include "../serviceregistry/plugintestinterface.h"
class TestPlugin : public QObject, public PluginTestInterface
{
Q_OBJECT
Q_INTERFACES(PluginTestInterface)
Q_PLUGIN_METADATA(IID PluginTestInterfaceIId FILE "serviceregistrytestplugin.json")
public:
TestPlugin(QObject *parent = nullptr);
int magicNumber() const override;
};
#endif // TESTPLUGIN_H

2
tests/auto/mvvmcore/settingsgenerator/settingsgenerator.pro

@ -21,8 +21,6 @@ SETTINGS_DEFINITIONS += \
SETTINGS_TRANSLATIONS += \
translatortest.xml
#_never_true: SOURCES += $$files(.ts-dummy/*)
DISTFILES += \
import_normal.xml \
import_config.xml

Loading…
Cancel
Save