|
|
@@ -0,0 +1,335 @@
|
|
|
+/*=============================================================================
|
|
|
+
|
|
|
+ Library: CTK
|
|
|
+
|
|
|
+ Copyright (c) German Cancer Research Center,
|
|
|
+ Division of Medical and Biological Informatics
|
|
|
+
|
|
|
+ Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
+ you may not use this file except in compliance with the License.
|
|
|
+ You may obtain a copy of the License at
|
|
|
+
|
|
|
+ http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+
|
|
|
+ Unless required by applicable law or agreed to in writing, software
|
|
|
+ distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+ See the License for the specific language governing permissions and
|
|
|
+ limitations under the License.
|
|
|
+
|
|
|
+=============================================================================*/
|
|
|
+
|
|
|
+
|
|
|
+#include "ctkEAScenario1TestSuite_p.h"
|
|
|
+
|
|
|
+#include <ctkPluginContext.h>
|
|
|
+#include <service/event/ctkEventConstants.h>
|
|
|
+#include <service/event/ctkEventAdmin.h>
|
|
|
+
|
|
|
+#include <QTest>
|
|
|
+
|
|
|
+ctkEAScenario1EventConsumer::ctkEAScenario1EventConsumer(
|
|
|
+ ctkPluginContext* pluginContext, const QStringList& topics,
|
|
|
+ int messagesSent, bool useSignalSlot)
|
|
|
+ : context(pluginContext), topicsToConsume(topics),
|
|
|
+ numOfasynchMessages(0), numOfsynchMessages(0),
|
|
|
+ synchMessageExpectedNumber(0), asynchMessageExpectedNumber(0),
|
|
|
+ messagesSent(messagesSent), error(false), exc(""),
|
|
|
+ useSignalSlot(useSignalSlot)
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1EventConsumer::runTest()
|
|
|
+{
|
|
|
+ numOfasynchMessages = 0;
|
|
|
+ numOfsynchMessages = 0;
|
|
|
+ synchMessageExpectedNumber = 0;
|
|
|
+ asynchMessageExpectedNumber = 0;
|
|
|
+
|
|
|
+ /* create the hashtable to put properties in */
|
|
|
+ ctkDictionary props;
|
|
|
+ /* put service.pid property in hashtable */
|
|
|
+ props.insert(ctkEventConstants::EVENT_TOPIC, topicsToConsume);
|
|
|
+
|
|
|
+ if (useSignalSlot)
|
|
|
+ {
|
|
|
+ /* Claims the reference of the EventAdmin Service */
|
|
|
+ eventAdminRef = context->getServiceReference<ctkEventAdmin>();
|
|
|
+
|
|
|
+ /* assert that a reference is aquired */
|
|
|
+ QVERIFY2(eventAdminRef, "Should be able to get reference to ctkEventAdmin service");
|
|
|
+
|
|
|
+ /* get the service */
|
|
|
+ eventAdmin = context->getService<ctkEventAdmin>(eventAdminRef);
|
|
|
+
|
|
|
+ /* assert that service is available */
|
|
|
+ QVERIFY2(eventAdmin, "Should be able to get instance to ctkEventAdmin object");
|
|
|
+
|
|
|
+ slotId = eventAdmin->subscribeSlot(this, SLOT(handleEvent(ctkEvent)), props);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* register the service */
|
|
|
+ serviceRegistration = context->registerService<ctkEventHandler>(this, props);
|
|
|
+ QVERIFY2(serviceRegistration, "service registration should not be invalid");
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1EventConsumer::cleanup()
|
|
|
+{
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (useSignalSlot)
|
|
|
+ {
|
|
|
+ eventAdmin->unsubscribeSlot(slotId);
|
|
|
+ context->ungetService(eventAdminRef);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ serviceRegistration.unregister();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (const std::logic_error&)
|
|
|
+ {}
|
|
|
+
|
|
|
+ if (error)
|
|
|
+ {
|
|
|
+ throw exc;
|
|
|
+ }
|
|
|
+ QCOMPARE(messagesSent, synchMessageExpectedNumber); //"Not all synch messages recieved"
|
|
|
+ QCOMPARE(messagesSent, asynchMessageExpectedNumber); //"Not all asynch messages recieved"
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1EventConsumer::reset()
|
|
|
+{
|
|
|
+ numOfasynchMessages = 0;
|
|
|
+ numOfsynchMessages = 0;
|
|
|
+ synchMessageExpectedNumber = 0;
|
|
|
+ asynchMessageExpectedNumber = 0;
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1EventConsumer::handleEvent(const ctkEvent& event)
|
|
|
+{
|
|
|
+ try
|
|
|
+ {
|
|
|
+
|
|
|
+//TODO security topic permission
|
|
|
+// TopicPermission permissionAquired
|
|
|
+// = new TopicPermission((String)event.getProperty
|
|
|
+// (EventConstants.EVENT_TOPIC),"subscribe");
|
|
|
+// TopicPermission actualPermission
|
|
|
+// = new TopicPermission("com/acme/*","subscribe");
|
|
|
+
|
|
|
+// assertTrue(getName() +"Should not recevice this topic:"
|
|
|
+// +(String)event.getProperty(EventConstants.EVENT_TOPIC),
|
|
|
+// actualPermission.implies(permissionAquired));
|
|
|
+
|
|
|
+ /* try to get the message */
|
|
|
+ QString message = event.getProperty("Synchronous message").toString();
|
|
|
+ /* check if message is null */
|
|
|
+ if(!message.isNull())
|
|
|
+ {
|
|
|
+ /* its a syncronous message */
|
|
|
+ numOfsynchMessages++;
|
|
|
+ /* print that a message is received */
|
|
|
+ qDebug() << "received a synchronous event with message:" << message;
|
|
|
+ /* get the message number */
|
|
|
+ int aquiredNumber= message.toInt();
|
|
|
+ /* assert that the message is the expected one */
|
|
|
+ QVERIFY2(synchMessageExpectedNumber == aquiredNumber,
|
|
|
+ qPrintable(QString("Expected syncronous message number: %1 got: %2 - order NOT conserved")
|
|
|
+ .arg(synchMessageExpectedNumber).arg(aquiredNumber)));
|
|
|
+
|
|
|
+ /* the next messages of this type should be +1 */
|
|
|
+ synchMessageExpectedNumber++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ message = event.getProperty("Asynchronous message").toString();
|
|
|
+ if(!message.isNull())
|
|
|
+ {
|
|
|
+ numOfasynchMessages++;
|
|
|
+ qDebug() << "received an asynchronous event with message:" << message;
|
|
|
+ /* get the message number */
|
|
|
+ int aquiredNumber= message.toInt();
|
|
|
+ /* assert that the message is the expected one */
|
|
|
+ QVERIFY2(asynchMessageExpectedNumber==aquiredNumber,
|
|
|
+ qPrintable(QString("Expected asyncronous message number: %1 got: %2 - order NOT conserved")
|
|
|
+ .arg(asynchMessageExpectedNumber).arg(aquiredNumber)));
|
|
|
+
|
|
|
+ /* the next messages of this type should be +1 */
|
|
|
+ asynchMessageExpectedNumber++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* assert that the messages property is not null */
|
|
|
+ QVERIFY2(!message.isNull(), "Message should not be null in ");
|
|
|
+
|
|
|
+ /* assert that the messages of syncronous type are not too many */
|
|
|
+ QVERIFY2(numOfsynchMessages < messagesSent+1,
|
|
|
+ "to many synchronous messages in handleEvent()");
|
|
|
+
|
|
|
+ /* assert that the messsage of the asyncronous type are not too many */
|
|
|
+ QVERIFY2(numOfasynchMessages < messagesSent+1,
|
|
|
+ "to many asynchronous messages in handleEvent()");
|
|
|
+
|
|
|
+ }
|
|
|
+ catch (const ctkRuntimeException& e)
|
|
|
+ {
|
|
|
+ error = true;
|
|
|
+ exc = e;
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ error = true;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+ctkEAScenario1EventPublisher::ctkEAScenario1EventPublisher(
|
|
|
+ ctkPluginContext* context, const QString& name,
|
|
|
+ int id, int numOfMessage, bool useSignalSlot)
|
|
|
+ : eventAdmin(0), context(context), messageTosend(numOfMessage), useSignalSlot(useSignalSlot)
|
|
|
+{
|
|
|
+ thread.setObjectName(QString("%1-%2").arg(name).arg(id));
|
|
|
+ moveToThread(&thread);
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1EventPublisher::runTest()
|
|
|
+{
|
|
|
+ /* Claims the reference of the EventAdmin Service */
|
|
|
+ serviceReference = context->getServiceReference<ctkEventAdmin>();
|
|
|
+
|
|
|
+ /* assert that a reference is aquired */
|
|
|
+ QVERIFY2(serviceReference, "Should be able to get reference to ctkEventAdmin service");
|
|
|
+
|
|
|
+ /* get the service */
|
|
|
+ eventAdmin = context->getService<ctkEventAdmin>(serviceReference);
|
|
|
+
|
|
|
+ /* assert that service is available */
|
|
|
+ QVERIFY2(eventAdmin, "Should be able to get instance to ctkEventAdmin object");
|
|
|
+
|
|
|
+ if (useSignalSlot)
|
|
|
+ {
|
|
|
+ eventAdmin->publishSignal(this, SIGNAL(syncSignalEvent(ctkEvent)), Qt::DirectConnection);
|
|
|
+ eventAdmin->publishSignal(this, SIGNAL(asyncSignalEvent(ctkEvent)), Qt::QueuedConnection);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* start the delivery thread */
|
|
|
+ connect(&thread, SIGNAL(started()), SLOT(sendEvents()));
|
|
|
+
|
|
|
+ /* print that the test has started */
|
|
|
+ qDebug() << "Testing synchronus delivery";
|
|
|
+ thread.start();
|
|
|
+
|
|
|
+ /* wait until thread is dead */
|
|
|
+ thread.wait();
|
|
|
+
|
|
|
+ disconnect(&thread, SIGNAL(started()), this, SLOT(sendEvents()));
|
|
|
+ connect(&thread, SIGNAL(started()), SLOT(postEvents()));
|
|
|
+ /* print that the test has started */
|
|
|
+ qDebug() << "Testing asynchronous delivery";
|
|
|
+ /* start the test */
|
|
|
+ thread.start();
|
|
|
+
|
|
|
+ /* wait until thread is dead */
|
|
|
+ thread.wait();
|
|
|
+
|
|
|
+ context->ungetService(serviceReference);
|
|
|
+
|
|
|
+ QTest::qWait(500); // allow for delivery
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1EventPublisher::sendEvents()
|
|
|
+{
|
|
|
+ qDebug() << "Starting to send events";
|
|
|
+ /* deliver the messages */
|
|
|
+ for (int i = 0; i < messageTosend; i++)
|
|
|
+ {
|
|
|
+ /* a Hash table to store message in */
|
|
|
+ ctkDictionary message;
|
|
|
+ /* put some properties into the messages */
|
|
|
+ message.insert("Synchronous message", i);
|
|
|
+ /* send the message */
|
|
|
+ ctkEvent event("com/acme/timer", message);
|
|
|
+ if (useSignalSlot)
|
|
|
+ {
|
|
|
+ emit syncSignalEvent(event);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ eventAdmin->sendEvent(event);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ thread.quit();
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1EventPublisher::postEvents()
|
|
|
+{
|
|
|
+ qDebug() << "Starting to post events";
|
|
|
+ for (int i = 0; i < messageTosend; i++)
|
|
|
+ {
|
|
|
+ /* create the hasht table */
|
|
|
+ ctkDictionary message;
|
|
|
+ /* create the message */
|
|
|
+ message.insert("Asynchronous message", i);
|
|
|
+ /* Sends an asynchronous event to the admin */
|
|
|
+ ctkEvent event("com/acme/timer", message);
|
|
|
+ if (useSignalSlot)
|
|
|
+ {
|
|
|
+ emit asyncSignalEvent(event);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ eventAdmin->postEvent(event);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ thread.quit();
|
|
|
+}
|
|
|
+
|
|
|
+ctkEAScenario1TestSuite::ctkEAScenario1TestSuite(ctkPluginContext* context, long eventPluginId, bool useSignalSlot)
|
|
|
+ : pluginContext(context), MESSAGES_SENT(10), eventPluginId(eventPluginId),
|
|
|
+ eventConsumer(0), eventPublisher(0), useSignalSlot(useSignalSlot)
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1TestSuite::initTestCase()
|
|
|
+{
|
|
|
+ qDebug() << "Using" << (useSignalSlot ? "" : "no") << "Qt signal/slot mechanism";
|
|
|
+
|
|
|
+ pluginContext->getPlugin(eventPluginId)->start();
|
|
|
+
|
|
|
+ QStringList scenario1_topics("com/acme/*");
|
|
|
+
|
|
|
+ /* add the event consumer to the test suite */
|
|
|
+ eventConsumer = new ctkEAScenario1EventConsumer(pluginContext,
|
|
|
+ scenario1_topics, MESSAGES_SENT,
|
|
|
+ useSignalSlot);
|
|
|
+
|
|
|
+ eventPublisher = new ctkEAScenario1EventPublisher(pluginContext,
|
|
|
+ "Scenario 1 EventPublisher",
|
|
|
+ 1, MESSAGES_SENT,
|
|
|
+ useSignalSlot);
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1TestSuite::cleanupTestCase()
|
|
|
+{
|
|
|
+ eventConsumer->cleanup();
|
|
|
+ delete eventPublisher;
|
|
|
+ delete eventConsumer;
|
|
|
+ pluginContext->getPlugin(eventPluginId)->stop();
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1TestSuite::testRegisterConsumer()
|
|
|
+{
|
|
|
+ eventConsumer->reset();
|
|
|
+ eventConsumer->runTest();
|
|
|
+}
|
|
|
+
|
|
|
+void ctkEAScenario1TestSuite::testPublishEvents()
|
|
|
+{
|
|
|
+ eventPublisher->runTest();
|
|
|
+}
|