瀏覽代碼

Initial plugin framework test suite.

Sascha Zelzer 15 年之前
父節點
當前提交
d8154c356f
共有 22 個文件被更改,包括 1262 次插入23 次删除
  1. 10 3
      CMake/ctkMacroBuildPlugin.cmake
  2. 6 1
      Libs/PluginFramework/Testing/CMakeLists.txt
  3. 13 19
      Libs/PluginFramework/Testing/Cpp/CMakeLists.txt
  4. 132 0
      Libs/PluginFramework/Testing/Cpp/ctkPluginFrameworkTestMain.cpp
  5. 73 0
      Libs/PluginFramework/Testing/Cpp/ctkPluginFrameworkTestUtil.h
  6. 33 0
      Libs/PluginFramework/Testing/Cpp/ctkTestSuiteInterface.h
  7. 34 0
      Libs/PluginFramework/Testing/FrameworkTest/CMakeLists.txt
  8. 49 0
      Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestActivator.cpp
  9. 45 0
      Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestActivator_p.h
  10. 495 0
      Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestSuite.cpp
  11. 109 0
      Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestSuite_p.h
  12. 10 0
      Libs/PluginFramework/Testing/FrameworkTest/manifest_headers.cmake
  13. 9 0
      Libs/PluginFramework/Testing/FrameworkTest/target_libraries.cmake
  14. 7 0
      Libs/PluginFramework/Testing/TestPlugins/CMakeLists.txt
  15. 30 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/CMakeLists.txt
  16. 32 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginA.cpp
  17. 41 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAActivator.cpp
  18. 46 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAActivator_p.h
  19. 31 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAService.h
  20. 41 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginA_p.h
  21. 7 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/manifest_headers.cmake
  22. 9 0
      Libs/PluginFramework/Testing/TestPlugins/pluginA_test/target_libraries.cmake

+ 10 - 3
CMake/ctkMacroBuildPlugin.cmake

@@ -48,7 +48,7 @@
 MACRO(ctkMacroBuildPlugin)
   CtkMacroParseArguments(MY
     "EXPORT_DIRECTIVE;SRCS;MOC_SRCS;UI_FORMS;INCLUDE_DIRECTORIES;TARGET_LIBRARIES;RESOURCES;CACHED_RESOURCEFILES;LIBRARY_TYPE"
-    ""
+    "TEST_PLUGIN"
     ${ARGN}
     )
 
@@ -195,11 +195,18 @@ MACRO(ctkMacroBuildPlugin)
     ${MY_QRC_SRCS}
     )
 
+  SET(runtime_output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins")
+  SET(library_output_dir "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins")
+  IF(MY_TEST_PLUGIN)
+    SET(runtime_output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_plugins")
+    SET(library_output_dir "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/test_plugins")
+  ENDIF()
+
   # Apply properties to the library target.
   SET_TARGET_PROPERTIES(${lib_name} PROPERTIES
     COMPILE_FLAGS "-DQT_PLUGIN"
-    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins"
-    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins"
+    RUNTIME_OUTPUT_DIRECTORY ${runtime_output_dir}
+    LIBRARY_OUTPUT_DIRECTORY ${library_output_dir}
     PREFIX "lib"
     )
 

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

@@ -1 +1,6 @@
-#ADD_SUBDIRECTORY(Cpp)
+ADD_SUBDIRECTORY(Cpp)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/Cpp)
+
+ADD_SUBDIRECTORY(FrameworkTest)
+ADD_SUBDIRECTORY(TestPlugins)

+ 13 - 19
Libs/PluginFramework/Testing/Cpp/CMakeLists.txt

@@ -1,27 +1,21 @@
 SET(KIT ${PROJECT_NAME})
 
-CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cpp
-  ctkLDAPExpreTest.cpp
-  )
+SET(SRCS
+  ctkPluginFrameworkTestMain.cpp
+  ctkPluginFrameworkTestUtil.h
+  ctkTestSuiteInterface.h
+)
 
-SET (TestsToRun ${Tests})
-REMOVE (TestsToRun ${KIT}CppTests.cpp)
+SET(MOC_SRCS )
 
-SET(LIBRARY_NAME ${PROJECT_NAME})
-
-ADD_EXECUTABLE(${KIT}CppTests ${Tests})
-TARGET_LINK_LIBRARIES(${KIT}CppTests ${LIBRARY_NAME} ${CTK_BASE_LIBRARIES})
+SET(MY_MOC_CXX )
 
-SET( KIT_TESTS ${CPP_TEST_PATH}/${KIT}CppTests)
+#QT4_WRAP_CPP(MY_MOC_CXX ${MOC_SRCS})
 
-MACRO( SIMPLE_TEST  TESTNAME )
-  ADD_TEST( ${TESTNAME} ${KIT_TESTS} ${TESTNAME} )
-  SET_PROPERTY(TEST ${TESTNAME} PROPERTY LABELS ${PROJECT_NAME})
-ENDMACRO( SIMPLE_TEST  )
-
-#
-# Add Tests
-#
+SET(LIBRARY_NAME ${PROJECT_NAME})
 
