Browse Source

Merge branch 'service-tracker-tests'

* service-tracker-tests:
  Added unit tests for ctkServiceTracker.
  Fixed recursive mutex lock issues.
  Added missing null pointer check.
  Replaced tabs with spaces.
Sascha Zelzer 14 years ago
parent
commit
15539d12a4
25 changed files with 794 additions and 16 deletions
  1. 1 0
      Libs/PluginFramework/Testing/CMakeLists.txt
  2. 2 0
      Libs/PluginFramework/Testing/FrameworkTest/CMakeLists.txt
  3. 9 1
      Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestActivator.cpp
  4. 1 0
      Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestActivator_p.h
  5. 237 0
      Libs/PluginFramework/Testing/FrameworkTest/ctkServiceTrackerTestSuite.cpp
  6. 91 0
      Libs/PluginFramework/Testing/FrameworkTest/ctkServiceTrackerTestSuite_p.h
  7. 33 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/CMakeLists.txt
  8. 67 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginS.cpp
  9. 48 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSActivator.cpp
  10. 50 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSActivator_p.h
  11. 35 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService0.h
  12. 35 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService1.h
  13. 35 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService2.h
  14. 35 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService3.h
  15. 63 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginS_p.h
  16. 7 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/manifest_headers.cmake
  17. 9 0
      Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/target_libraries.cmake
  18. 1 1
      Libs/PluginFramework/ctkPluginAbstractTracked_p.h
  19. 1 1
      Libs/PluginFramework/ctkServiceRegistration.cpp
  20. 1 1
      Libs/PluginFramework/ctkServiceRegistrationPrivate.cpp
  21. 5 8
      Libs/PluginFramework/ctkServiceTracker.tpp
  22. 2 0
      Libs/PluginFramework/ctkServiceTrackerPrivate.h
  23. 11 0
      Libs/PluginFramework/ctkServiceTrackerPrivate.tpp
  24. 10 4
      Libs/PluginFramework/ctkServices.cpp
  25. 5 0
      Libs/PluginFramework/ctkServices_p.h

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

@@ -7,6 +7,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/Cpp)
 
 SET(fwtest_plugins
   pluginA_test
+  pluginS_test
   pluginA2_test
   pluginD_test
   pluginSL1_test

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

@@ -6,12 +6,14 @@ SET(PLUGIN_SRCS
   ctkPluginFrameworkTestActivator.cpp
   ctkPluginFrameworkTestSuite.cpp
   ctkServiceListenerTestSuite.cpp
+  ctkServiceTrackerTestSuite.cpp
 )
 
 SET(PLUGIN_MOC_SRCS
   ctkPluginFrameworkTestActivator_p.h
   ctkPluginFrameworkTestSuite_p.h
   ctkServiceListenerTestSuite_p.h
+  ctkServiceTrackerTestSuite_p.h
 )
 
 SET(PLUGIN_UI_FORMS

+ 9 - 1
Libs/PluginFramework/Testing/FrameworkTest/ctkPluginFrameworkTestActivator.cpp

@@ -23,6 +23,7 @@
 
 #include "ctkPluginFrameworkTestSuite_p.h"
 #include "ctkServiceListenerTestSuite_p.h"
+#include "ctkServiceTrackerTestSuite_p.h"
 
 #include <ctkPluginContext.h>
 #include <ctkPluginConstants.h>
@@ -41,8 +42,14 @@ void ctkPluginFrameworkTestActivator::start(ctkPluginContext* context)
   context->registerService<ctkTestSuiteInterface>(frameworkTestSuite, props);
 
   serviceListenerTestSuite = new ctkServiceListenerTestSuite(context);
-  props.insert(ctkPluginConstants::SERVICE_PID, frameworkTestSuite->metaObject()->className());
+  props.clear();
+  props.insert(ctkPluginConstants::SERVICE_PID, serviceListenerTestSuite->metaObject()->className());
   context->registerService<ctkTestSuiteInterface>(serviceListenerTestSuite, props);
+
+  serviceTrackerTestSuite = new ctkServiceTrackerTestSuite(context);
+  props.clear();
+  props.insert(ctkPluginConstants::SERVICE_PID, serviceTrackerTestSuite->metaObject()->className());
+  context->registerService<ctkTestSuiteInterface>(serviceTrackerTestSuite, props);
 }
 
 //----------------------------------------------------------------------------
@@ -52,6 +59,7 @@ void ctkPluginFrameworkTestActivator::stop(ctkPluginContext* context)
 
   delete frameworkTestSuite;
   delete serviceListenerTestSuite;
+  delete serviceTrackerTestSuite;
 }
 
 Q_EXPORT_PLUGIN2(org_commontk_pluginfwtest, ctkPluginFrameworkTestActivator)

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

