Bladeren bron

Test-suite for CTK EventAdmin implementations.

This is a black-box test suite, using only the interfaces
defined in the EventAdmin specs. More tests will be provided
in the future.
Sascha Zelzer 16 jaren geleden
bovenliggende
commit
0d812a6fb4

+ 1 - 0
Libs/PluginFramework/Testing/CMakeLists.txt

@@ -18,3 +18,4 @@ ADD_SUBDIRECTORY(FrameworkTest)
 ADD_SUBDIRECTORY(FrameworkTestPlugins)
 
 ADD_SUBDIRECTORY(ConfigAdminTest)
+ADD_SUBDIRECTORY(EventAdminTest)

+ 50 - 0
Libs/PluginFramework/Testing/EventAdminTest/CMakeLists.txt

@@ -0,0 +1,50 @@
+PROJECT(org_commontk_eventadmintest)
+
+SET(PLUGIN_export_directive "org_commontk_eventadmintest_EXPORT")
+
+SET(PLUGIN_SRCS
+  ctkEventAdminTestActivator_p.h
+  ctkEventAdminTestActivator.cpp
+  ctkEAScenario1TestSuite_p.h
+  ctkEAScenario1TestSuite.cpp
+  ctkEAScenario2TestSuite_p.h
+  ctkEAScenario2TestSuite.cpp
+  ctkEAScenario3TestSuite_p.h
+  ctkEAScenario3TestSuite.cpp
+  ctkEAScenario4TestSuite_p.h
+  ctkEAScenario4TestSuite.cpp
+  ctkEATopicWildcardTestSuite_p.h
+  ctkEATopicWildcardTestSuite.cpp
+)
+
+SET(PLUGIN_MOC_SRCS
+  ctkEventAdminTestActivator_p.h
+  ctkEAScenario1TestSuite_p.h
+  ctkEAScenario2TestSuite_p.h
+  ctkEAScenario3TestSuite_p.h
+  ctkEAScenario4TestSuite_p.h
+  ctkEATopicWildcardTestSuite_p.h
+)
+
+SET(PLUGIN_UI_FORMS
+  
+)
+
+SET(PLUGIN_resources
+  
+)
+
+ctkMacroGetTargetLibraries(PLUGIN_target_libraries)
+
+ctkMacroBuildPlugin(
+  NAME ${PROJECT_NAME}
+  EXPORT_DIRECTIVE ${PLUGIN_export_directive}
+  SRCS ${PLUGIN_SRCS}
+  MOC_SRCS ${PLUGIN_MOC_SRCS}
+  UI_FORMS ${PLUGIN_UI_FORMS}
+  RESOURCES ${PLUGIN_resources}
+  TARGET_LIBRARIES ${PLUGIN_target_libraries}
+  TEST_PLUGIN
+)
+
+SET(eventadmin_test ${PROJECT_NAME} CACHE INTERNAL "Target name for the plugin containing unit tests for EventAdmin implementations")

+ 335 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario1TestSuite.cpp

@@ -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();
+}

+ 192 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario1TestSuite_p.h

@@ -0,0 +1,192 @@
+/*=============================================================================
+
+  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.
+
+=============================================================================*/
+
+
+#ifndef CTKEASCENARIO1TESTSUITE_P_H
+#define CTKEASCENARIO1TESTSUITE_P_H
+
+#include <QObject>
+#include <QThread>
+
+#include <service/event/ctkEventHandler.h>
+#include <ctkTestSuiteInterface.h>
+#include <ctkServiceRegistration.h>
+#include <ctkRuntimeException.h>
+
+class ctkPluginContext;
+struct ctkEventAdmin;
+
+/**
+ * This class consumes events
+ */
+class ctkEAScenario1EventConsumer : public QObject, public ctkEventHandler
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkEventHandler)
+
+private:
+
+  ctkPluginContext* context;
+
+  ctkServiceReference eventAdminRef;
+  ctkEventAdmin* eventAdmin;
+  qlonglong slotId;
+
+  /** class variable for service registration */
+  ctkServiceRegistration serviceRegistration;
+
+  /** class variable indicating the topics */
+  QStringList topicsToConsume;
+
+  /** class variable keeping number of asynchronus messages */
+  int numOfasynchMessages;
+
+  /** class variable keeping number of synchronus messages */
+  int numOfsynchMessages;
+
+  /** class variable holding the old syncronus message nummber */
+  int synchMessageExpectedNumber;
+
+  /** class variable holding the old asyncronus message nummber */
+  int asynchMessageExpectedNumber;
+
+  const int messagesSent;
+
+  bool error;
+  ctkRuntimeException exc;
+
+  bool useSignalSlot;
+
+public:
+
+  /**
+   * Constructor creates a consumer service
+   */
+  ctkEAScenario1EventConsumer(ctkPluginContext* pluginContext, const QStringList& topics,
+                              int messagesSent, bool useSignalSlot);
+
+  /**
+   * run the test
+   */
+  void runTest();
+  void cleanup();
+  void reset();
+
+public slots:
+
+  /**
+   * This method takes events from the event admin service.
+   */
+  void handleEvent(const ctkEvent& event);
+
+};
+
+/**
+ * Class publish events
+ */
+class ctkEAScenario1EventPublisher : public QObject
+{
+  Q_OBJECT
+
+private:
+
+  /** A reference to a service */
+  ctkServiceReference serviceReference;
+
+  /** The admin which delivers the events */
+  ctkEventAdmin* eventAdmin;
+
+  /** class variable holding bundle context */
+  ctkPluginContext* context;
+
+  /** variable holding messages to send */
+  int messageTosend;
+
+  QThread thread;
+
+  bool useSignalSlot;
+
+public:
+
+  ctkEAScenario1EventPublisher(ctkPluginContext* context, const QString& name,
+                               int id, int numOfMessage, bool useSignalSlot);
+
+  void runTest();
+
+protected slots:
+
+  void sendEvents();
+  void postEvents();
+
+signals:
+
+  void syncSignalEvent(const ctkEvent&);
+  void asyncSignalEvent(const ctkEvent&);
+};
+
+/**
+ * Test sute for testing the requirements specified in the test
+ * specification for the EventAdmin service. It will ensure that the
+ * events arrive in time and order it will even check that the
+ * wildcards according to the topics works properly.
+ *
+ * @author Magnus Klack
+ */
+class ctkEAScenario1TestSuite : public QObject, public ctkTestSuiteInterface
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkTestSuiteInterface)
+
+private:
+
+  /** plugin context variable */
+  ctkPluginContext* pluginContext;
+  /** the messages to be deliverd */
+  const int MESSAGES_SENT;
+  long eventPluginId;
+  ctkServiceReference reference;
+
+  ctkEAScenario1EventConsumer* eventConsumer;
+  ctkEAScenario1EventPublisher* eventPublisher;
+
+  bool useSignalSlot;
+
+public:
+
+  /**
+   * Constructor for the TestSuite class.
+   *
+   * @param context The handle to the framework
+   * @param eventPluginId The id of the plugin implementing the EventAdmin spec
+   */
+  ctkEAScenario1TestSuite(ctkPluginContext* context, long eventPluginId, bool useSignalSlot);
+
+private slots:
+
+  void initTestCase();
+  void cleanupTestCase();
+
+  void testRegisterConsumer();
+  void testPublishEvents();
+
+};
+
+#endif // CTKEASCENARIO1TESTSUITE_P_H

+ 264 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario2TestSuite.cpp

