From b63a404897f33891ba3968c17393bf11f72ccd82 Mon Sep 17 00:00:00 2001 From: Marja Hassinen Date: Fri, 11 Sep 2009 13:40:37 +0300 Subject: libcontextsubscriber plugins: Move declaration files to test directory. --- libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp | 4 ++++ libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp | 4 ++++ .../customer-tests/testplugins/timeplugin1/time1.context | 4 ---- .../customer-tests/testplugins/timeplugin2/time2.context | 4 ---- 4 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp create mode 100644 libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp delete mode 100644 libcontextsubscriber/customer-tests/testplugins/timeplugin1/time1.context delete mode 100644 libcontextsubscriber/customer-tests/testplugins/timeplugin2/time2.context diff --git a/libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp b/libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp new file mode 100644 index 00000000..33c9d20d --- /dev/null +++ b/libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp @@ -0,0 +1,4 @@ + + + STRING + diff --git a/libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp b/libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp new file mode 100644 index 00000000..ac170272 --- /dev/null +++ b/libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp @@ -0,0 +1,4 @@ + + + STRING + diff --git a/libcontextsubscriber/customer-tests/testplugins/timeplugin1/time1.context b/libcontextsubscriber/customer-tests/testplugins/timeplugin1/time1.context deleted file mode 100644 index 33c9d20d..00000000 --- a/libcontextsubscriber/customer-tests/testplugins/timeplugin1/time1.context +++ /dev/null @@ -1,4 +0,0 @@ - - - STRING - diff --git a/libcontextsubscriber/customer-tests/testplugins/timeplugin2/time2.context b/libcontextsubscriber/customer-tests/testplugins/timeplugin2/time2.context deleted file mode 100644 index ac170272..00000000 --- a/libcontextsubscriber/customer-tests/testplugins/timeplugin2/time2.context +++ /dev/null @@ -1,4 +0,0 @@ - - - STRING - -- cgit v1.2.3 From 97d436aca10ce605678a85924321cba2bf68b489 Mon Sep 17 00:00:00 2001 From: Marja Hassinen Date: Fri, 11 Sep 2009 13:41:57 +0300 Subject: .gitignore --- libcontextsubscriber/customer-tests/testplugins/timeplugin1/.gitignore | 2 ++ libcontextsubscriber/customer-tests/testplugins/timeplugin2/.gitignore | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 libcontextsubscriber/customer-tests/testplugins/timeplugin1/.gitignore create mode 100644 libcontextsubscriber/customer-tests/testplugins/timeplugin2/.gitignore diff --git a/libcontextsubscriber/customer-tests/testplugins/timeplugin1/.gitignore b/libcontextsubscriber/customer-tests/testplugins/timeplugin1/.gitignore new file mode 100644 index 00000000..d79521dc --- /dev/null +++ b/libcontextsubscriber/customer-tests/testplugins/timeplugin1/.gitignore @@ -0,0 +1,2 @@ +timeplugin.cpp +timeplugin.h diff --git a/libcontextsubscriber/customer-tests/testplugins/timeplugin2/.gitignore b/libcontextsubscriber/customer-tests/testplugins/timeplugin2/.gitignore new file mode 100644 index 00000000..d79521dc --- /dev/null +++ b/libcontextsubscriber/customer-tests/testplugins/timeplugin2/.gitignore @@ -0,0 +1,2 @@ +timeplugin.cpp +timeplugin.h -- cgit v1.2.3 From d6acc231d31ca1f7321d6ed11e932b825b168126 Mon Sep 17 00:00:00 2001 From: Marja Hassinen Date: Fri, 11 Sep 2009 13:48:35 +0300 Subject: libcontextsubscriber: Modifying the locking in ContextPropertyInfo so that emitting signals and listeners accessing cached values doesn't create a deadlock. Adding a pluginChanged signal. --- libcontextsubscriber/src/contextpropertyinfo.cpp | 47 +++++++++++++++++------- libcontextsubscriber/src/contextpropertyinfo.h | 8 ++++ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/libcontextsubscriber/src/contextpropertyinfo.cpp b/libcontextsubscriber/src/contextpropertyinfo.cpp index 1e23f2db..30cfd8b7 100644 --- a/libcontextsubscriber/src/contextpropertyinfo.cpp +++ b/libcontextsubscriber/src/contextpropertyinfo.cpp @@ -303,29 +303,48 @@ void ContextPropertyInfo::onKeyDataChanged(const QString& key) if (key != keyName) return; + // Update caches and store old values + QString oldType = cachedType; QString newType = InfoBackend::instance()->typeForKey(keyName); - if (cachedType != newType) { + cachedType = newType; - if (cachedType == "") + cachedDoc = InfoBackend::instance()->docForKey(keyName); + + QString oldPlugin = cachedPlugin; + QString oldConstructionString = cachedConstructionString; + QString newPlugin = InfoBackend::instance()->pluginForKey(keyName); + QString newConstructionString = InfoBackend::instance()->constructionStringForKey(keyName); + cachedPlugin = newPlugin; + cachedConstructionString = newConstructionString; + + // Release the lock before emitting the signals; otherwise + // listeners trying to access cached values would create a + // deadlock. + lock.unlock(); + + // Emit the needed signals + if (oldType != newType) { + + if (oldType == "") emit existsChanged(true); if (newType == "") emit existsChanged(false); - cachedType = newType; emit typeChanged(cachedType); } - cachedDoc = InfoBackend::instance()->docForKey(keyName); - - // TBD: obsolete the providerChanged signal and add pluginChanged or sth? - QString newPlugin = InfoBackend::instance()->pluginForKey(keyName); - if (cachedPlugin == "contextkit-dbus" || newPlugin == "contextkit-dbus") { - cachedPlugin = newPlugin; - cachedConstructionString = InfoBackend::instance()->constructionStringForKey(keyName); - QString newProvider = ""; - if (newPlugin == "contextkit-dbus") { - newProvider = cachedConstructionString.split(":").last(); + // TBD: obsolete the providerChanged & providerDBusTypeChanged signals? + if (oldPlugin != newPlugin || oldConstructionString != newConstructionString) { + if (oldPlugin == "contextkit-dbus" || newPlugin == "contextkit-dbus") { + QString newProvider = ""; + if (newPlugin == "contextkit-dbus") { + newProvider = cachedConstructionString.split(":").last(); + } + emit providerChanged(newProvider); + // Note: we don't emit providerDBusTypeChanged any + // more. It would be cumbersome, and there's no real use + // case for listening to it. } - emit providerChanged(newProvider); + emit pluginChanged(newPlugin, newConstructionString); } } diff --git a/libcontextsubscriber/src/contextpropertyinfo.h b/libcontextsubscriber/src/contextpropertyinfo.h index 3ba6b255..e83aebb9 100644 --- a/libcontextsubscriber/src/contextpropertyinfo.h +++ b/libcontextsubscriber/src/contextpropertyinfo.h @@ -85,6 +85,14 @@ signals: /// signal you can wait (watch) for various keys to become available. /// \param exists The new state of the key. void existsChanged(bool exists); + + /// Emitted when the libcontextsubscriber plugin providing the key + /// changes, or the construction parameter to give to the plugin + /// changes.. The \a plugin is the name of the new plugin + /// providing the key and the \a constructionString is the new + /// construction parameter to give to the plugin. + void pluginChanged(QString plugin, QString constructionString); + }; #endif // CONTEXTPROPERTYINFO_H -- cgit v1.2.3 From 317756832757a87dc0ee85b3ea1c040a83648c47 Mon Sep 17 00:00:00 2001 From: Marja Hassinen Date: Fri, 11 Sep 2009 13:50:05 +0300 Subject: libcontextsubscriber: logging additions --- libcontextsubscriber/src/loggingfeatures.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libcontextsubscriber/src/loggingfeatures.h b/libcontextsubscriber/src/loggingfeatures.h index 86f71c25..05a0d276 100644 --- a/libcontextsubscriber/src/loggingfeatures.h +++ b/libcontextsubscriber/src/loggingfeatures.h @@ -26,5 +26,6 @@ #define F_XML (ContextFeature("xml")) #define F_CDB (ContextFeature("cdb")) #define F_DESTROY (ContextFeature("destroy")) +#define F_PLUGINS (ContextFeature("plugins")) #endif -- cgit v1.2.3 From ddfa69b8e9fdc8256025d08e1e4cd197884c9e7d Mon Sep 17 00:00:00 2001 From: Marja Hassinen Date: Fri, 11 Sep 2009 13:58:56 +0300 Subject: libcontextsubscriber: PropertyHandle listening to ContextPropertyInfo signals to determine when it needs to update its provider information. This way the caches of ContextPropertyInfo are up to date when PropertyHandle is notified. --- libcontextsubscriber/src/propertyhandle.cpp | 13 ++++++++++--- .../unit-tests/propertyhandle/contextpropertyinfo.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/libcontextsubscriber/src/propertyhandle.cpp b/libcontextsubscriber/src/propertyhandle.cpp index f1592659..cef5c406 100644 --- a/libcontextsubscriber/src/propertyhandle.cpp +++ b/libcontextsubscriber/src/propertyhandle.cpp @@ -83,6 +83,12 @@ PropertyHandle::PropertyHandle(const QString& key) // done before calling updateProvider. myInfo = new ContextPropertyInfo(myKey, this); + // Start listening to changes in property introspection (e.g., added to registry, plugin changes) + sconnect(myInfo, SIGNAL(existsChanged(bool)), + this, SLOT(updateProvider())); + sconnect(myInfo, SIGNAL(pluginChanged(QString, QString)), + this, SLOT(updateProvider())); + // Start listening for the context commander, and also initiate a // NameHasOwner check. @@ -103,9 +109,6 @@ PropertyHandle::PropertyHandle(const QString& key) // Otherwise, delay connecting to the provider until we know // whether commander is present. - // Start listening to changes in property registry (e.g., new keys, keys removed) - sconnect(ContextRegistryInfo::instance(), SIGNAL(keysChanged(const QStringList&)), - this, SLOT(updateProvider())); // Move the PropertyHandle (and all children) to main thread. moveToThread(QCoreApplication::instance()->thread()); @@ -127,6 +130,7 @@ void PropertyHandle::setTypeCheck(bool typeCheck) void PropertyHandle::updateProvider() { Provider *newProvider; + contextDebug() << F_PLUGINS; if (commandingEnabled && commanderListener->isServicePresent() == DBusNameListener::Present) { // If commander is present it should be able to override the @@ -139,6 +143,7 @@ void PropertyHandle::updateProvider() if (myInfo->exists()) { // If myInfo knows the current provider which should be // connected to, connect to it. + contextDebug() << F_PLUGINS << "Key exists"; newProvider = Provider::instance(myInfo->plugin(), myInfo->constructionString()); } else { @@ -146,6 +151,8 @@ void PropertyHandle::updateProvider() // This way, we can still continue communicating with the // provider even though the key is no longer in the // registry. + contextDebug() << F_PLUGINS << "Key doesn't exist -> keep old provider info"; + newProvider = myProvider; if (newProvider == 0) { diff --git a/libcontextsubscriber/unit-tests/propertyhandle/contextpropertyinfo.h b/libcontextsubscriber/unit-tests/propertyhandle/contextpropertyinfo.h index a53f6d46..61cdcb45 100644 --- a/libcontextsubscriber/unit-tests/propertyhandle/contextpropertyinfo.h +++ b/libcontextsubscriber/unit-tests/propertyhandle/contextpropertyinfo.h @@ -50,6 +50,7 @@ signals: void providerDBusTypeChanged(QDBusConnection::BusType newBusType); void typeChanged(QString newType); void existsChanged(bool exists); + void pluginChanged(QString, QString); public: // For the test program -- cgit v1.2.3 From a7b641122cae7077de844c9831111ff784304c2e Mon Sep 17 00:00:00 2001 From: Marja Hassinen Date: Fri, 11 Sep 2009 14:24:47 +0300 Subject: libcontextsubscriber plugins: Adding a customer test for plugins: changing the plugin which provides a property. --- .../pluginchanging/pluginchanging.py | 82 ++++++++++++++++++++++ libcontextsubscriber/customer-tests/runTests.sh | 4 +- 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py diff --git a/libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py b/libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py new file mode 100644 index 00000000..b564db52 --- /dev/null +++ b/libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +## +## This file is part of ContextKit. +## +## Copyright (C) 2009 Nokia. All rights reserved. +## +## Contact: Marius Vollmer +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public License +## version 2.1 as published by the Free Software Foundation. +## +## This library is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +## 02110-1301 USA +## +## +## Requires python2.5-gobject and python2.5-dbus +## +import sys +import unittest +import os +import string +from subprocess import Popen, PIPE +import time +import signal + +def proc_kill(pid): + os.system('../common/rec-kill.sh %d' % pid) + +def timeoutHandler(signum, frame): + raise Exception('tests has been running for too long') + +def stdoutRead (object,lines): + list = [] + for i in range(lines): + list.append(object.stdout.readline().rstrip()) + return list + +class Subscription(unittest.TestCase): + + def setUp(self): + os.environ["CONTEXT_PROVIDERS"] = "." + + self.context_client = Popen(["context-listen","Test.Time"],stdin=PIPE,stdout=PIPE,stderr=PIPE) + + def tearDown(self): + proc_kill(self.context_client.pid) + os.remove('time.context') + + def testChangingPlugin(self): + + # Copy the declaration file, declaring libcontextsubscribertime1 plugin. + os.system('cp time1.context.temp time.context.temp') + os.system('mv time.context.temp time.context') + actual = self.context_client.stdout.readline().rstrip() + + # The client got a value provided by the libcontextsubscribertime1 + self.assertEqual(actual.startswith("Test.Time = QString:Time1: "), True, "Got: %s" % actual) + + # Modify the registry so that the key is now provided by libcontextsubscribertime2 + os.system('cp time2.context.temp time.context.temp') + os.system('mv time.context.temp time.context') + + # Assert that the client starts getting the value from the correct plugin + # (not necessarily the first one) + actual = self.context_client.stdout.readline().rstrip() + actual = self.context_client.stdout.readline().rstrip() + + self.assertEqual(actual.startswith("Test.Time = QString:Time2: "), True, "Got: %s" % actual) + +if __name__ == "__main__": + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1) + signal.signal(signal.SIGALRM, timeoutHandler) + signal.alarm(30) + unittest.main() diff --git a/libcontextsubscriber/customer-tests/runTests.sh b/libcontextsubscriber/customer-tests/runTests.sh index a901888b..f0ba2042 100755 --- a/libcontextsubscriber/customer-tests/runTests.sh +++ b/libcontextsubscriber/customer-tests/runTests.sh @@ -1,11 +1,11 @@ #!/bin/bash -DIRS="commander subscription asynchronicity registry bluez-plugin2" +DIRS="commander subscription asynchronicity registry bluez-plugin2 pluginchanging" if pkg-config contextprovider-1.0 || [ -e ../../libcontextprovider/src/.libs/libcontextprovider.so ] then export CONTEXT_PROVIDERS=. - export LD_LIBRARY_PATH=../../src/.libs:../../plugins/bluez/.libs:../../../libcontextprovider/src/.libs + export LD_LIBRARY_PATH=../../src/.libs:../../plugins/bluez/.libs:../../../libcontextprovider/src/.libs:../testplugins/timeplugin1/.libs:../testplugins/timeplugin2/.libs export PATH=$PATH:../../../python:../../cli:../../reg-cli for dir in $DIRS; do -- cgit v1.2.3