@@ -41,6 +41,7 @@ private:
 
   QObject* frameworkTestSuite;
   QObject* serviceListenerTestSuite;
+  QObject* serviceTrackerTestSuite;
 };
 
 #endif // CTKPLUGINFRAMEWORKTESTACTIVATOR_H

+ 237 - 0
Libs/PluginFramework/Testing/FrameworkTest/ctkServiceTrackerTestSuite.cpp

@@ -0,0 +1,237 @@
+/*=============================================================================
+
+  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 "ctkServiceTrackerTestSuite_p.h"
+
+#include <ctkPlugin.h>
+#include <ctkPluginContext.h>
+#include <ctkPluginException.h>
+#include <ctkServiceTracker.h>
+
+#include <ctkPluginFrameworkTestUtil.h>
+
+#include <QTest>
+
+//----------------------------------------------------------------------------
+ctkServiceTrackerTestSuite::ctkServiceTrackerTestSuite(ctkPluginContext* pc)
+  : pc(pc), p(pc->getPlugin())
+{
+}
+
+//----------------------------------------------------------------------------
+void ctkServiceTrackerTestSuite::initTestCase()
+{
+  // load and start pluginS_test, that may be prodded to
+  // register/unregister some services. At start it registers one
+  // service, org.commontk.pluginStest.TestPluginSService0
+  pS = ctkPluginFrameworkTestUtil::installPlugin(pc, "pluginS_test");
+  QVERIFY(pS);
+}
+
+//----------------------------------------------------------------------------
+void ctkServiceTrackerTestSuite::cleanupTestCase()
+{
+  pS->uninstall();
+}
+
+//----------------------------------------------------------------------------
+void ctkServiceTrackerTestSuite::runTest()
+{
+  try
+  {
+    pS->start();
+    qDebug() << "started service plugin";
+  }
+  catch (const ctkPluginException& pexcS)
+  {
+    QString msg = QString("Test plugin: ") + pexcS.what();
+    QFAIL(msg.toAscii());
+  }
+
+  // 1. Create a ctkServiceTracker with ctkServiceTrackerCustomizer == null
+
+  QString s1("org.commontk.pluginStest.TestPluginSService");
+  ctkServiceReference servref = pc->getServiceReference(s1 + "0");
+
+  QVERIFY2(servref != 0, "Test if registered service of id org.commontk.pluginStest.TestPluginSService0");
+
+  connect(this, SIGNAL(serviceControl(int,QString,long)),
+          pc->getService(servref), SLOT(controlService(int,QString,long)));
+
+  ctkServiceTracker<>* st1 = new ctkServiceTracker<>(pc, servref);
+
+  // 2. Check the size method with an unopened service tracker
+
+  QVERIFY2(st1->size() == 0, "Test if size == 0");
+
+  // 3. Open the service tracker and see what it finds,
+  // expect to find one instance of the implementation,
+  // "org.commontk.pluginStest.TestPluginSService0"
+
+  st1->open();
+  QString expName  = "ctkTestPluginS";
+  QList<ctkServiceReference> sa2 = st1->getServiceReferences();
+
+  QVERIFY(sa2.size() == 1);
+  QString name = pc->getService(sa2[0])->metaObject()->className();
+  QVERIFY(name == expName);
+
+  // 5. Close this service tracker
+  st1->close();
+
+  // 6. Check the size method, now when the servicetracker is closed
+  QVERIFY(st1->size() == 0);
+
+  // 7. Check if we still track anything , we should get null
+  sa2 = st1->getServiceReferences();
+  QVERIFY(sa2.empty());
+
+  // 8. A new Servicetracker, this time with a filter for the object
+  QString fs = QString("(") + ctkPluginConstants::OBJECTCLASS + "=" + s1 + "*" + ")";
+  ctkLDAPSearchFilter f1(fs);
+  delete st1;
+  st1 = new ctkServiceTracker<>(pc, f1);
+  // add a service
+  emit serviceControl(1, "register", 7);
+
+  // 9. Open the service tracker and see what it finds,
+  // expect to find two instances of references to
+  // "org.commontk.pluginStest.TestPluginSService*"
+  // i.e. they refer to the same piece of code
+
+  st1->open();
+  sa2 = st1->getServiceReferences();
+  QVERIFY(sa2.size() == 2);
+  for (int i = 0;  i < sa2.size(); ++i)
+  {
+    QString name = pc->getService(sa2[i])->metaObject()->className();
+    QVERIFY(name == expName);
+  }
+
+  // 10. Get pluginS_test to register one more service and see if it appears
+  emit serviceControl(2, "register", 1);
+  sa2 = st1->getServiceReferences();
+  QVERIFY(sa2.size() == 3);
+  for (int i = 0; i < sa2.size(); ++i)
+  {
+    QString name = pc->getService(sa2[i])->metaObject()->className();
+    QVERIFY(name == expName);
+  }
+
+  // 11. Get pluginS_test to register one more service and see if it appears
+  emit serviceControl(3, "register", 2);
+  sa2 = st1->getServiceReferences();
+  QVERIFY(sa2.size() == 4);
+  for (int i = 0; i < sa2.size(); ++i)
+  {
+    QString name = pc->getService(sa2[i])->metaObject()->className();
+    QVERIFY(name == expName);
+  }
+
+  // 12. Get pluginS_test to unregister one service and see if it disappears
+  emit serviceControl(3, "unregister", 0);
+  sa2 = st1->getServiceReferences();
+  QVERIFY(sa2.size() == 3);
+  for (int i = 0; i < sa2.size(); ++i)
+  {
+    QString name = pc->getService(sa2[i])->metaObject()->className();
+    QVERIFY(name == expName);
+  }
+
+  // 13. Get the highest ranking service reference, it should have ranking 7
+  ctkServiceReference h1 = st1->getServiceReference();
+  long rank = h1.getProperty(ctkPluginConstants::SERVICE_RANKING).toLongLong();
+  QVERIFY(rank == 7);
+
+  // 14. Get the service of the highest ranked service reference
+
+  QObject* o1 = st1->getService(h1);
+  QVERIFY(o1 != 0);
+
+  // 14a Get the highest ranked service, directly this time
+  QObject* o3 = st1->getService();
+  QVERIFY(o3 != 0);
+  QVERIFY(o1 == o3);
+
+  // 15. Now release the tracking of that service and then try to get it
+  //     from the servicetracker, which should yield a null object
+  emit serviceControl (1, "unregister", 7);
+  QObject* o2 = st1->getService(h1);
+  QVERIFY(o2 == 0);
+
+  // 16. Get all service objects this tracker tracks, it should be 2
+  QList<QObject*> ts1 = st1->getServices();
+  QVERIFY(ts1.size() == 2);
+
+  // 17. Test the remove method.
+  //     First register another service, then remove it being tracked
+  emit serviceControl(1, "register", 7);
+  h1 = st1->getServiceReference();
+  QList<ctkServiceReference> sa3 = st1->getServiceReferences();
+  QVERIFY(sa3.size() == 3);
+  for (int i = 0; i < sa3.size(); ++i)
+  {
+    QString name = pc->getService(sa3[i])->metaObject()->className();
+    QVERIFY(name == expName);
+  }
+
+  st1->remove(h1);           // remove tracking on one servref
+  sa2 = st1->getServiceReferences();
+  QVERIFY(sa2.size() == 2);
+
+  // 18. Test the addingService method,add a service reference
+
+  // 19. Test the removedService method, remove a service reference
+
+
+  // 20. Test the waitForService method
+  QObject* o9 = st1->waitForService(50);
+  QVERIFY(o9 != 0);
+
+  // 21. Test the waitForService method across threads
+  ctkServiceTrackerTestWorker worker(pc);
+  worker.start();
+  QTest::qWait(100);
+  // register "org.commontk.pluginStest.TestPluginSService3"
+  emit serviceControl(3, "register", 2);
+  QVERIFY(worker.wait());
+  QVERIFY(worker.waitSuccess);
+
+}
+
+ctkServiceTrackerTestWorker::ctkServiceTrackerTestWorker(ctkPluginContext* pc)
+  : waitSuccess(false), pc(pc)
+{
+
+}
+
+void ctkServiceTrackerTestWorker::run()
+{
+  ctkServiceTracker<> tracker(pc, "org.commontk.pluginStest.TestPluginSService3");
+  tracker.open();
+  // the tracker should initially be empty
+  QVERIFY(tracker.isEmpty());
+  QObject* obj = tracker.waitForService(1000);
+  if (obj != 0) waitSuccess = true;
+  quit();
+}
+

+ 91 - 0
Libs/PluginFramework/Testing/FrameworkTest/ctkServiceTrackerTestSuite_p.h

@@ -0,0 +1,91 @@
+/*=============================================================================
+
+  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 CTKSERVICETRACKERTESTSUITE_P_H
+#define CTKSERVICETRACKERTESTSUITE_P_H
+
+#include <QObject>
+#include <QThread>
+
+#include <ctkTestSuiteInterface.h>
+#include <ctkServiceEvent.h>
+
+class ctkPlugin;
+class ctkPluginContext;
+
+class ctkServiceTrackerTestSuite : public QObject,
+    public ctkTestSuiteInterface
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkTestSuiteInterface)
+
+public:
+    ctkServiceTrackerTestSuite(ctkPluginContext* pc);
+
+private slots:
+
+    void initTestCase();
+    void cleanupTestCase();
+
+    // test functions
+
+    // Checks that the correct service events
+    // are sent to a registered service listener.
+    // Case where the plugin does not unregister its
+    // service in the stop()-method.
+    void runTest();
+
+signals:
+
+    void serviceControl(int service, const QString operation, long rank);
+
+private:
+
+    ctkPluginContext* pc;
+    QSharedPointer<ctkPlugin> p;
+
+    QSharedPointer<ctkPlugin> pS;
+
+};
+
+class ctkServiceTrackerTestWorker : public QThread
+{
+  Q_OBJECT
+
+public:
+
+  ctkServiceTrackerTestWorker(ctkPluginContext* pc);
+
+  bool waitSuccess;
+
+protected:
+
+  void run();
+
+private:
+
+  ctkPluginContext* pc;
+
+};
+
+
+#endif // CTKSERVICETRACKERTESTSUITE_P_H

+ 33 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/CMakeLists.txt

@@ -0,0 +1,33 @@
+PROJECT(pluginS_test)
+
+SET(PLUGIN_export_directive "pluginS_test_EXPORT")
+
+SET(PLUGIN_SRCS
+  ctkTestPluginS.cpp
+  ctkTestPluginSActivator.cpp
+  ctkTestPluginSService0.h
+  ctkTestPluginSService1.h
+  ctkTestPluginSService2.h
+  ctkTestPluginSService3.h
+)
+
+SET(PLUGIN_MOC_SRCS
+  ctkTestPluginS_p.h
+  ctkTestPluginSActivator_p.h
+)
+
+SET(PLUGIN_resources
+  
+)
+
+ctkFunctionGetTargetLibraries(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
+)

+ 67 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginS.cpp

@@ -0,0 +1,67 @@
+/*=============================================================================
+
+  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 "ctkTestPluginS_p.h"
+
+#include <ctkPluginContext.h>
+
+#include <QStringList>
+
+const QString ctkTestPluginS::SERVICE = "org.commontk.pluginStest.TestPluginSService";
+
+//----------------------------------------------------------------------------
+ctkTestPluginS::ctkTestPluginS(ctkPluginContext* pc)
+  : pc(pc)
+{
+  for(int i = 0; i <= 3; ++i)
+  {
+    servregs.push_back(ctkServiceRegistration());
+  }
+  sreg = pc->registerService<ctkTestPluginSService0>(this);
+}
+
+//----------------------------------------------------------------------------
+void ctkTestPluginS::controlService(int offset, const QString& operation, long ranking)
+{
+  if (0 <= offset && offset <= 3)
+  {
+    if (operation == "register")
+    {
+      if (!servregs[offset])
+      {
+        QString servicename = SERVICE + QString::number(offset);
+        ctkProperties props;
+        props.insert(ctkPluginConstants::SERVICE_RANKING, QVariant::fromValue(ranking));
+        servregs[offset] = pc->registerService(QStringList(servicename), this, props);
+      }
+    }
+    if (operation == "unregister")
+    {
+      if (servregs[offset])
+      {
+        ctkServiceRegistration sr1 = servregs[offset];
+        sr1.unregister();
+        servregs[offset] = 0;
+      }
+    }
+  }
+}

+ 48 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSActivator.cpp

@@ -0,0 +1,48 @@
+/*=============================================================================
+
+  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 "ctkTestPluginSActivator_p.h"
+#include "ctkTestPluginS_p.h"
+
+#include <ctkPluginContext.h>
+
+#include <QtPlugin>
+
+//----------------------------------------------------------------------------
+void ctkTestPluginSActivator::start(ctkPluginContext* context)
+{
+  s.reset(new ctkTestPluginS(context));
+}
+
+//----------------------------------------------------------------------------
+void ctkTestPluginSActivator::stop(ctkPluginContext* context)
+{
+  Q_UNUSED(context)
+}
+
+//----------------------------------------------------------------------------
+ctkTestPluginSActivator::~ctkTestPluginSActivator()
+{
+
+}
+
+Q_EXPORT_PLUGIN2(pluginS_test, ctkTestPluginSActivator)

+ 50 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSActivator_p.h

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

+ 35 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService0.h

@@ -0,0 +1,35 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINSSERVICE0_H
+#define CTKTESTPLUGINSSERVICE0_H
+
+#include <qglobal.h>
+
+struct ctkTestPluginSService0
+{
+  virtual ~ctkTestPluginSService0() {}
+};
+
+Q_DECLARE_INTERFACE(ctkTestPluginSService0, "org.commontk.pluginStest.TestPluginSService0")
+
+#endif // CTKTESTPLUGINSSERVICE0_H

+ 35 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService1.h

@@ -0,0 +1,35 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINSSERVICE1_H
+#define CTKTESTPLUGINSSERVICE1_H
+
+#include <qglobal.h>
+
+struct ctkTestPluginSService1
+{
+  virtual ~ctkTestPluginSService1() {}
+};
+
+Q_DECLARE_INTERFACE(ctkTestPluginSService1, "org.commontk.pluginStest.TestPluginSService1")
+
+#endif // CTKTESTPLUGINSSERVICE1_H

+ 35 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService2.h

@@ -0,0 +1,35 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINSSERVICE2_H
+#define CTKTESTPLUGINSSERVICE2_H
+
+#include <qglobal.h>
+
+struct ctkTestPluginSService2
+{
+  virtual ~ctkTestPluginSService2() {}
+};
+
+Q_DECLARE_INTERFACE(ctkTestPluginSService2, "org.commontk.pluginStest.TestPluginSService2")
+
+#endif // CTKTESTPLUGINSSERVICE0_H

+ 35 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginSService3.h

@@ -0,0 +1,35 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINSSERVICE3_H
+#define CTKTESTPLUGINSSERVICE3_H
+
+#include <qglobal.h>
+
+struct ctkTestPluginSService3
+{
+  virtual ~ctkTestPluginSService3() {}
+};
+
+Q_DECLARE_INTERFACE(ctkTestPluginSService3, "org.commontk.pluginStest.TestPluginSService3")
+
+#endif // CTKTESTPLUGINSSERVICE0_H

+ 63 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/ctkTestPluginS_p.h

@@ -0,0 +1,63 @@
+/*=============================================================================
+
+  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 CTKTESTPLUGINS_P_H
+#define CTKTESTPLUGINS_P_H
+
+#include <QObject>
+
+#include "ctkTestPluginSService0.h"
+#include "ctkTestPluginSService1.h"
+#include "ctkTestPluginSService2.h"
+#include "ctkTestPluginSService3.h"
+
+#include <ctkServiceRegistration.h>
+
+class ctkPluginContext;
+
+class ctkTestPluginS : public QObject,
+                       public ctkTestPluginSService0,
+                       public ctkTestPluginSService1,
+                       public ctkTestPluginSService2,
+                       public ctkTestPluginSService3
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkTestPluginSService0 ctkTestPluginSService1 ctkTestPluginSService2 ctkTestPluginSService3)
+
+public:
+
+  ctkTestPluginS(ctkPluginContext* pc);
+  
+public slots:
+
+  void controlService(int service, const QString& operation, long ranking);
+
+private:
+
+  static const QString SERVICE; // = "org.commontk.pluginStest.TestPluginSService"
+
+  ctkPluginContext* pc;
+  QList<ctkServiceRegistration> servregs;
+  ctkServiceRegistration sreg;
+};
+
+#endif // CTKTESTPLUGINS_P_H

+ 7 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/manifest_headers.cmake

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

+ 9 - 0
Libs/PluginFramework/Testing/FrameworkTestPlugins/pluginS_test/target_libraries.cmake

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

+ 1 - 1
Libs/PluginFramework/ctkPluginAbstractTracked_p.h

@@ -51,7 +51,7 @@ class ctkPluginAbstractTracked : public QMutex
 public:
 
   /* set this to true to compile in debug messages */