@@ -0,0 +1,264 @@
+/*=============================================================================
+
+  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 "ctkEAScenario2TestSuite_p.h"
+
+#include <ctkPluginContext.h>
+#include <service/event/ctkEventConstants.h>
+#include <service/event/ctkEventAdmin.h>
+
+#include <QTest>
+
+ctkEAScenario2EventConsumer::ctkEAScenario2EventConsumer(
+  ctkPluginContext* pluginContext, const QStringList& topics,
+  int numSyncMsg, int numAsyncMsg)
+  : context(pluginContext),topicsToConsume(topics),
+    asynchMessages(0), synchMessages(0), numSyncMessages(numSyncMsg),
+    numAsyncMessages(numAsyncMsg), error(false), exc("")
+{
+
+}
+
+void ctkEAScenario2EventConsumer::runTest()
+{
+  asynchMessages = 0;
+  synchMessages = 0;
+  /* create the hashtable to put properties in */
+  ctkDictionary props;
+  /* put service.pid property in hashtable */
+  props.insert(ctkEventConstants::EVENT_TOPIC, topicsToConsume);
+  /* register the service */
+  serviceRegistration = context->registerService<ctkEventHandler>(this, props);
+
+  QVERIFY2(serviceRegistration, "service registration should not be invalid");
+}
+
+void ctkEAScenario2EventConsumer::cleanup()
+{
+  QMutexLocker l(&mutex);
+  try
+  {
+    serviceRegistration.unregister();
+  }
+  catch (const std::logic_error&)
+  {}
+
+  if (error)
+  {
+    throw exc;
+  }
+
+  QCOMPARE(synchMessages, numSyncMessages); // "Not all synch messages recieved"
+  QCOMPARE(asynchMessages, numAsyncMessages); // "Not all asynch messages recieved"
+}
+
+void ctkEAScenario2EventConsumer::handleEvent(const ctkEvent& event)
+{
+  QMutexLocker l(&mutex);
+  try
+  {
+    /* get the topic from the event*/
+//    QString eventTopic = event.getTopic();
+    //TODO security topic permission
+//    /* make a topic permission from the received topic in order to check it*/
+//    TopicPermission permissionAccuired = new TopicPermission(eventTopic, "SUBSCRIBE");
+//    /* make a topic permission from the topic to consume in order to check it*/
+//    TopicPermission actualPermission = new TopicPermission(topicsToConsume[0], "SUBSCRIBE");
+//    /* assert if the topic in the event is the same as the topic to listen fore including wildcard */
+//    assertTrue("The topics was not equal", actualPermission.implies(permissionAccuired));
+
+    /* try to get the message */
+    QString message = event.getProperty("Synchronous message").toString();
+
+    if(!message.isNull())
+    {
+      /* its a syncronous message */
+      qDebug() << "received a synchronous event with message:" << message;
+      /* assert that the messages of syncronous type are not too many */
+      QVERIFY2(synchMessages < numSyncMessages, "too many synchronous messages");
+      synchMessages++;
+      qDebug() << "Max number of Sync messages is:" << numSyncMessages << "and number of received Sync messages is: " << synchMessages;
+    }
+    else
+    {
+      message = event.getProperty("Asynchronous message").toString();
+      if(!message.isNull())
+      {
+        qDebug() << "received an asynchronous event with message:" << message;
+        /* assert that the messsage of the asyncronous type are not too many */
+        QVERIFY2(asynchMessages < numAsyncMessages, "too many asynchronous messages");
+        asynchMessages++;
+        qDebug() << "Max number of Async messages is:" << numAsyncMessages << "and number of received Async messages is:" << asynchMessages;
+      }
+    }
+  }
+  catch (const ctkRuntimeException& e)
+  {
+    error = true;
+    exc = e;
+    throw e;
+  }
+  catch (...)
+  {
+    error = true;
+  }
+}
+
+ctkEAScenario2EventPublisher::ctkEAScenario2EventPublisher(ctkPluginContext* context,
+                             const QString& name, const QStringList topics,
+                             int id, int numOfMessage)
+  : eventAdmin(0), context(context),
+    messageTosend(numOfMessage), topicsToSend(topics)
+{
+  thread.setObjectName(QString("%1-%2").arg(name).arg(id));
+  moveToThread(&thread);
+}
+
+void ctkEAScenario2EventPublisher::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");
+
+  eventAdmin = context->getService<ctkEventAdmin>(serviceReference);
+
+  QVERIFY2(eventAdmin, "Should be able to get instance to ctkEventAdmin object");
+
+  connect(&thread, SIGNAL(started()), SLOT(sendEvents()));
+  thread.start();
+  /* wait until thread is dead */
+  thread.wait();
+
+  disconnect(&thread, SIGNAL(started()), this, SLOT(sendEvents()));
+  connect(&thread, SIGNAL(started()), SLOT(postEvents()));
+  thread.start();
+  /* wait until thread is dead */
+  thread.wait();
+
+  context->ungetService(serviceReference);
+
+  QTest::qWait(1000); // allow for delivery
+}
+
+void ctkEAScenario2EventPublisher::sendEvents()
+{
+  for (int i = 0; i < messageTosend; i++)
+  {
+    try
+    {
+      /* a Hash table to store message in */
+      ctkDictionary message;
+      /* put some properties into the messages */
+      message.insert("Synchronous message",i);
+      /* send the message */
+      qDebug() << " sending a synchronous event with message:"
+               << message << "and the topic:" << topicsToSend[i];
+      eventAdmin->sendEvent(ctkEvent(topicsToSend[i], message));
+    }
+    catch(const std::exception& e)
+    {
+      qDebug() << "Error when publishing synhronous:" << e.what();
+    }
+  }
+  thread.quit();
+}
+
+void ctkEAScenario2EventPublisher::postEvents()
+{
+  for (int i = 0; i < messageTosend; i++)
+  {
+    try
+    {
+      /* create the hasht table */
+      ctkDictionary message;
+      /* create the message */
+      message.insert("Asynchronous message",i);
+      /* Sends an asynchronous event to the admin */
+      qDebug() << "sending an Asynchronous event with message:"
+               << message << "and the topic:" << topicsToSend[i];
+      eventAdmin->postEvent(ctkEvent(topicsToSend[i], message));
+    }
+    catch(const std::exception& e)
+    {
+      qDebug() << "Error when publishing asynhronous:" << e.what();
+    }
+  }
+  thread.quit();
+}
+
+ctkEAScenario2TestSuite::ctkEAScenario2TestSuite(ctkPluginContext* context, long eventPluginId)
+  : pluginContext(context), eventPluginId(eventPluginId)
+{
+
+}
+
+void ctkEAScenario2TestSuite::initTestCase()
+{
+  pluginContext->getPlugin(eventPluginId)->start();
+
+  /* create a topic string */
+  QStringList scenario2_topics1("com/acme/timer");
+  QStringList scenario2_topics2("com/*");
+
+  QStringList scenario2_topicsToPublish;
+  scenario2_topicsToPublish << "";
+  scenario2_topicsToPublish << "com/AcMe/TiMeR";
+  scenario2_topicsToPublish << "com.acme.timer";
+  scenario2_topicsToPublish << "com/acme/timer";
+
+  eventConsumers.push_back(new ctkEAScenario2EventConsumer(
+                             pluginContext, scenario2_topics1,
+                             1,1));
+  eventConsumers.push_back(new ctkEAScenario2EventConsumer(
+                             pluginContext, scenario2_topics2,
+                             2,2));
+
+  eventPublisher = new ctkEAScenario2EventPublisher(
+        pluginContext, "Scenario 2 EventPublisher",
+        scenario2_topicsToPublish, 2, 4);
+}
+
+void ctkEAScenario2TestSuite::cleanupTestCase()
+{
+  foreach (ctkEAScenario2EventConsumer* consumer, eventConsumers)
+  {
+    consumer->cleanup();
+  }
+  delete eventPublisher;
+  qDeleteAll(eventConsumers);
+  pluginContext->getPlugin(eventPluginId)->stop();
+}
+
+void ctkEAScenario2TestSuite::testRegisterConsumer()
+{
+  foreach(ctkEAScenario2EventConsumer* consumer, eventConsumers)
+  {
+    consumer->runTest();
+  }
+}
+
+void ctkEAScenario2TestSuite::testPublishEvents()
+{
+  eventPublisher->runTest();
+}