-SIMPLE_TEST( ctkLDAPExpreTest )
+ADD_EXECUTABLE(${KIT}CppTests ${SRCS} ${MY_MOC_CXX})
+TARGET_LINK_LIBRARIES(${KIT}CppTests ${LIBRARY_NAME})
 
+ADD_TEST(${PROJECT_NAME} ${KIT}CppTests)
+SET_PROPERTY(TEST ${PROJECT_NAME} PROPERTY LABELS ${PROJECT_NAME})

+ 132 - 0
Libs/PluginFramework/Testing/Cpp/ctkPluginFrameworkTestMain.cpp

@@ -0,0 +1,132 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 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 <QCoreApplication>
+#include <QDirIterator>
+#include <QTest>
+#include <QThread>
+
+#include <ctkPluginConstants.h>
+#include <ctkPluginFrameworkFactory.h>
+#include <ctkPluginFramework.h>
+#include <ctkPluginException.h>
+#include <ctkServiceReference.h>
+
+class TestRunner : public QThread
+{
+public:
+
+  TestRunner(ctkPluginContext* context, int argc, char** argv)
+    : context(context), argc(argc), argv(argv)
+  {
+
+  }
+
+  void run()
+  {
+    QList<ctkServiceReference> refs = context->getServiceReferences("ctkTestSuiteInterface");
+
+    int result = 0;
+    foreach(ctkServiceReference ref, refs)
+    {
+      result = QTest::qExec(context->getService(ref), argc, argv);
+    }
+
+    QCoreApplication::exit(result);
+  }
+
+private:
+
+  ctkPluginContext* context;
+  int argc;
+  char** argv;
+};
+
+int main(int argc, char** argv)
+{
+  QCoreApplication app(argc, argv);
+
+  app.setOrganizationName("CTK");
+  app.setOrganizationDomain("commontk.org");
+  app.setApplicationName("ctkPluginFrameworkCppTests");
+
+  QString pluginDir;
+#ifdef CMAKE_INTDIR
+  pluginDir = qApp->applicationDirPath() + "/../test_plugins/" CMAKE_INTDIR "/";
+#else
+  pluginDir = qApp->applicationDirPath() + "/test_plugins/";
+#endif
+
+  QApplication::addLibraryPath(pluginDir);
+
+  ctkProperties fwProps;
+  fwProps.insert(ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN, ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
+  fwProps.insert("pluginfw.testDir", pluginDir);
+  ctkPluginFrameworkFactory fwFactory(fwProps);
+  ctkPluginFramework* framework = fwFactory.getFramework();
+  framework->start();
+
+  ctkPluginContext* context = framework->getPluginContext();
+
+  ctkPlugin* fwTest = 0;
+  QStringList libFilter;
+  libFilter << "*.dll" << "*.so" << "*.dylib";
+  QDirIterator dirIter(pluginDir, libFilter, QDir::Files);
+  while(dirIter.hasNext())
+  {
+    dirIter.next();
+    if (dirIter.fileName().contains("org_commontk_pluginfwtest"))
+    {
+      try
+      {
+        fwTest = context->installPlugin(QUrl::fromLocalFile(dirIter.filePath()).toString());
+        break;
+      }
+      catch (const ctkPluginException& e)
+      {
+        qCritical() << e.what();
+      }
+    }
+  }
+
+  if (!fwTest)
+  {
+    qCritical() << "Could not find the plugin framework test plugin: org.commontk.pluginfwtest";
+  }
+
+  // start the main test plugin which registers the test suites (QObject classes)
+  fwTest->start();
+
+//  QList<ctkServiceReference> refs = context->getServiceReferences("ctkTestSuiteInterface");
+
+//  int result = 0;
+//  foreach(ctkServiceReference ref, refs)
+//  {
+//    result = QTest::qExec(context->getService(ref), argc, argv);
+//  }
+
+//  return result;
+
+  TestRunner runner(context, argc,argv);
+  runner.start();
+
+  return app.exec();
+}

+ 73 - 0
Libs/PluginFramework/Testing/Cpp/ctkPluginFrameworkTestUtil.h

@@ -0,0 +1,73 @@
+/*=============================================================================
+
+  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 CTKPLUGINFRAMEWORKTESTUTIL_H
+#define CTKPLUGINFRAMEWORKTESTUTIL_H
+
+#include <QString>
+#include <QFileInfo>
+#include <QLibrary>
+#include <QDirIterator>
+
+#include <ctkPluginContext.h>
+#include <ctkPluginException.h>
+
+class ctkPluginFrameworkTestUtil
+{
+public:
+
+  static ctkPlugin* installPlugin(ctkPluginContext* pc, const QString& plugin)
+  { 
+    qDebug() << "installPlugin(" << plugin << ")";
+    QFileInfo pluginInfo(plugin);
+    if (pluginInfo.exists() && pluginInfo.isFile() &&
+        QLibrary::isLibrary(pluginInfo.absoluteFilePath()))
+    {
+      return pc->installPlugin(QUrl::fromLocalFile(pluginInfo.absoluteFilePath()).toString());
+    }
+    else
+    {
+      QString testPluginDir = pc->getProperty("pluginfw.testDir").toString();
+      QFileInfo testDirInfo(testPluginDir);
+      if (!testDirInfo.exists() || !testDirInfo.isDir())
+      {
+        throw ctkPluginException(QString("No plugin %1 in %2").arg(plugin).arg(testPluginDir));
+      }
+
+      QStringList libFilter;
+      libFilter << "*.dll" << "*.so" << "*.dylib";
+      QDirIterator dirIter(testDirInfo.absoluteFilePath(), libFilter, QDir::Files);
+      while (dirIter.hasNext())
+      {
+        QString lib = dirIter.next();
+        if (dirIter.fileName().contains(plugin))
+        {
+          return pc->installPlugin(QUrl::fromLocalFile(lib));
+        }
+      }
+
+      throw ctkPluginException(QString("No plugin %1 in %2").arg(plugin).arg(testPluginDir));
+    }
+  }
+};
+
+#endif // CTKPLUGINFRAMEWORKTESTUTIL_H

+ 33 - 0
Libs/PluginFramework/Testing/Cpp/ctkTestSuiteInterface.h

@@ -0,0 +1,33 @@
+/*=============================================================================
+
+  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 CTKTESTSUITEINTERFACE_H
+#define CTKTESTSUITEINTERFACE_H
+
+#include <qglobal.h>
+
+struct ctkTestSuiteInterface
+{
+  virtual ~ctkTestSuiteInterface() {}
+};
+
+#endif // CTKTESTSUITEINTERFACE_H

+ 34 - 0
Libs/PluginFramework/Testing/FrameworkTest/CMakeLists.txt

@@ -0,0 +1,34 @@
+PROJECT(org_commontk_pluginfwtest)
+
+SET(PLUGIN_export_directive "org_commontk_pluginfwtest_EXPORT")
+
+SET(PLUGIN_SRCS
+  ctkPluginFrameworkTestActivator.cpp
+  ctkPluginFrameworkTestSuite.cpp
+)
+
+SET(PLUGIN_MOC_SRCS
+  ctkPluginFrameworkTestActivator_p.h
+  ctkPluginFrameworkTestSuite_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
+)

+ 49 - 0
Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestActivator.cpp

@@ -0,0 +1,49 @@
+/*=============================================================================
+
+  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 "ctkPluginFrameworkTestActivator_p.h"
+
+#include "ctkPluginFrameworkTestSuite_p.h"
+
+#include <ctkPluginContext.h>
+#include <ctkPluginConstants.h>
+
+#include <QtPlugin>
+#include <QStringList>
+
+void ctkPluginFrameworkTestActivator::start(ctkPluginContext* context)
+{
+  ServiceProperties props;
+
+  frameworkTestSuite = new ctkPluginFrameworkTestSuite(context);
+  props.clear();
+  props.insert(ctkPluginConstants::SERVICE_PID, frameworkTestSuite->metaObject()->className());
+  context->registerService(QStringList("ctkTestSuiteInterface"), frameworkTestSuite, props);
+}
+
+void ctkPluginFrameworkTestActivator::stop(ctkPluginContext* context)
+{
+  Q_UNUSED(context);
+
+  delete frameworkTestSuite;
+}
+
+Q_EXPORT_PLUGIN2(org_commontk_pluginfwtest, ctkPluginFrameworkTestActivator)

+ 45 - 0
Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestActivator_p.h

@@ -0,0 +1,45 @@
+/*=============================================================================
+
+  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 CTKPLUGINFRAMEWORKTESTACTIVATOR_H
+#define CTKPLUGINFRAMEWORKTESTACTIVATOR_H
+
+#include <ctkPluginActivator.h>
+
+
+class ctkPluginFrameworkTestActivator : public QObject,
+                                        public ctkPluginActivator
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkPluginActivator)
+
+public:
+
+  void start(ctkPluginContext* context);
+  void stop(ctkPluginContext* context);
+
+private:
+
+  QObject* frameworkTestSuite;
+};
+
+#endif // CTKPLUGINFRAMEWORKTESTACTIVATOR_H

+ 495 - 0
Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestSuite.cpp

@@ -0,0 +1,495 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 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 "ctkPluginFrameworkTestSuite_p.h"
+
+#include <ctkPluginFrameworkTestUtil.h>
+#include <ctkPluginContext.h>
+#include <ctkPluginConstants.h>
+#include <ctkServiceException.h>
+
+#include <QTest>
+#include <QDebug>
+
+
+int ctkPluginFrameworkTestSuite::nRunCount = 0;
+
+
+ctkPluginFrameworkTestSuite::ctkPluginFrameworkTestSuite(ctkPluginContext* pc)
+  : eventDelay(500), pc(pc), p(pc->getPlugin())
+{
+
+}
+
+void ctkPluginFrameworkTestSuite::initTestCase()
+{
+  qDebug() << "### plugin framework test suite: SETUP start";
+  if (nRunCount > 0)
+  {
+    QFAIL("The ctkPluginFrameworkTestSuite CANNOT be run reliably more than once. Other test results in this suite are/may not be valid. Restart framework to retest: CLEANUP:FAIL");
+  }
+  ++nRunCount;
+
+  try
+  {
+    bool success = pc->connectFrameworkListener(this, SLOT(frameworkListener(ctkPluginFrameworkEvent)));
+    if (!success)
+    {
+      QFAIL("plugin framework test suite: SETUP:FAIL");
+    }
+  }
+  catch (const std::logic_error& e)
+  {
+    QString msg  = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
+    QFAIL(msg.toAscii());
+  }
+
+  try
+  {
+    bool success = pc->connectPluginListener(this, SLOT(pluginListener(ctkPluginEvent)));
+    if (!success)
+    {
+      QFAIL("plugin framework test suite: SETUP:FAIL");
+    }
+  }
+  catch (const std::logic_error& e)
+  {
+    QString msg  = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
+    QFAIL(msg.toAscii());
+  }
+
+  try
+  {
+    bool success = pc->connectPluginListener(this, SLOT(syncPluginListener(ctkPluginEvent)), Qt::DirectConnection);
+    if (!success)
+    {
+      QFAIL("plugin framework test suite: SETUP:FAIL");
+    }
+  }
+  catch (const std::logic_error& e)
+  {
+    QString msg  = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
+    QFAIL(msg.toAscii());
+  }
+
+  try
+  {
+    pc->connectServiceListener(this, "serviceListener");
+  }
+  catch (const std::logic_error& e)
+  {
+    QString msg  = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
+    QFAIL(msg.toAscii());
+  }
+
+  qDebug() << "### plugin framework test suite: SETUP:PASS";
+}
+
+void ctkPluginFrameworkTestSuite::cleanupTestCase()
+{
+
+}
+
+// Verify information from the getHeaders() method
+void ctkPluginFrameworkTestSuite::frame005a()
+{
+  QHash<QString, QString> headers = p->getHeaders();
+
+  // check expected headers
+
+  QString k = "Plugin-Name";
+  QCOMPARE(QString("framework_test"), headers.value(k));
+
+  k = "Plugin-Version";
+  QCOMPARE(QString("1.0.1"), headers.value(k));
+
+  k = "Plugin-Description";
+  QCOMPARE(QString("Test bundle for the CTK plugin framework"), headers.value(k));
+
+  k = "Plugin-Vendor";
+  QCOMPARE(QString("CommonTK"), headers.value(k));
+
+  k = "Plugin-DocURL";
+  QCOMPARE(QString("http://www.commontk.org"), headers.value(k));
+
+  k = "Plugin-ContactAddress";
+  QCOMPARE(QString("http://www.commontk.org"), headers.value(k));
+
+  k = "Plugin-Category";
+  QCOMPARE(QString("test"), headers.value(k));
+
+  k = "Plugin-Copyright";
+  QCOMPARE(QString("German Cancer Research Center, Division of Medical and Biological Informatics"), headers.value(k));
+
+  k = "Plugin-License";
+  QCOMPARE(QString("http://www.apache.org/licenses/LICENSE-2.0.html"), headers.value(k));
+}
+
+// Load pluginA_test and check that it exists and that its expected service does not exist,
+// also check that the expected events in the framework occur
+void ctkPluginFrameworkTestSuite::frame020a()
+{
+  pA = 0;
+
+  try
+  {
+    pA = ctkPluginFrameworkTestUtil::installPlugin(pc, "pluginA_test");
+  }
+  catch (ctkPluginException& e)
+  {
+    QFAIL(e.what());
+  }
+
+  const QHash<QString, QString> headers = pA->getHeaders();
+  QHash<QString, QString>::const_iterator iter =
+      headers.find(ctkPluginConstants::PLUGIN_SYMBOLICNAME);
+  QVERIFY(iter != headers.end());
+  QCOMPARE(iter.value(), QString("pluginA.test"));
+
+  // Check that no service reference exist yet.
+  try
+  {
+    pc->getServiceReference("ctkTestPluginAService");
+    QFAIL("framework test plugin, service from test plugin A unexpectedly found");
+  }
+  catch (ctkServiceException& e)
+  {
+
+  }
+
+  // check the listeners for events, expect only a plugin event,
+  // of type installation
+  bool lStat = checkListenerEvents(false, ctkPluginFrameworkEvent::INFO, true , ctkPluginEvent::INSTALLED,
+                                   false, ctkServiceEvent::MODIFIED, pA, 0);
+
+  QVERIFY(pA->getState() == ctkPlugin::INSTALLED && lStat == true);
+}
+
+// Start pluginA_test and check that it gets state ACTIVE,
+// and that the service it registers exist
+void ctkPluginFrameworkTestSuite::frame025b()
+{
+  try
+  {
+    pA->start();
+    QVERIFY2(pA->getState() == ctkPlugin::ACTIVE, "pluginA_test should be ACTIVE");
+  }
+  catch (const ctkPluginException& pexcA)
+  {
+    QString failMsg = QString("Unexpected plugin exception: ") + pexcA.what();
+    QFAIL(failMsg.toStdString().c_str());
+  }
+  catch (const std::logic_error& le)
+  {
+    QString failMsg = QString("Start plugin exception: ") + le.what();
+    QFAIL(failMsg.toStdString().c_str());
+  }
+
+  // Check if pluginA_test registered the expected service
+  try
+  {
+    ctkServiceReference sr1 = pc->getServiceReference("ctkTestPluginAService");
+    QObject* o1 = pc->getService(sr1);
+    QVERIFY2(o1 != 0, "no service object found");
+
+    try
+    {
+      QVERIFY2(pc->ungetService(sr1), "Service unget should return true");
+    }
+    catch (const std::logic_error le)
+    {
+      QString failMsg = QString("Unget service exception: ") + le.what();
+      QFAIL(failMsg.toStdString().c_str());
+    }
+
+    // check the listeners for events
+    QList<ctkPluginEvent> pEvts;
+    pEvts.push_back(ctkPluginEvent(ctkPluginEvent::RESOLVED, pA));
+    pEvts.push_back(ctkPluginEvent(ctkPluginEvent::STARTED, pA));
+
+    QList<ctkServiceEvent> seEvts;
+    seEvts.push_back(ctkServiceEvent(ctkServiceEvent::REGISTERED, sr1));
+
+    QVERIFY2(checkListenerEvents(QList<ctkPluginFrameworkEvent>(), pEvts, seEvts),
+             "Unexpected events");
+
+    QList<ctkPluginEvent> syncPEvts;
+    syncPEvts.push_back(ctkPluginEvent(ctkPluginEvent::STARTING, pA));
+
+    QVERIFY2(checkSyncListenerEvents(syncPEvts), "Unexpected events");
+  }
+  catch (const ctkServiceException& /*se*/)
+  {
+    QFAIL("framework test bundle, expected service not found");
+  }
+}
+
+void ctkPluginFrameworkTestSuite::frameworkListener(const ctkPluginFrameworkEvent& fwEvent)
+{
+  frameworkEvents.push_back(fwEvent);
+  qDebug() << "FrameworkEvent:" << fwEvent;
+}
+
+void ctkPluginFrameworkTestSuite::pluginListener(const ctkPluginEvent& event)
+{
+  pluginEvents.push_back(event);
+  qDebug() << "PluginEvent:" << event;
+}
+
+void ctkPluginFrameworkTestSuite::syncPluginListener(const ctkPluginEvent& event)
+{
+  if (event.getType() == ctkPluginEvent::STARTING ||
+      event.getType() == ctkPluginEvent::STOPPING)
+  {
+    syncPluginEvents.push_back(event);
+    qDebug() << "Synchronous PluginEvent:" << event;
+  }
+}
+
+void ctkPluginFrameworkTestSuite::serviceListener(const ctkServiceEvent& event)
+{
+  serviceEvents.push_back(event);
+  qDebug() << "ServiceEvent:" << event;
+}
+
+ctkPluginEvent ctkPluginFrameworkTestSuite::getPluginEvent() const
+{
+  if (pluginEvents.empty())
+  {
+    return ctkPluginEvent();
+  }
+  return pluginEvents.last();
+}
+
+ctkPluginEvent ctkPluginFrameworkTestSuite::getSyncPluginEvent() const
+{
+  if (syncPluginEvents.empty())
+  {
+    return ctkPluginEvent();
+  }
+  return syncPluginEvents.last();
+}
+
+ctkPluginFrameworkEvent ctkPluginFrameworkTestSuite::getFrameworkEvent() const
+{
+  if (frameworkEvents.empty())
+  {
+    return ctkPluginFrameworkEvent();
+  }
+  return frameworkEvents.last();
+}
+
+ctkServiceEvent ctkPluginFrameworkTestSuite::getServiceEvent() const
+{
+  if (serviceEvents.empty())
+  {
+    return ctkServiceEvent();
+  }
+  return serviceEvents.last();
+}
+
+bool ctkPluginFrameworkTestSuite::checkListenerEvents(
+    bool fwexp, ctkPluginFrameworkEvent::Type fwtype,
+    bool pexp, ctkPluginEvent::Type ptype,
+    bool sexp, ctkServiceEvent::Type stype,
+    ctkPlugin* pluginX, ctkServiceReference* servX)
+{
+  QList<ctkPluginFrameworkEvent> fwEvts;
+  QList<ctkPluginEvent> pEvts;
+  QList<ctkServiceEvent> seEvts;
+
+  if (fwexp) fwEvts << ctkPluginFrameworkEvent(fwtype, pluginX);
+  if (pexp) pEvts << ctkPluginEvent(ptype, pluginX);
+  if (sexp) seEvts << ctkServiceEvent(stype, *servX);
+
+  return checkListenerEvents(fwEvts, pEvts, seEvts);
+}
+
+bool ctkPluginFrameworkTestSuite::checkListenerEvents(
+    const QList<ctkPluginFrameworkEvent>& fwEvts,
+    const QList<ctkPluginEvent>& pEvts,
+    const QList<ctkServiceEvent>& seEvts)
+{
+  bool listenState = true; // assume everything will work
+
+  // Wait a while to allow events to arrive
+  QTest::qWait(eventDelay);
+  //QCoreApplication::sendPostedEvents();
+
+  if (fwEvts.size() != frameworkEvents.size())
+  {
+    listenState = false;
+    qDebug() << "*** Plugin Framework event mismatch: expected"
+        << fwEvts.size() << "event(s), found"
+        << frameworkEvents.size() << "event(s).";
+
+    const int max = fwEvts.size() > frameworkEvents.size()
+                    ? fwEvts.size() : frameworkEvents.size();
+    for (int i = 0; i < max; ++i)
+    {
+      const ctkPluginFrameworkEvent& fwE = i < fwEvts.size() ? fwEvts[i] : ctkPluginFrameworkEvent();
+      const ctkPluginFrameworkEvent& fwR = i < frameworkEvents.size() ? frameworkEvents[i] : ctkPluginFrameworkEvent();
+      qDebug() << "    " << fwE << " - " << fwR;
+    }
+  }
+  else
+  {
+    for (int i = 0; i < fwEvts.size(); ++i)
+    {
+      const ctkPluginFrameworkEvent& feE = fwEvts[i];
+      const ctkPluginFrameworkEvent& feR = frameworkEvents[i];
+      if (feE.getType() != feR.getType()
+        || feE.getPlugin() != feR.getPlugin())
+      {
+        listenState = false;
+        qDebug() << "*** Wrong framework event:" << feR
+            << "expected" << feE;
+      }
+    }
+  }
+
+  if (pEvts.size() != pluginEvents.size())
+  {
+    listenState = false;
+    qDebug() << "*** Plugin event mismatch: expected"
+        << pEvts.size() << "event(s), found "
+        << pluginEvents.size() << "event(s).";
+
+    const int max = pEvts.size() > pluginEvents.size() ? pEvts.size() : pluginEvents.size();
+    for (int i = 0; i < max; ++i)
+    {
+      const ctkPluginEvent& pE = i < pEvts.size() ? pEvts[i] : ctkPluginEvent();
+      const ctkPluginEvent& pR = i < pluginEvents.size() ? pluginEvents[i] : ctkPluginEvent();
+      qDebug() << "    " << pE << " - " << pR;
+    }
+  }
+  else
+  {
+    for (int i = 0; i < pEvts.size(); ++i)
+    {
+      const ctkPluginEvent& pE = pEvts[i];
+      const ctkPluginEvent& pR = pluginEvents[i];
+      if (pE.getType() != pR.getType()
+        || pE.getPlugin() != pR.getPlugin())
+      {
+        listenState = false;
+        qDebug() << "*** Wrong plugin event:" << pR << "expected" << pE;
+      }
+    }
+  }
+
+  if (seEvts.size() != serviceEvents.size())
+  {
+    listenState = false;
+    qDebug() << "*** Service event mismatch: expected"
+        << seEvts.size() << "event(s), found"
+        << serviceEvents.size() << "event(s).";
+
+    const int max = seEvts.size() > serviceEvents.size()
+                    ? seEvts.size() : serviceEvents.size();
+    for (int i = 0; i < max; ++i)
+    {
+      const ctkServiceEvent& seE = i < seEvts.size() ? seEvts[i] : ctkServiceEvent();
+      const ctkServiceEvent& seR = i < serviceEvents.size() ? serviceEvents[i] : ctkServiceEvent();
+      qDebug() << "    " << seE << " - " << seR;
+    }
+  }
+  else
+  {
+    for (int i = 0; i < seEvts.size(); ++i)
+    {
+      const ctkServiceEvent& seE = seEvts[i];
+      const ctkServiceEvent& seR = serviceEvents[i];
+      if (seE.getType() != seR.getType()
+        || (!(seE.getServiceReference() == seR.getServiceReference())))
+      {
+        listenState = false;
+        qDebug() << "*** Wrong service event:" << seR << "expected" << seE;
+      }
+    }
+  }
+
+  frameworkEvents.clear();
+  pluginEvents.clear();
+  serviceEvents.clear();
+  return listenState;
+}
+
+// Check that the expected events have reached the listeners and
+// reset the events
+bool ctkPluginFrameworkTestSuite::checkSyncListenerEvents(
+    bool pexp, ctkPluginEvent::Type ptype, ctkPlugin* pX,
+    ctkServiceReference servX)
+{
+  Q_UNUSED(servX)
+
+  QList<ctkPluginEvent> pEvts;
+
+  if (pexp)
+  {
+    pEvts << ctkPluginEvent(ptype, pX);
+  }
+
+  return checkSyncListenerEvents(pEvts);
+}
+
+// Check that the expected events have reached the listeners and
+// reset the events
+bool ctkPluginFrameworkTestSuite::checkSyncListenerEvents(
+    const QList<ctkPluginEvent>& pEvts)
+{
+  bool listenState = true; // assume everything will work
+
+  // Sleep a while to allow events to arrive
+  QTest::qWait(eventDelay);
+
+  if (pEvts.size() != syncPluginEvents.size())
+  {
+    listenState = false;
+    qDebug() << "*** Sync plugin event mismatch: expected"
+        << pEvts.size() << "event(s), found"
+        << syncPluginEvents.size() << "event(s).";
+
+    const int max = pEvts.size() > syncPluginEvents.size() ? pEvts.size() : syncPluginEvents.size();
+    for (int i = 0; i < max; ++i)
+    {
+      const ctkPluginEvent& pE =  i< pEvts.size() ? pEvts[i] : ctkPluginEvent();
+      const ctkPluginEvent& pR = i < syncPluginEvents.size() ? syncPluginEvents[i] : ctkPluginEvent();
+      qDebug() << "    " << pE << " - " << pR;
+    }
+  }
+  else
+  {
+    for (int i = 0; i < pEvts.size(); ++i)
+    {
+      const ctkPluginEvent& pE = pEvts[i];
+      const ctkPluginEvent& pR = syncPluginEvents[i];
+      if (pE.getType() != pR.getType() || pE.getPlugin() != pR.getPlugin())
+      {
+        listenState = false;
+        qDebug() << "Wrong sync plugin event:" << pR << "expected" << pE;
+      }
+    }
+  }
+
+  syncPluginEvents.clear();
+  return listenState;
+}

