#include #include #include #include #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 weak0; static QWeakPointer weak1; static QWeakPointer weak2; static QWeakPointer weak3; }; QWeakPointer ServiceRegistryTest::weak0; QWeakPointer ServiceRegistryTest::weak1; QWeakPointer ServiceRegistryTest::weak2; QWeakPointerServiceRegistryTest::weak3; void ServiceRegistryTest::testRegistrations() { try { QVERIFY(!ServiceRegistry::instance()->isRegistered()); QVERIFY(!ServiceRegistry::instance()->isRegistered()); QVERIFY(!ServiceRegistry::instance()->isRegistered()); QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->service(), ServiceDependencyException); QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->service(), ServiceDependencyException); //register service ServiceRegistry::instance()->registerInterface(ServiceRegistry::DestroyOnAppDestroy, true); QVERIFY(ServiceRegistry::instance()->isRegistered()); QVERIFY(ServiceRegistry::instance()->isRegistered(TestInterfaceIId)); QVERIFY(!ServiceRegistry::instance()->isRegistered()); QVERIFY(!ServiceRegistry::instance()->isRegistered()); ServiceRegistry::instance()->registerInterface(); QVERIFY(ServiceRegistry::instance()->isRegistered()); QVERIFY(!ServiceRegistry::instance()->isRegistered()); #define TMP_REGISTER ServiceRegistry::instance()->registerInterface() QVERIFY_EXCEPTION_THROWN(TMP_REGISTER, ServiceExistsException); #undef TMP_REGISTER QVERIFY(ServiceRegistry::instance()->service()); QVERIFY(ServiceRegistry::instance()->serviceObj(TestInterfaceIId)); QVERIFY(dynamic_cast(ServiceRegistry::instance()->service())); //register object ServiceRegistry::instance()->registerObject(); QVERIFY(ServiceRegistry::instance()->isRegistered()); QVERIFY(ServiceRegistry::instance()->service()); } catch(QException &e) { QFAIL(e.what()); } } void ServiceRegistryTest::testPlainConstructions() { try { // test default (meta) construction ServiceRegistry::instance()->registerObject(); auto obj1 = ServiceRegistry::instance()->service(); QVERIFY(obj1); QCOMPARE(obj1->data, 42); // test function construction ServiceRegistry::instance()->registerObject([](){ auto obj = new TestObject2{}; obj->data = 13; return obj; }); auto obj2 = ServiceRegistry::instance()->service(); QVERIFY(obj2); QCOMPARE(obj2->data, 13); // test instance construction auto obj3Instance = new TestObject3{}; ServiceRegistry::instance()->registerObject(obj3Instance); auto obj3 = ServiceRegistry::instance()->service(); QCOMPARE(obj3, obj3Instance); } catch(QException &e) { QFAIL(e.what()); } } void ServiceRegistryTest::testDepedencyConstructions() { try { //try valid (inverse order must work) ServiceRegistry::instance()->registerObject(); ServiceRegistry::instance()->registerObject(); auto obj = ServiceRegistry::instance()->service(); QVERIFY(obj); QVERIFY(obj->dep); //try without dep ServiceRegistry::instance()->registerObject(); QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->service(), ServiceDependencyException); ServiceRegistry::instance()->registerObject(); QVERIFY(ServiceRegistry::instance()->service()); // try with fn ServiceRegistry::instance()->registerObject([](TestObject6 *obj1, TestObject0 *obj2){ auto retObj = new TestObject8{}; retObj->hasBoth = obj1 && obj2; return retObj; }); auto fnObj = ServiceRegistry::instance()->service(); 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(this); QVERIFY(obj2); QVERIFY(obj2->dep); obj2->deleteLater(); //try invalid injection QVERIFY_EXCEPTION_THROWN(ServiceRegistry::instance()->constructInjected(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"))); #elif defined(Q_OS_WIN) #ifdef QT_NO_DEBUG QVERIFY(QFile::exists(QStringLiteral(PLUGIN_TESTDIR "/serviceregistry/serviceregistry_testplugin.dll"))); #else QVERIFY(QFile::exists(QStringLiteral(PLUGIN_TESTDIR "/serviceregistry/serviceregistry_testplugind.dll"))); #endif #endif qputenv("QT_PLUGIN_PATH", PLUGIN_TESTDIR); ServiceRegistry::instance()->registerPlugin(QStringLiteral("serviceregistry"), QStringLiteral("test2")); QVERIFY(ServiceRegistry::instance()->isRegistered()); QVERIFY(ServiceRegistry::instance()->service()); QCOMPARE(ServiceRegistry::instance()->service()->magicNumber(), 72); } catch(QException &e) { #ifdef __MINGW32__ QEXPECT_FAIL("", "Plugin loading in the tests is currently broken on mingw", Abort) QVERIFY2(false, e.what()); #else QFAIL(e.what()); #endif } } void ServiceRegistryTest::testDestructionScopes() { try { { auto holder0 = QSharedPointer::create(); auto holder1 = QSharedPointer::create(); auto holder2 = QSharedPointer::create(); auto holder3 = QSharedPointer::create(); weak0 = holder0; weak1 = holder1; weak2 = holder2; weak3 = holder3; //register and create all destruction instances ServiceRegistry::instance()->registerObject(ServiceRegistry::DestroyOnAppQuit); QVERIFY(ServiceRegistry::instance()->service()); ServiceRegistry::instance()->service()->holder = holder0; ServiceRegistry::instance()->registerObject(ServiceRegistry::DestroyOnAppDestroy); QVERIFY(ServiceRegistry::instance()->service()); ServiceRegistry::instance()->service()->holder = holder1; ServiceRegistry::instance()->registerObject(ServiceRegistry::DestroyOnRegistryDestroy); QVERIFY(ServiceRegistry::instance()->service()); ServiceRegistry::instance()->service()->holder = holder2; ServiceRegistry::instance()->registerObject(ServiceRegistry::DestroyNever); QVERIFY(ServiceRegistry::instance()->service()); ServiceRegistry::instance()->service()->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"