+ 167 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario2TestSuite_p.h

@@ -0,0 +1,167 @@
+/*=============================================================================
+
+  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.
+
+=============================================================================*/
+
+
+#ifndef CTKEASCENARIO2TESTSUITE_P_H
+#define CTKEASCENARIO2TESTSUITE_P_H
+
+#include <QObject>
+#include <QThread>
+#include <QMutex>
+
+#include <service/event/ctkEventHandler.h>
+#include <ctkTestSuiteInterface.h>
+#include <ctkServiceRegistration.h>
+#include <ctkRuntimeException.h>
+
+struct ctkEventAdmin;
+
+class ctkEAScenario2EventConsumer : public QObject, public ctkEventHandler
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkEventHandler)
+
+private:
+
+  ctkPluginContext* context;
+
+  /** class variable for service registration */
+  ctkServiceRegistration serviceRegistration;
+
+  /** class variable indicating the topics */
+  QStringList topicsToConsume;
+
+  /** class variable keeping number of asynchronus message */
+  int asynchMessages;
+
+  /** class variable keeping number of synchronus message */
+  int synchMessages;
+
+  /** class variable indication the number of synchronous messages to be received */
+  int numSyncMessages;
+
+  /** class variable indication the number of asynchronous messages to be received */
+  int numAsyncMessages;
+
+  bool error;
+  ctkRuntimeException exc;
+
+  QMutex mutex;
+
+public:
+
+  /**
+   * Constructor creates a consumer service
+   */
+  ctkEAScenario2EventConsumer(ctkPluginContext* pluginContext, const QStringList& topics,
+                              int numSyncMsg, int numAsyncMsg);
+
+  void runTest();
+
+  void cleanup();
+
+  /**
+   * This method takes events from the event admin service.
+   */
+  void handleEvent(const ctkEvent& event);
+};
+
+class ctkEAScenario2EventPublisher : public QObject
+{
+  Q_OBJECT
+
+private:
+
+  /** A reference to a service */
+  ctkServiceReference serviceReference;
+
+  /** The admin which delivers the events */
+  ctkEventAdmin* eventAdmin;
+
+  /** class variable holding plugin context */
+  ctkPluginContext* context;
+
+  /** variable holding messages to send */
+  int messageTosend;
+
+  /** variable holding the topic to send */
+  QStringList topicsToSend;
+
+  QThread thread;
+
+public:
+
+  ctkEAScenario2EventPublisher(ctkPluginContext* context,
+                               const QString& name, const QStringList topics,
+                               int id, int numOfMessage);
+
+  void runTest();
+
+protected slots:
+
+  void sendEvents();
+  void postEvents();
+};
+
+
+/**
+ * Test suite for testing the requirements specified in the test specification
+ * for the EventAdmin service.
+ *
+ * Check the Topic sorting of events, both synchronous and asynchronous.
+ *
+ */
+class ctkEAScenario2TestSuite : public QObject, public ctkTestSuiteInterface
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkTestSuiteInterface)
+
+private:
+
+  /** plugin context variable */
+  ctkPluginContext* pluginContext;
+
+  long eventPluginId;
+
+  QList<ctkEAScenario2EventConsumer*> eventConsumers;
+  ctkEAScenario2EventPublisher* eventPublisher;
+
+public:
+
+  /**
+   * Constructor for the TestSuite class.
+   *
+   * @param context the handle to the frame work
+   * @param eventPluginId The id of the plugin implementing the EventAdmin spec
+   */
+  ctkEAScenario2TestSuite(ctkPluginContext* context, long eventPluginId);
+
+private slots:
+
+  void initTestCase();
+  void cleanupTestCase();
+
+  void testRegisterConsumer();
+  void testPublishEvents();
+
+};
+
+#endif // CTKEASCENARIO2TESTSUITE_P_H

+ 235 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario3TestSuite.cpp