+ 109 - 0
Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestSuite_p.h

@@ -0,0 +1,109 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 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 CTKPLUGINFRAMEWORKTESTSUITE_P_H
+#define CTKPLUGINFRAMEWORKTESTSUITE_P_H
+
+#include <QObject>
+
+#include <ctkPluginFrameworkEvent.h>
+#include <ctkPluginEvent.h>
+#include <ctkServiceEvent.h>
+
+#include <ctkTestSuiteInterface.h>
+
+class ctkPluginContext;
+
+class ctkPluginFrameworkTestSuite : public QObject,
+                                    public ctkTestSuiteInterface
+{
+  Q_OBJECT
+
+public:
+
+  ctkPluginFrameworkTestSuite(ctkPluginContext* pc);
+
+protected slots:
+
+  void frameworkListener(const ctkPluginFrameworkEvent& fwEvent);
+  void pluginListener(const ctkPluginEvent& event);
+  void syncPluginListener(const ctkPluginEvent& event);
+  void serviceListener(const ctkServiceEvent& event);
+
+private slots:
+
+  void initTestCase();
+  void cleanupTestCase();
+
+  // test functions
+  void frame005a();
+  void frame020a();
+  void frame025b();
+
+private:
+
+  ctkPluginEvent getPluginEvent() const;
+  ctkPluginEvent getSyncPluginEvent() const;
+  ctkPluginFrameworkEvent getFrameworkEvent() const;
+  ctkServiceEvent getServiceEvent() const;
+
+  // Check that the expected events have reached the listeners and
+  // reset the events
+  bool checkListenerEvents(
+      bool fwexp, ctkPluginFrameworkEvent::Type fwtype,
+      bool pexp, ctkPluginEvent::Type ptype,
+      bool sexp, ctkServiceEvent::Type stype,
+      ctkPlugin* pluginX, ctkServiceReference* servX);
+
+  // Check that the expected events have reached the listeners and
+  // reset the events
+  bool checkListenerEvents(
+      const QList<ctkPluginFrameworkEvent>& fwEvts,
+      const QList<ctkPluginEvent>& pEvts,
+      const QList<ctkServiceEvent>& seEvts);
+
+  // Check that the expected events have reached the listeners and
+  // reset the events
+  bool checkSyncListenerEvents(
+      bool pexp, ctkPluginEvent::Type ptype, ctkPlugin* pX,
+      ctkServiceReference servX);
+
+  // Check that the expected events have reached the listeners and
+  // reset the events
+  bool checkSyncListenerEvents(const QList<ctkPluginEvent>& pEvts);
+
+  static int nRunCount;
+
+  QList<ctkPluginEvent> pluginEvents;
+  QList<ctkPluginEvent> syncPluginEvents;
+  QList<ctkPluginFrameworkEvent> frameworkEvents;
+  QList<ctkServiceEvent> serviceEvents;
+
+  int eventDelay;
+
+  ctkPluginContext* pc;
+  ctkPlugin* p;
+
+  ctkPlugin* pA;
+
+};
+
+#endif // CTKPLUGINFRAMEWORKTESTSUITE_P_H

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