-  static const bool	DEBUG; //	= false;
+  static const bool DEBUG; // = false;
 
   /**
    * ctkPluginAbstractTracked constructor.

+ 1 - 1
Libs/PluginFramework/ctkServiceRegistration.cpp

@@ -44,7 +44,7 @@ ctkServiceRegistration::ctkServiceRegistration()
 ctkServiceRegistration::ctkServiceRegistration(const ctkServiceRegistration& reg)
   : d_ptr(reg.d_ptr)
 {
-  d_func()->ref.ref();
+  if (d_func()) d_func()->ref.ref();
 }
 
 //----------------------------------------------------------------------------

+ 1 - 1
Libs/PluginFramework/ctkServiceRegistrationPrivate.cpp

@@ -27,7 +27,7 @@ ctkServiceRegistrationPrivate::ctkServiceRegistrationPrivate(
   const ctkDictionary& props)
   : ref(1), service(service), plugin(plugin), reference(this),
     properties(props), available(true), unregistering(false),
-    propsLock(QMutex::Recursive)
+    propsLock()
 {
 
 }

+ 5 - 8
Libs/PluginFramework/ctkServiceTracker.tpp

@@ -220,11 +220,7 @@ QList<ctkServiceReference> ctkServiceTracker<S,T>::getServiceReferences() const
   }
   {
     QMutexLocker lockT(t.data());
-    if (t->size() == 0)
-    {
-      return QList<ctkServiceReference>();
-    }
-    return t->getTracked();
+    return d->getServiceReferences_unlocked(t.data());
   }
 }
 
@@ -337,11 +333,12 @@ QList<T> ctkServiceTracker<S,T>::getServices() const
   }
   {
     QMutexLocker lockT(t.data());
-    QList<ctkServiceReference> references = getServiceReferences();
+    QList<ctkServiceReference> references = d->getServiceReferences_unlocked(t.data());
     QList<T> objects;
     foreach (ctkServiceReference ref, references)
     {
-      objects << getService(ref);
+      //objects << getService(ref);
+      objects << t->getCustomizedObject(ref);
     }
     return objects;
   }
@@ -358,7 +355,7 @@ T ctkServiceTracker<S,T>::getService() const
     if (d->DEBUG)
     {
       qDebug() << "ctkServiceTracker<S,T>::getService[cached]:"
-                   << d->filter;
+               << d->filter;
     }
     return service;
   }

+ 2 - 0
Libs/PluginFramework/ctkServiceTrackerPrivate.h

@@ -69,6 +69,8 @@ public:
   QList<ctkServiceReference> getInitialReferences(const QString& className,
                                                   const QString& filterString);
 
+  QList<ctkServiceReference> getServiceReferences_unlocked(ctkTrackedService<S,T>* t) const;
+
   /* set this to true to compile in debug messages */
   static const bool	DEBUG; //	= false;
 