@@ -0,0 +1,235 @@
+/*=============================================================================
+
+  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 "ctkEAScenario3TestSuite_p.h"
+
+#include <ctkPluginContext.h>
+#include <service/event/ctkEventConstants.h>
+#include <service/event/ctkEventAdmin.h>
+
+#include <QTest>
+
+ctkEAScenario3EventConsumer::ctkEAScenario3EventConsumer(
+  ctkPluginContext* pluginContext, const QStringList topics,
+  int numSyncMsg, int numAsyncMsg)
+  : context(pluginContext), topicsToConsume(topics), asynchMessages(0), synchMessages(0),
+    numSyncMessages(numSyncMsg), numAsyncMessages(numAsyncMsg), error(false), exc("")
+{
+
+}
+
+void ctkEAScenario3EventConsumer::runTest()
+{
+  asynchMessages = 0;
+  synchMessages = 0;
+  /* create the hashtable to put properties in */
+  ctkDictionary props;
+
+  /* put service.pid property in hashtable */
+  props.insert(ctkEventConstants::EVENT_TOPIC, topicsToConsume);
+
+  /* register the service */
+  serviceRegistration = context->registerService<ctkEventHandler>(this, props);
+
+  QVERIFY2(serviceRegistration, "service registration should not be null");
+}
+
+void ctkEAScenario3EventConsumer::cleanup()
+{
+  QMutexLocker l(&mutex);
+  try
+  {
+    serviceRegistration.unregister();
+  }
+  catch (const std::logic_error&) {}
+
+  if (error)
+  {
+    throw exc;
+  }
+
+  QCOMPARE(synchMessages, numSyncMessages); // "Not all synch messages recieved"
+  QCOMPARE(asynchMessages, numAsyncMessages); // "Not all asynch messages recieved"
+}
+
+void ctkEAScenario3EventConsumer::handleEvent(const ctkEvent& event)
+{
+  QMutexLocker l(&mutex);
+  try
+  {
+    /* try to get the message */
+    QString message = event.getProperty("Synchronous message").toString();
+
+    if (!message.isNull())
+    {
+      /* its an asyncronous message */
+      synchMessages++;
+      qDebug() << "recived a Synchronous event with message:" << message;
+    }
+    else
+    {
+      message = event.getProperty("Asynchronous message").toString();
+      if (!message.isNull())
+      {
+        asynchMessages++;
+        qDebug() << "recived an Asynchronus event with message:" << message;
+      }
+    }
+
+    /* assert that the messages property is not null */
+    QVERIFY2(!message.isNull(), "Message should not be null in handleEvent()");
+
+    /* assert that the messages of syncronous type are not too many */
+    QVERIFY2(synchMessages < numSyncMessages + 1, "too many synchronous messages");
+    /* assert that the messsage of the asyncronous type are not too many */
+    QVERIFY2(asynchMessages < numAsyncMessages + 1, "too many asynchronous messages");
+  }
+  catch (const ctkRuntimeException& e)
+  {
+    error = true;
+    exc = e;
+    throw e;
+  }
+  catch (...)
+  {
+    error = true;
+  }
+}
+
+void ctkEAScenario3EventPublisher::sendEvents()
+{
+  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 */
+    qDebug() << "sending a synchronous event with message:"
+             << message << "and the topic:" << topicToSend;
+    eventAdmin->sendEvent(ctkEvent(topicToSend, message));
+  }
+  thread.quit();
+}
+
+void ctkEAScenario3EventPublisher::postEvents()
+{
+  for (int i = 0; i < messageTosend; i++)
+  {
+    /* create the hasht table */
+    ctkDictionary message;
+    /* create the message */
+    message.insert("Asynchronous message", i);
+    /* Sends a asynchronous event to the admin */
+    qDebug() << "sending an Asynchronous event with message:"
+             << message << "and the topic:" << topicToSend;
+    eventAdmin->postEvent(ctkEvent(topicToSend, message));
+  }
+  thread.quit();
+}
+
+ctkEAScenario3EventPublisher::ctkEAScenario3EventPublisher(ctkPluginContext* context, const QString& name,
+                             int id, int numOfMessage, const QString& topic)
+  : eventAdmin(0), context(context), messageTosend(numOfMessage), topicToSend(topic)
+{
+  thread.setObjectName(QString("%1-%2").arg(name).arg(id));
+  moveToThread(&thread);
+}
+
+void ctkEAScenario3EventPublisher::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");
+
+  eventAdmin = context->getService<ctkEventAdmin>(serviceReference);
+
+  QVERIFY2(eventAdmin, "Should be able to get instance to ctkEventAdmin object");
+
+  connect(&thread, SIGNAL(started()), SLOT(sendEvents()));
+  thread.start();
+  /* wait until thread is dead */
+  thread.wait();
+
+  disconnect(&thread, SIGNAL(started()), this, SLOT(sendEvents()));
+  connect(&thread, SIGNAL(started()), SLOT(postEvents()));
+  thread.start();
+  /* wait until thread is dead */
+  thread.wait();
+
+  QTest::qWait(1000); // allow for delivery
+}
+
+ctkEAScenario3TestSuite::ctkEAScenario3TestSuite(ctkPluginContext* context, long eventPluginId)
+  : pluginContext(context), eventPluginId(eventPluginId)
+{
+
+}
+
+void ctkEAScenario3TestSuite::initTestCase()
+{
+  pluginContext->getPlugin(eventPluginId)->start();
+
+  /* create a topic string */
+  QStringList scenario3_topics1;
+  scenario3_topics1 << "com/acme/timer";
+  scenario3_topics1 << "com/acme/log";
+
+  /* add the event consumer with the correct topics to the test suite */
+  eventConsumers.push_back(new ctkEAScenario3EventConsumer(pluginContext, scenario3_topics1, 8, 8));
+
+  eventPublishers.push_back(new ctkEAScenario3EventPublisher(
+                              pluginContext, "Scenario 3 EventPublisher1",
+                              3, 4, "com/acme/timer"));
+  eventPublishers.push_back(new ctkEAScenario3EventPublisher(
+                              pluginContext, "Scenario 3 EventPublisher2",
+                              3, 4, "com/acme/log"));
+}
+
+void ctkEAScenario3TestSuite::cleanupTestCase()
+{
+  foreach(ctkEAScenario3EventConsumer* eventConsumer, eventConsumers)
+  {
+    eventConsumer->cleanup();
+  }
+  qDeleteAll(eventPublishers);
+  qDeleteAll(eventConsumers);
+  pluginContext->getPlugin(eventPluginId)->stop();
+}
+
+void ctkEAScenario3TestSuite::testRegisterConsumer()
+{
+  foreach(ctkEAScenario3EventConsumer* consumer, eventConsumers)
+  {
+    consumer->runTest();
+  }
+}
+
+void ctkEAScenario3TestSuite::testPublishEvents()
+{
+  foreach(ctkEAScenario3EventPublisher* publisher, eventPublishers)
+  {
+    publisher->runTest();
+  }
+}

+ 181 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario3TestSuite_p.h

@@ -0,0 +1,181 @@
+/*=============================================================================
+
+  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.
+
+=============================================================================*/
+
+
+#ifndef CTKEASCENARIO3TESTSUITE_P_H
+#define CTKEASCENARIO3TESTSUITE_P_H
+
+#include <QObject>
+#include <QThread>
+#include <QMutex>
+
+#include <service/event/ctkEventHandler.h>
+#include <ctkTestSuiteInterface.h>
+#include <ctkServiceRegistration.h>
+#include <ctkRuntimeException.h>
+
+struct ctkEventAdmin;
+
+class ctkEAScenario3EventConsumer : public QObject, public ctkEventHandler
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkEventHandler)
+
+private:
+
+  ctkPluginContext* context;
+
+  /** class variable for service registration */
+  ctkServiceRegistration serviceRegistration;
+
+  /** class variable indicating the topics correct version */
+  QStringList topicsToConsume;
+
+  /** class variable keeping number of asynchronous message */
+  int asynchMessages;
+
+  /** class variable keeping number of synchronous message */
+  int synchMessages;
+
+  /**
+   * class variable indication the number of synchronous messages to be
+   * received
+   */
+  int numSyncMessages;
+
+  /**
+   * class variable indication the number of asynchronous messages to be
+   * received
+   */
+  int numAsyncMessages;
+
+  bool error;
+  ctkRuntimeException exc;
+
+  QMutex mutex;
+
+public:
+
+  /**
+   * Constructor creates a consumer service
+   *
+   * @param bundleContext
+   * @param topics
+   * @param numSyncMsg
+   *            number of synchronous messages to be received
+   * @param numAsyncMsg
+   *            number of asynchronous messages to be received
+   * @param name
+   *            name of the Consumer
+   * @param id
+   */
+  ctkEAScenario3EventConsumer(ctkPluginContext* pluginContext, const QStringList topics,
+                       int numSyncMsg, int numAsyncMsg);
+
+  void runTest();
+
+  void cleanup();
+
+  /**
+   * This method takes events from the event admin service.
+   */
+  void handleEvent(const ctkEvent& event);
+};
+
+class ctkEAScenario3EventPublisher : public QObject
+{
+  Q_OBJECT
+
+private:
+
+  /** A reference to a service */
+  ctkServiceReference serviceReference;
+
+  /** The admin which delivers the events */
+  ctkEventAdmin* eventAdmin;
+
+  /** class variable holding plugin context */
+  ctkPluginContext* context;
+
+  /** variable holding messages to send */
+  int messageTosend;
+
+  /** variable holding the topic to use */
+  QString topicToSend;
+
+  QThread thread;
+
+protected slots:
+
+  void sendEvents();
+  void postEvents();
+
+public:
+
+  ctkEAScenario3EventPublisher(ctkPluginContext* context, const QString& name,
+                               int id, int numOfMessage, const QString& topic);
+
+  void runTest();
+};
+
+/**
+ * Test suite for testing the requirements specified in the test specification
+ * for the EventAdmin service.
+ *
+ * Several minor test of the Topics, this is done both synchronously and
+ * asynchronously.
+ */
+class ctkEAScenario3TestSuite : public QObject, public ctkTestSuiteInterface
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkTestSuiteInterface)
+
+private:
+
+  /** plugin context variable */
+  ctkPluginContext* pluginContext;
+
+  long eventPluginId;
+
+  QList<ctkEAScenario3EventConsumer*> eventConsumers;
+  QList<ctkEAScenario3EventPublisher*> eventPublishers;
+
+public:
+
+  /**
+   * Constructor for the TestSuite class.
+   *
+   * @param context
+   *            the handle to the frame work
+   */
+  ctkEAScenario3TestSuite(ctkPluginContext* context, long eventPluginId);
+
+private slots:
+
+  void initTestCase();
+  void cleanupTestCase();
+
+  void testRegisterConsumer();
+  void testPublishEvents();
+
+};
+
+#endif // CTKEASCENARIO3TESTSUITE_P_H