@@ -0,0 +1,10 @@
+set(Plugin-ActivationPolicy "eager")
+set(Plugin-Name "framework_test")
+set(Plugin-Version "1.0.1")
+set(Plugin-Description "Test bundle for the CTK plugin framework")
+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/FrameworkTest/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
+  )

+ 7 - 0
Libs/PluginFramework/Testing/TestPlugins/CMakeLists.txt

@@ -0,0 +1,7 @@
+set(test_plugins
+  pluginA_test
+)
+
+foreach(test_plugin ${test_plugins})
+  ADD_SUBDIRECTORY(${test_plugin})
+endforeach()

+ 30 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/CMakeLists.txt

@@ -0,0 +1,30 @@
+PROJECT(pluginA_test)
+
+SET(PLUGIN_export_directive "pluginA_test_EXPORT")
+
+SET(PLUGIN_SRCS
+  ctkTestPluginA.cpp
+  ctkTestPluginAActivator.cpp
+  ctkTestPluginAService.h
+)
+
+SET(PLUGIN_MOC_SRCS
+  ctkTestPluginA_p.h
+  ctkTestPluginAActivator_p.h
+)
+
+SET(PLUGIN_resources
+  
+)
+
+ctkMacroGetTargetLibraries(PLUGIN_target_libraries)
+
+ctkMacroBuildPlugin(
+  NAME ${PROJECT_NAME}
+  EXPORT_DIRECTIVE ${PLUGIN_export_directive}
+  SRCS ${PLUGIN_SRCS}
+  MOC_SRCS ${PLUGIN_MOC_SRCS}
+  RESOURCES ${PLUGIN_resources}
+  TARGET_LIBRARIES ${PLUGIN_target_libraries}
+  TEST_PLUGIN
+)