+ 11 - 0
Libs/PluginFramework/ctkServiceTrackerPrivate.tpp

@@ -122,6 +122,17 @@ QList<ctkServiceReference> ctkServiceTrackerPrivate<S,T>::getInitialReferences(c
 
 //----------------------------------------------------------------------------
 template<class S, class T>
+QList<ctkServiceReference> ctkServiceTrackerPrivate<S,T>::getServiceReferences_unlocked(ctkTrackedService<S,T>* t) const
+{
+  if (t->size() == 0)
+  {
+    return QList<ctkServiceReference>();
+  }
+  return t->getTracked();
+}
+
+//----------------------------------------------------------------------------
+template<class S, class T>
 QSharedPointer<ctkTrackedService<S,T> > ctkServiceTrackerPrivate<S,T>::tracked() const
 {
   return trackedService;

+ 10 - 4
Libs/PluginFramework/ctkServices.cpp

@@ -63,7 +63,7 @@ ctkDictionary ctkServices::createServiceProperties(const ctkDictionary& in,
 
 //----------------------------------------------------------------------------
 ctkServices::ctkServices(ctkPluginFrameworkContext* fwCtx)
-  : mutex(QMutex::Recursive), framework(fwCtx)
+  : mutex(), framework(fwCtx)
 {
 
 }
@@ -166,7 +166,7 @@ ctkServiceReference ctkServices::get(ctkPluginPrivate* plugin, const QString& cl
 {
   QMutexLocker lock(&mutex);
   try {
-    QList<ctkServiceReference> srs = get(clazz, QString(), plugin);
+    QList<ctkServiceReference> srs = get_unlocked(clazz, QString(), plugin);
     if (framework->debug.service_reference)
     {
       qDebug() << "get service ref" << clazz << "for plugin"
@@ -186,9 +186,15 @@ ctkServiceReference ctkServices::get(ctkPluginPrivate* plugin, const QString& cl
 QList<ctkServiceReference> ctkServices::get(const QString& clazz, const QString& filter,
                                             ctkPluginPrivate* plugin) const
 {
-  Q_UNUSED(plugin)
-
   QMutexLocker lock(&mutex);
+  return get_unlocked(clazz, filter, plugin);
+}
+
+//----------------------------------------------------------------------------
+QList<ctkServiceReference> ctkServices::get_unlocked(const QString& clazz, const QString& filter,
+                                                     ctkPluginPrivate* plugin) const
+{
+  Q_UNUSED(plugin)
 
   QListIterator<ctkServiceRegistration>* s = 0;
   QList<ctkServiceRegistration> v;

+ 5 - 0
Libs/PluginFramework/ctkServices_p.h

@@ -179,6 +179,11 @@ public:
    */
   QList<ctkServiceRegistration> getUsedByPlugin(QSharedPointer<ctkPlugin> p) const;
 
+private:
+
+  QList<ctkServiceReference> get_unlocked(const QString& clazz, const QString& filter,
+                                          ctkPluginPrivate* plugin) const;
+
 };