| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). |
| 4 | ** Contact: http://www.qt-project.org/legal |
| 5 | ** |
| 6 | ** This file is part of the QtSystems module of the Qt Toolkit. |
| 7 | ** |
| 8 | ** $QT_BEGIN_LICENSE:LGPL21$ |
| 9 | ** Commercial License Usage |
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 11 | ** accordance with the commercial license agreement provided with the |
| 12 | ** Software or, alternatively, in accordance with the terms contained in |
| 13 | ** a written agreement between you and The Qt Company. For licensing terms |
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
| 15 | ** information use the contact form at http://www.qt.io/contact-us. |
| 16 | ** |
| 17 | ** GNU Lesser General Public License Usage |
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
| 19 | ** General Public License version 2.1 or version 3 as published by the Free |
| 20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
| 21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
| 22 | ** following information to ensure the GNU Lesser General Public License |
| 23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
| 24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 25 | ** |
| 26 | ** As a special exception, The Qt Company gives you certain additional |
| 27 | ** rights. These rights are described in The Qt Company LGPL Exception |
| 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 29 | ** |
| 30 | ** $QT_END_LICENSE$ |
| 31 | ** |
| 32 | ****************************************************************************/ |
| 33 | |
| 34 | //TESTED_COMPONENT=src/serviceframework |
| 35 | |
| 36 | #include <qservicemanager.h> |
| 37 | #include <qremoteserviceregister.h> |
| 38 | |
| 39 | #include <QtTest/QtTest> |
| 40 | #include <QtCore> |
| 41 | #include <QSettings> |
| 42 | #include <QFileInfo> |
| 43 | #include <QDir> |
| 44 | #include <QPair> |
| 45 | #include <QTimer> |
| 46 | |
| 47 | #define PRINT_ERR(a) qPrintable(QString("error = %1").arg(a.error())) |
| 48 | QT_USE_NAMESPACE |
| 49 | |
| 50 | class TestService : public QObject |
| 51 | { |
| 52 | Q_OBJECT |
| 53 | Q_PROPERTY(qint64 time READ time WRITE setTime NOTIFY timeChanged) |
| 54 | |
| 55 | public: |
| 56 | explicit TestService(QObject *parent = 0) |
| 57 | : QObject(parent), m_time(42) |
| 58 | { |
| 59 | } |
| 60 | |
| 61 | ~TestService() |
| 62 | { |
| 63 | } |
| 64 | |
| 65 | Q_INVOKABLE void setTime(qint64 time) { m_time = time; emit timeChanged(); } |
| 66 | qint64 time() const { |
| 67 | return m_time; |
| 68 | } |
| 69 | |
| 70 | signals: |
| 71 | void timeChanged(); |
| 72 | |
| 73 | private: |
| 74 | qint64 m_time; |
| 75 | }; |
| 76 | |
| 77 | static int sigs = 0; |
| 78 | |
| 79 | class tst_QServiceDeletion: public QObject |
| 80 | { |
| 81 | Q_OBJECT |
| 82 | |
| 83 | private: |
| 84 | QObject *connectToService(const QString &serviceName); |
| 85 | |
| 86 | private slots: |
| 87 | void initTestCase(); |
| 88 | |
| 89 | void publishService(); |
| 90 | |
| 91 | void cleanupTestCase(); |
| 92 | |
| 93 | public slots: |
| 94 | void error(QService::UnrecoverableIPCError); |
| 95 | void timeChanged(); |
| 96 | |
| 97 | }; |
| 98 | |
| 99 | void tst_QServiceDeletion::initTestCase() |
| 100 | { |
| 101 | |
| 102 | } |
| 103 | |
| 104 | void tst_QServiceDeletion::cleanupTestCase() |
| 105 | { |
| 106 | |
| 107 | } |
| 108 | |
| 109 | void tst_QServiceDeletion::publishService() |
| 110 | { |
| 111 | QRemoteServiceRegister *serviceRegister = new QRemoteServiceRegister(this); |
| 112 | |
| 113 | QString serviceName = "TestService" ; |
| 114 | QString xmlFilename = QFINDTESTDATA("xmldata/testdeletion.xml" ); |
| 115 | QString interfaceName = "com.nokia.test.services.TestService" ; |
| 116 | QString interfaceVersion = "1.0" ; |
| 117 | QString ipcAddress = "test_service" ; |
| 118 | |
| 119 | QServiceManager serviceManager(QService::UserScope); |
| 120 | serviceManager.removeService(serviceName); |
| 121 | |
| 122 | QRemoteServiceRegister::Entry entry = |
| 123 | serviceRegister->createEntry<TestService>( |
| 124 | serviceName, |
| 125 | interfaceName, |
| 126 | version: interfaceVersion); |
| 127 | entry.setInstantiationType(QRemoteServiceRegister::GlobalInstance); |
| 128 | |
| 129 | QVERIFY(serviceManager.addService(xmlFilename)); |
| 130 | |
| 131 | serviceRegister->publishEntries(ident: ipcAddress); |
| 132 | |
| 133 | // Two connections are created and one of them is deleted later |
| 134 | QObject *conn1 = connectToService(serviceName); |
| 135 | QVERIFY(conn1); |
| 136 | QObject *conn2 = connectToService(serviceName); |
| 137 | QVERIFY(conn2); |
| 138 | |
| 139 | connect(sender: conn1, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), |
| 140 | receiver: this, SLOT(error(QService::UnrecoverableIPCError))); |
| 141 | connect(sender: conn2, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), |
| 142 | receiver: this, SLOT(error(QService::UnrecoverableIPCError))); |
| 143 | connect(sender: conn1, SIGNAL(timeChanged()), |
| 144 | receiver: this, SLOT(timeChanged())); |
| 145 | connect(sender: conn2, SIGNAL(timeChanged()), |
| 146 | receiver: this, SLOT(timeChanged())); |
| 147 | |
| 148 | QCOMPARE(conn1->property("time" ).toInt(), 42); |
| 149 | QCOMPARE(conn2->property("time" ).toInt(), 42); |
| 150 | |
| 151 | QVERIFY(QMetaObject::invokeMethod(conn2, "setTime" , Q_ARG(qint64, 21))); |
| 152 | |
| 153 | QTRY_VERIFY(sigs == 2); |
| 154 | QCOMPARE(conn2->property("time" ).toInt(), 21); |
| 155 | |
| 156 | delete conn2; |
| 157 | QCOMPARE(conn1->property("time" ).toInt(), 21); |
| 158 | |
| 159 | sigs = 0; |
| 160 | QVERIFY(QMetaObject::invokeMethod(conn1, "setTime" , Q_ARG(qint64, 42))); |
| 161 | QTRY_VERIFY(sigs == 1); |
| 162 | QCOMPARE(conn1->property("time" ).toInt(), 42); |
| 163 | |
| 164 | |
| 165 | delete conn1; |
| 166 | serviceManager.removeService(serviceName); |
| 167 | } |
| 168 | |
| 169 | QObject *tst_QServiceDeletion::connectToService(const QString &serviceName) |
| 170 | { |
| 171 | QServiceManager manager; |
| 172 | QList<QServiceInterfaceDescriptor> list = manager.findInterfaces(serviceName); |
| 173 | if (list.isEmpty()) { |
| 174 | qWarning() << "Couldn't find service" << serviceName; |
| 175 | return 0; |
| 176 | } |
| 177 | |
| 178 | // Get the interface descriptor |
| 179 | QServiceInterfaceDescriptor desc = list.at(i: 0); |
| 180 | if (!desc.isValid()) { |
| 181 | qWarning() << "Warning: Invalid service interface descriptor for" << serviceName; |
| 182 | return 0; |
| 183 | } |
| 184 | |
| 185 | QObject* service = manager.loadInterface(descriptor: desc); |
| 186 | if (!service) { |
| 187 | qWarning() << "Couldn't load service interface for" << serviceName; |
| 188 | return 0; |
| 189 | } |
| 190 | return service; |
| 191 | } |
| 192 | |
| 193 | void tst_QServiceDeletion::error(QService::UnrecoverableIPCError) |
| 194 | { |
| 195 | qDebug() << "Error received from IPC" ; |
| 196 | } |
| 197 | |
| 198 | void tst_QServiceDeletion::timeChanged() |
| 199 | { |
| 200 | qDebug() << "time changed" ; |
| 201 | sigs++; |
| 202 | } |
| 203 | |
| 204 | QTEST_MAIN(tst_QServiceDeletion) |
| 205 | |
| 206 | #include "tst_servicedeletion.moc" |
| 207 | |