+ 32 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginA.cpp

@@ -0,0 +1,32 @@
+/*=============================================================================
+
+  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 "ctkTestPluginA_p.h"
+
+#include <ctkPluginContext.h>
+
+#include <QStringList>
+
+ctkTestPluginA::ctkTestPluginA(ctkPluginContext* pc)
+{
+  pc->registerService(QStringList("ctkTestPluginAService"), this);
+}

+ 41 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAActivator.cpp

@@ -0,0 +1,41 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 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 "ctkTestPluginAActivator_p.h"
+#include "ctkTestPluginA_p.h"
+
+#include <ctkPluginContext.h>
+
+#include <QtPlugin>
+
+void ctkTestPluginAActivator::start(ctkPluginContext* context)
+{
+  s = new ctkTestPluginA(context);
+}
+
+void ctkTestPluginAActivator::stop(ctkPluginContext* context)
+{
+  Q_UNUSED(context)
+  delete s;
+}
+
+Q_EXPORT_PLUGIN2(pluginA_test, ctkTestPluginAActivator)

+ 46 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAActivator_p.h

@@ -0,0 +1,46 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINAACTIVATOR_P_H
+#define CTKTESTPLUGINAACTIVATOR_P_H
+
+#include <ctkPluginActivator.h>
+
+class ctkTestPluginAService;
+
+class ctkTestPluginAActivator : public QObject,
+                                public ctkPluginActivator
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkPluginActivator)
+
+public:
+
+  void start(ctkPluginContext* context);
+  void stop(ctkPluginContext* context);
+
+private:
+
+  ctkTestPluginAService* s;
+
+};
+
+#endif // CTKTESTPLUGINAACTIVATOR_P_H

+ 31 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginAService.h

@@ -0,0 +1,31 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINASERVICE_H
+#define CTKTESTPLUGINASERVICE_H
+
+struct ctkTestPluginAService
+{
+  virtual ~ctkTestPluginAService() {}
+};
+
+#endif // CTKTESTPLUGINASERVICE_H

+ 41 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/ctkTestPluginA_p.h

@@ -0,0 +1,41 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINA_P_H
+#define CTKTESTPLUGINA_P_H
+
+#include <QObject>
+
+#include "ctkTestPluginAService.h"
+
+class ctkPluginContext;
+
+class ctkTestPluginA : public QObject,
+                       public ctkTestPluginAService
+{
+  Q_OBJECT
+
+public:
+    ctkTestPluginA(ctkPluginContext* pc);
+};
+
+#endif // CTKTESTPLUGINA_P_H

+ 7 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/manifest_headers.cmake

@@ -0,0 +1,7 @@
+set(Plugin-ActivationPolicy "eager")
+set(Plugin-Name "pluginA_test")
+set(Plugin-Version "1.0.0")
+set(Plugin-Description "Test plugin for framework, pluginA_test")
+set(Plugin-Vendor "CommonTK")
+set(Plugin-ContactAddress "http://www.commontk.org")
+set(Plugin-Category "test")

+ 9 - 0
Libs/PluginFramework/Testing/TestPlugins/pluginA_test/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
+  )