+ 269 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario4TestSuite.cpp

@@ -0,0 +1,269 @@
+/*=============================================================================
+
+  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 "ctkEAScenario4TestSuite_p.h"
+
+#include <ctkPluginContext.h>
+#include <service/event/ctkEventConstants.h>
+#include <service/event/ctkEventAdmin.h>
+
+#include <QTest>
+
+ctkEAScenario4EventConsumer::ctkEAScenario4EventConsumer(
+  ctkPluginContext* pluginContext, const QStringList topics,
+  int numSyncMsg, int numAsyncMsg, const QString& filter)
+  : context(pluginContext), topicsToConsume(topics), filterToConsume(filter),
+    asynchMessages(0), synchMessages(0), numSyncMessages(numSyncMsg),
+    numAsyncMessages(numAsyncMsg), error(false), exc("")
+{
+
+}
+
+void ctkEAScenario4EventConsumer::runTest()
+{
+  asynchMessages = 0;
+  synchMessages = 0;
+  /* create the hashtable to put properties in */
+  ctkDictionary props;
+
+  /* put service.pid property in hashtable */
+  props.insert(ctkEventConstants::EVENT_TOPIC, topicsToConsume);
+
+  if (!filterToConsume.isEmpty())
+  {
+    props.insert(ctkEventConstants::EVENT_FILTER, filterToConsume);
+  }
+
+  /* register the service */
+  serviceRegistration = context->registerService<ctkEventHandler>(this, props);
+
+  QVERIFY2(serviceRegistration, "service registration should not be null");
+}
+
+void ctkEAScenario4EventConsumer::cleanup()
+{
+  QMutexLocker l(&mutex);
+  try
+  {
+    serviceRegistration.unregister();
+  }
+  catch (const std::logic_error&) {}
+
+  if (error)
+  {
+    throw exc;
+  }
+
+  QCOMPARE(synchMessages, numSyncMessages); // "Not all synch messages recieved"
+  QCOMPARE(asynchMessages, numAsyncMessages); // "Not all asynch messages recieved"
+}
+
+void ctkEAScenario4EventConsumer::handleEvent(const ctkEvent& event)
+{
+  QMutexLocker l(&mutex);
+  try
+  {
+    /* try to get the message */
+    QString message = event.getProperty("Synchronous message").toString();
+
+    if (!message.isNull())
+    {
+      /* its an asyncronous message */
+      synchMessages++;
+      qDebug() << "recived a Synchronous event with message:" << message;
+    }
+    else
+    {
+      message = event.getProperty("Asynchronous message").toString();
+      if (!message.isNull())
+      {
+        asynchMessages++;
+        qDebug() << "recived an Asynchronus event with message:" << message;
+      }
+    }
+
+    /* assert that the messages property is not null */
+    QVERIFY2(!message.isNull(), "Message should not be null in handleEvent()");
+
+    /* assert that the messages of syncronous type are not too many */
+    QVERIFY2(synchMessages < numSyncMessages + 1, "too many synchronous messages");
+    /* assert that the messsage of the asyncronous type are not too many */
+    QVERIFY2(asynchMessages < numAsyncMessages + 1, "too many asynchronous messages");
+  }
+  catch (const ctkRuntimeException& e)
+  {
+    error = true;
+    exc = e;
+    throw e;
+  }
+  catch (...)
+  {
+    error = true;
+  }
+}
+
+void ctkEAScenario4EventPublisher::sendEvents()
+{
+  /* a Hash table to store message in */
+  ctkDictionary message(propertiesToSend);
+
+  for (int i = 0; i < messageTosend; i++)
+  {
+    /* put some properties into the messages */
+    message.insert("Synchronous message", i);
+    /* send the message */
+    qDebug() << "sending a synchronous event with message:"
+             << message << "and the topic:" << topicToSend;
+    eventAdmin->sendEvent(ctkEvent(topicToSend, message));
+  }
+  thread.quit();
+}
+
+void ctkEAScenario4EventPublisher::postEvents()
+{
+  /* create the hash table */
+  ctkDictionary message(propertiesToSend);
+
+  for (int i = 0; i < messageTosend; i++)
+  {
+    /* create the message */
+    message.insert("Asynchronous message", i);
+    /* Sends a asynchronous event to the admin */
+    qDebug() << "sending an Asynchronous event with message:"
+             << message << "and the topic:" << topicToSend;
+    eventAdmin->postEvent(ctkEvent(topicToSend, message));
+  }
+  thread.quit();
+}
+
+ctkEAScenario4EventPublisher::ctkEAScenario4EventPublisher(ctkPluginContext* context, const QString& name,
+                                                           const QString& topic, const ctkDictionary& props,
+                                                           int id, int numOfMessage)
+  : eventAdmin(0), context(context), messageTosend(numOfMessage), topicToSend(topic), propertiesToSend(props)
+{
+  thread.setObjectName(QString("%1-%2").arg(name).arg(id));
+  moveToThread(&thread);
+}
+
+void ctkEAScenario4EventPublisher::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");
+
+  eventAdmin = context->getService<ctkEventAdmin>(serviceReference);
+
+  QVERIFY2(eventAdmin, "Should be able to get instance to ctkEventAdmin object");
+
+  connect(&thread, SIGNAL(started()), SLOT(sendEvents()));
+  thread.start();
+  /* wait until thread is dead */
+  thread.wait();
+
+  disconnect(&thread, SIGNAL(started()), this, SLOT(sendEvents()));
+  connect(&thread, SIGNAL(started()), SLOT(postEvents()));
+  thread.start();
+  /* wait until thread is dead */
+  thread.wait();
+
+  QTest::qWait(1000); // allow for delivery
+}
+
+ctkEAScenario4TestSuite::ctkEAScenario4TestSuite(ctkPluginContext* context, long eventPluginId)
+  : pluginContext(context), eventPluginId(eventPluginId)
+{
+
+}
+
+void ctkEAScenario4TestSuite::initTestCase()
+{
+  pluginContext->getPlugin(eventPluginId)->start();
+
+  /* keys and properties to be used in the EventProducers*/
+  ctkDictionary keysAndProps1;
+  keysAndProps1.insert("year", "2004");
+  keysAndProps1.insert("month", "12");
+  ctkDictionary keysAndProps2;
+  keysAndProps2.insert("year", "2005");
+  keysAndProps2.insert("month", "12");
+  ctkDictionary keysAndProps3;
+  keysAndProps3.insert("YEAR", "2005");
+  keysAndProps3.insert("month", "11"); // Won't year filters match because year is not present?
+
+  /*Topics to be used in the EventConsumers*/
+  QStringList scenario4_topics1("com/acme/timer");
+  /*Filters to be used in the EventConsumers*/
+  QString scenario4_filter1 = "(year=2004)";
+  QString scenario4_filter2 = "(year=2005)";
+  QString scenario4_filter3 = "(year:2004)";
+  QString scenario4_filter4;
+  QString scenario4_filter5 = "(month=12)";
+
+  /* add the event consumer with the correct topics to the test suite */
+  eventConsumers.push_back(new ctkEAScenario4EventConsumer(pluginContext, scenario4_topics1,
+                                                           1, 1, scenario4_filter1));
+  eventConsumers.push_back(new ctkEAScenario4EventConsumer(pluginContext, scenario4_topics1,
+                                                           2, 2, scenario4_filter2));
+  eventConsumers.push_back(new ctkEAScenario4EventConsumer(pluginContext, scenario4_topics1,
+                                                           0, 0, scenario4_filter3));
+  eventConsumers.push_back(new ctkEAScenario4EventConsumer(pluginContext, scenario4_topics1,
+                                                           3, 3, scenario4_filter4));
+  eventConsumers.push_back(new ctkEAScenario4EventConsumer(pluginContext, scenario4_topics1,
+                                                           2, 2, scenario4_filter5));
+
+  /* add the event publisher to the test suite */
+  eventPublishers.push_back(new ctkEAScenario4EventPublisher(pluginContext, "Scenario 4 EventPublisher1",
+                                                             "com/acme/timer", keysAndProps1, 4, 1));
+  eventPublishers.push_back(new ctkEAScenario4EventPublisher(pluginContext, "Scenario 4 EventPublisher2",
+                                                             "com/acme/timer", keysAndProps2, 4, 1));
+  eventPublishers.push_back(new ctkEAScenario4EventPublisher(pluginContext, "Scenario 4 EventPublisher3",
+                                                             "com/acme/timer", keysAndProps3, 4, 1));
+}
+
+void ctkEAScenario4TestSuite::cleanupTestCase()
+{
+  foreach(ctkEAScenario4EventConsumer* eventConsumer, eventConsumers)
+  {
+    eventConsumer->cleanup();
+  }
+  qDeleteAll(eventPublishers);
+  qDeleteAll(eventConsumers);
+  pluginContext->getPlugin(eventPluginId)->stop();
+}
+
+void ctkEAScenario4TestSuite::testRegisterConsumer()
+{
+  foreach(ctkEAScenario4EventConsumer* consumer, eventConsumers)
+  {
+    consumer->runTest();
+  }
+}
+
+void ctkEAScenario4TestSuite::testPublishEvents()
+{
+  foreach(ctkEAScenario4EventPublisher* publisher, eventPublishers)
+  {
+    publisher->runTest();
+  }
+}

+ 189 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEAScenario4TestSuite_p.h

@@ -0,0 +1,189 @@
+/*=============================================================================
+
+  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.
+
+=============================================================================*/
+
+
+#ifndef CTKEASCENARIO4TESTSUITE_P_H
+#define CTKEASCENARIO4TESTSUITE_P_H
+
+#include <QObject>
+#include <QThread>
+#include <QMutex>
+
+#include <service/event/ctkEventHandler.h>
+#include <ctkTestSuiteInterface.h>
+#include <ctkServiceRegistration.h>
+#include <ctkRuntimeException.h>
+
+struct ctkEventAdmin;
+
+class ctkEAScenario4EventConsumer : public QObject, public ctkEventHandler
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkEventHandler)
+
+private:
+
+  ctkPluginContext* context;
+
+  /** class variable for service registration */
+  ctkServiceRegistration serviceRegistration;
+
+  /** class variable indicating the topics correct version */
+  QStringList topicsToConsume;
+
+  /** class variable indicating the topics */
+  QString filterToConsume;
+
+  /** class variable keeping number of asynchronous message */
+  int asynchMessages;
+
+  /** class variable keeping number of synchronous message */
+  int synchMessages;
+
+  /**
+   * class variable indication the number of synchronous messages to be
+   * received
+   */
+  int numSyncMessages;
+
+  /**
+   * class variable indication the number of asynchronous messages to be
+   * received
+   */
+  int numAsyncMessages;
+
+  bool error;
+  ctkRuntimeException exc;
+
+  QMutex mutex;
+
+public:
+
+  /**
+   * Constructor creates a consumer service
+   *
+   * @param bundleContext
+   * @param topics
+   * @param numSyncMsg
+   *            number of synchronous messages to be received
+   * @param numAsyncMsg
+   *            number of asynchronous messages to be received
+   * @param name
+   *            name of the Consumer
+   * @param id
+   */
+  ctkEAScenario4EventConsumer(ctkPluginContext* pluginContext, const QStringList topics,
+                       int numSyncMsg, int numAsyncMsg, const QString& filter);
+
+  void runTest();
+
+  void cleanup();
+
+  /**
+   * This method takes events from the event admin service.
+   */
+  void handleEvent(const ctkEvent& event);
+};
+
+class ctkEAScenario4EventPublisher : public QObject
+{
+  Q_OBJECT
+
+private:
+
+  /** A reference to a service */
+  ctkServiceReference serviceReference;
+
+  /** The admin which delivers the events */
+  ctkEventAdmin* eventAdmin;
+
+  /** class variable holding plugin context */
+  ctkPluginContext* context;
+
+  /** variable holding messages to send */
+  int messageTosend;
+
+  /** variable holding the topic to use */
+  QString topicToSend;
+
+  /** variable holding the parameters to use */
+  ctkDictionary propertiesToSend;
+
+  QThread thread;
+
+protected slots:
+
+  void sendEvents();
+  void postEvents();
+
+public:
+
+  ctkEAScenario4EventPublisher(ctkPluginContext* context, const QString& name,
+                               const QString& topic, const ctkDictionary& props,
+                               int id, int numOfMessage);
+
+  void runTest();
+};
+
+/**
+ * Test suite for testing the requirements specified in the test specification
+ * for the EventAdmin service.
+ *
+ * Check the filter both faulty and correctly, also check if the events are
+ * received in the order that they were sent both synchronously and
+ * asynchronously.
+ */
+class ctkEAScenario4TestSuite : public QObject, public ctkTestSuiteInterface
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkTestSuiteInterface)
+
+private:
+
+  /** plugin context variable */
+  ctkPluginContext* pluginContext;
+
+  long eventPluginId;
+
+  QList<ctkEAScenario4EventConsumer*> eventConsumers;
+  QList<ctkEAScenario4EventPublisher*> eventPublishers;
+
+public:
+
+  /**
+   * Constructor for the TestSuite class.
+   *
+   * @param context
+   *            the handle to the frame work
+   */
+  ctkEAScenario4TestSuite(ctkPluginContext* context, long eventPluginId);
+
+private slots:
+
+  void initTestCase();
+  void cleanupTestCase();
+
+  void testRegisterConsumer();
+  void testPublishEvents();
+
+};
+
+#endif // CTKEASCENARIO4TESTSUITE_P_H

+ 184 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEATopicWildcardTestSuite.cpp

@@ -0,0 +1,184 @@
+/*=============================================================================
+
+  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 "ctkEATopicWildcardTestSuite_p.h"
+
+#include <ctkPluginContext.h>
+#include <ctkPluginConstants.h>
+
+#include <service/event/ctkEventAdmin.h>
+#include <service/event/ctkEventConstants.h>
+
+#include <QTest>
+#include <QDebug>
+
+ctkEvent ctkEATopicWildcardTestHelper::clearLastEvent()
+{
+  QWriteLocker l(&rwlock);
+  ctkEvent result = last;
+  last = ctkEvent();
+  return result;
+}
+
+void ctkEATopicWildcardTestHelper::handleEvent(const ctkEvent& event)
+{
+  QWriteLocker l(&rwlock);
+  last = event;
+}
+
+ctkEvent ctkEATopicWildcardTestHelper::lastEvent() const
+{
+  QReadLocker l(&rwlock);
+  return last;
+}
+
+ctkEATopicWildcardTestSuite::ctkEATopicWildcardTestSuite(
+  ctkPluginContext* pc, long eventPluginId, bool useSignalSlot)
+  : context(pc), eventPluginId(eventPluginId),
+    useSignalSlot(useSignalSlot), eventAdmin(0)
+{
+
+}
+
+void ctkEATopicWildcardTestSuite::initTestCase()
+{
+  qDebug() << "Using" << (useSignalSlot ? "" : "no") << "Qt signal/slot mechanism";
+}
+
+void ctkEATopicWildcardTestSuite::init()
+{
+  context->getPlugin(eventPluginId)->start();
+  reference = context->getServiceReference<ctkEventAdmin>();
+  eventAdmin = context->getService<ctkEventAdmin>(reference);
+
+  if (useSignalSlot)
+  {
+    eventAdmin->publishSignal(this, SIGNAL(syncSignal(ctkEvent)), Qt::DirectConnection);
+  }
+}
+
+void ctkEATopicWildcardTestSuite::cleanup()
+{
+  context->ungetService(reference);
+  context->getPlugin(eventPluginId)->stop();
+}
+
+void ctkEATopicWildcardTestSuite::testEventDeliveryForWildcardTopic1()
+{
+  ctkDictionary properties;
+  properties.insert(ctkEventConstants::EVENT_TOPIC, "a/b/c/*");
+  ctkEATopicWildcardTestHelper handler;
+  ctkEvent event("a/b/c");
+
+  if (useSignalSlot)
+  {
+    qlonglong id = eventAdmin->subscribeSlot(&handler, SLOT(handleEvent(ctkEvent)), properties);
+    emit syncSignal(event);
+    eventAdmin->unsubscribeSlot(id);
+  }
+  else
+  {
+    ctkServiceRegistration handlerRegistration = context->registerService<ctkEventHandler>(&handler, properties);
+    eventAdmin->sendEvent(event);
+    handlerRegistration.unregister();
+  }
+
+  QVERIFY2(handler.lastEvent().isNull(), "Received event published to topic 'a/b/c' while listening to 'a/b/c/*'");
+}
+
+void ctkEATopicWildcardTestSuite::testEventDeliveryForWildcardTopic2()
+{
+  ctkDictionary properties;
+  properties.insert(ctkEventConstants::EVENT_TOPIC, "a/b/c/*");
+  ctkEATopicWildcardTestHelper handler;
+  ctkServiceRegistration handlerRegistration = context->registerService<ctkEventHandler>(&handler, properties);
+  ctkEvent event("a/b");
+  eventAdmin->sendEvent(event);
+  QVERIFY2(handler.lastEvent().isNull(), "Received event published to topic 'a/b' while listening to 'a/b/c/*'");
+  handlerRegistration.unregister();
+}
+
+void ctkEATopicWildcardTestSuite::testEventDeliveryForWildcardTopic3()
+{
+  ctkDictionary properties;
+  properties.insert(ctkEventConstants::EVENT_TOPIC, "a/b/c/*");
+  ctkEATopicWildcardTestHelper handler;
+  ctkServiceRegistration handlerRegistration = context->registerService<ctkEventHandler>(&handler, properties);
+  ctkEvent event("a");
+  eventAdmin->sendEvent(event);
+  QVERIFY2(handler.lastEvent().isNull(), "Received event published to topic 'a' while listening to 'a/b/c/*'");
+  handlerRegistration.unregister();
+}
+
+void ctkEATopicWildcardTestSuite::testEventDeliveryForWildcardTopic4()
+{
+  ctkDictionary properties;
+  properties.insert(ctkEventConstants::EVENT_TOPIC, "a/b/c/*");
+  ctkEATopicWildcardTestHelper handler;
+  ctkServiceRegistration handlerRegistration = context->registerService<ctkEventHandler>(&handler, properties);
+  ctkEvent event("a/b/c/d");
+  eventAdmin->sendEvent(event);
+  QVERIFY2(!handler.lastEvent().isNull(), "Did not receive event published to topic 'a/b/c/d' while listening to 'a/b/c/*'");
+  handlerRegistration.unregister();
+}
+
+void ctkEATopicWildcardTestSuite::testEventDeliveryForWildcardTopic5()
+{
+  ctkDictionary properties;
+  properties.insert(ctkEventConstants::EVENT_TOPIC, "a/b/c/*");
+  ctkEATopicWildcardTestHelper handler;
+  ctkServiceRegistration handlerRegistration = context->registerService<ctkEventHandler>(&handler, properties);
+  ctkEvent event("a/b/c/d/e");
+  eventAdmin->sendEvent(event);
+  QVERIFY2(!handler.lastEvent().isNull(), "Did not receive event published to topic 'a/b/c/d/e' while listening to 'a/b/c/*'");
+  handlerRegistration.unregister();
+}
+
+void ctkEATopicWildcardTestSuite::testEventDeliveryForWildcardTopic6()
+{
+  ctkDictionary properties;
+  properties.insert(ctkEventConstants::EVENT_TOPIC, "a/b/c/*");
+  ctkEATopicWildcardTestHelper handler;
+  ctkServiceRegistration handlerRegistration = context->registerService<ctkEventHandler>(&handler, properties);
+  ctkEvent event("a/b/c/d/e/f");
+  eventAdmin->sendEvent(event);
+  QVERIFY2(!handler.lastEvent().isNull(), "Did not receive event published to topic 'a/b/c/d/e/f' while listening to 'a/b/c/*'");
+  handlerRegistration.unregister();
+}
+
+void ctkEATopicWildcardTestSuite::testEventDeliveryForWildcardTopic7()
+{
+  ctkDictionary properties;
+  QStringList topics("a/b/c");
+  topics << "a/b/c/*";
+  properties.insert(ctkEventConstants::EVENT_TOPIC, topics);
+  ctkEATopicWildcardTestHelper handler;
+  ctkServiceRegistration handlerRegistration = context->registerService<ctkEventHandler>(&handler, properties);
+  ctkEvent event("a/b/c");
+  eventAdmin->sendEvent(event);
+  QVERIFY2(!handler.clearLastEvent().isNull(), "Did not receive event published to topic 'a/b/c' while listening to 'a/b/c'");
+  event = ctkEvent("a/b/c/d");
+  eventAdmin->sendEvent(event);
+  QVERIFY2(!handler.lastEvent().isNull(), "Did not receive event published to topic 'a/b/c/d' while listening to 'a/b/c/*'");
+  handlerRegistration.unregister();
+}
+

+ 133 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEATopicWildcardTestSuite_p.h

@@ -0,0 +1,133 @@
+/*=============================================================================
+
+  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.
+
+=============================================================================*/
+
+
+#ifndef CTKEATOPICWILDCARDTESTSUITE_P_H
+#define CTKEATOPICWILDCARDTESTSUITE_P_H
+
+#include <QObject>
+#include <QReadWriteLock>
+
+#include <ctkServiceReference.h>
+#include <ctkTestSuiteInterface.h>
+
+#include <service/event/ctkEventHandler.h>
+
+class ctkPluginContext;
+struct ctkEventAdmin;
+
+class ctkEATopicWildcardTestHelper : public QObject, public ctkEventHandler
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkEventHandler)
+
+private:
+
+  mutable QReadWriteLock rwlock;
+  ctkEvent last;
+
+public slots:
+
+  void handleEvent(const ctkEvent& event);
+
+public:
+
+  ctkEvent clearLastEvent();
+
+  ctkEvent lastEvent() const;
+
+};
+
+
+class ctkEATopicWildcardTestSuite : public QObject,
+    public ctkTestSuiteInterface
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkTestSuiteInterface)
+
+public:
+
+  ctkEATopicWildcardTestSuite(ctkPluginContext* pc, long eventPluginId, bool useSignalSlot);
+
+signals:
+
+  void syncSignal(const ctkEvent& event);
+
+private slots:
+
+  void initTestCase();
+
+  void init();
+  void cleanup();
+
+  /*
+   * Ensures ctkEventAdmin does not deliver an event published on topic "a/b/c"
+   * to a ctkEventHandler listening to topic a/b/c/&#42;.
+   */
+  void testEventDeliveryForWildcardTopic1();
+
+  /*
+   * Ensures ctkEventAdmin does not deliver an event published on topic "a/b" to
+   * an ctkEventHandler listening to topic a/b/c/&#42;.
+   */
+  void testEventDeliveryForWildcardTopic2();
+
+  /*
+   * Ensures ctkEventAdmin does not deliver an event published on topic "a" to
+   * an ctkEventHandler listening to topic a/b/c/&#42;.
+   */
+  void testEventDeliveryForWildcardTopic3();
+
+  /*
+   * Ensures ctkEventAdmin delivers an event published on topic "a/b/c/d" to an
+   * ctkEventHandler listening to topic "a/b/c/&#42;".
+   */
+  void testEventDeliveryForWildcardTopic4();
+
+  /*
+   * Ensures ctkEventAdmin delivers an event published on topic "a/b/c/d/e" to
+   * an ctkEventHandler listening to topic "a/b/c/&#42;".
+   */
+  void testEventDeliveryForWildcardTopic5();
+
+  /*
+   * Ensures ctkEventAdmin delivers an event published on topic "a/b/c/d/e/f" to
+   * an ctkEventHandler listening to topic "a/b/c/&#42;".
+   */
+  void testEventDeliveryForWildcardTopic6();
+
+  /*
+   * Ensures ctkEventAdmin delivers an event published to topics "a/b/c" and
+   * "a/b/c/d" to an ctkEventHandler listening to topics "a/b/c" and "a/b/c/&#42;".
+   */
+  void testEventDeliveryForWildcardTopic7();
+
+
+private:
+
+  ctkPluginContext* context;
+  long eventPluginId;
+  bool useSignalSlot;
+  ctkEventAdmin* eventAdmin;
+  ctkServiceReference reference;
+};
+
+#endif // CTKEATOPICWILDCARDTESTSUITE_P_H

+ 105 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEventAdminTestActivator.cpp

@@ -0,0 +1,105 @@
+/*=============================================================================
+
+  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 "ctkEventAdminTestActivator_p.h"
+
+#include <ctkPluginContext.h>
+#include <ctkPluginConstants.h>
+
+#include <QtPlugin>
+#include <QStringList>
+
+#include "ctkEATopicWildcardTestSuite_p.h"
+#include "ctkEAScenario1TestSuite_p.h"
+#include "ctkEAScenario2TestSuite_p.h"
+#include "ctkEAScenario3TestSuite_p.h"
+#include "ctkEAScenario4TestSuite_p.h"
+
+ctkEventAdminTestActivator::ctkEventAdminTestActivator()
+  : topicWildcardTestSuite(0), topicWildcardTestSuiteSS(0),
+    scenario1TestSuite(0), scenario1TestSuiteSS(0), scenario2TestSuite(0)
+{
+
+}
+
+ctkEventAdminTestActivator::~ctkEventAdminTestActivator()
+{
+  delete topicWildcardTestSuite;
+  delete topicWildcardTestSuiteSS;
+  delete scenario1TestSuite;
+  delete scenario1TestSuiteSS;
+  delete scenario2TestSuite;
+}
+
+void ctkEventAdminTestActivator::start(ctkPluginContext* context)
+{
+  QString symbolicName = context->getProperty("event.impl").toString();
+  if (symbolicName.isEmpty())
+  {
+    throw std::logic_error("Framework property 'event.impl' containing the symbolic "
+                           "name of the EventAdmin implementation not found!");
+  }
+
+  long eventPluginId = -1;
+  foreach(QSharedPointer<ctkPlugin> p, context->getPlugins())
+  {
+    if (p->getSymbolicName() == symbolicName)
+    {
+      eventPluginId = p->getPluginId();
+      break;
+    }
+  }
+
+  if (eventPluginId < 0)
+  {
+    QString msg = QString("The EventAdmin implementation '%1' is not installed.")
+        .arg(symbolicName);
+    throw std::logic_error(msg.toStdString());
+  }
+
+  topicWildcardTestSuite = new ctkEATopicWildcardTestSuite(context, eventPluginId, false);
+  context->registerService<ctkTestSuiteInterface>(topicWildcardTestSuite);
+
+  topicWildcardTestSuiteSS = new ctkEATopicWildcardTestSuite(context, eventPluginId, true);
+  context->registerService<ctkTestSuiteInterface>(topicWildcardTestSuiteSS);
+
+  scenario1TestSuite = new ctkEAScenario1TestSuite(context, eventPluginId, false);
+  context->registerService<ctkTestSuiteInterface>(scenario1TestSuite);
+
+  scenario1TestSuiteSS = new ctkEAScenario1TestSuite(context, eventPluginId, true);
+  context->registerService<ctkTestSuiteInterface>(scenario1TestSuiteSS);
+
+  scenario2TestSuite = new ctkEAScenario2TestSuite(context, eventPluginId);
+  context->registerService<ctkTestSuiteInterface>(scenario2TestSuite);
+
+  scenario3TestSuite = new ctkEAScenario3TestSuite(context, eventPluginId);
+  context->registerService<ctkTestSuiteInterface>(scenario3TestSuite);
+
+  scenario4TestSuite = new ctkEAScenario4TestSuite(context, eventPluginId);
+  context->registerService<ctkTestSuiteInterface>(scenario4TestSuite);
+}
+
+void ctkEventAdminTestActivator::stop(ctkPluginContext* context)
+{
+  Q_UNUSED(context);
+}
+
+Q_EXPORT_PLUGIN2(org_commontk_eventadmintest, ctkEventAdminTestActivator)

+ 54 - 0
Libs/PluginFramework/Testing/EventAdminTest/ctkEventAdminTestActivator_p.h

@@ -0,0 +1,54 @@
+/*=============================================================================
+
+  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.
+
+=============================================================================*/
+
+
+#ifndef CTKEVENTADMINTESTACTIVATOR_H
+#define CTKEVENTADMINTESTACTIVATOR_H
+
+#include <ctkPluginActivator.h>
+
+
+class ctkEventAdminTestActivator : public QObject,
+                                   public ctkPluginActivator
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkPluginActivator)
+
+public:
+
+  ctkEventAdminTestActivator();
+  ~ctkEventAdminTestActivator();
+
+  void start(ctkPluginContext* context);
+  void stop(ctkPluginContext* context);
+
+private:
+
+  QObject* topicWildcardTestSuite;
+  QObject* topicWildcardTestSuiteSS;
+  QObject* scenario1TestSuite;
+  QObject* scenario1TestSuiteSS;
+  QObject* scenario2TestSuite;
+  QObject* scenario3TestSuite;
+  QObject* scenario4TestSuite;
+};
+
+#endif // CTKEVENTADMINTESTACTIVATOR_H

+ 10 - 0
Libs/PluginFramework/Testing/EventAdminTest/manifest_headers.cmake

@@ -0,0 +1,10 @@
+set(Plugin-ActivationPolicy "eager")
+set(Plugin-Name "EventAdmin TestSuite")
+set(Plugin-Version "0.9")
+set(Plugin-Description "Test bundle for the CTK Event Admin specs")
+set(Plugin-Vendor "CommonTK")
+set(Plugin-DocURL "http://www.commontk.org")
+set(Plugin-ContactAddress "http://www.commontk.org")
+set(Plugin-Category "test")
+set(Plugin-Copyright "German Cancer Research Center, Division of Medical and Biological Informatics")
+set(Plugin-License "http://www.apache.org/licenses/LICENSE-2.0.html")

+ 9 - 0
Libs/PluginFramework/Testing/EventAdminTest/target_libraries.cmake

@@ -0,0 +1,9 @@
+#
+# See CMake/ctkMacroGetTargetLibraries.cmake
+# 
+# This file should list the libraries required to build the current CTK plugin.
+# 
+
+SET(target_libraries
+  CTKPluginFramework
+  )