diff options
author | Gergely Risko <gergely+context@risko.hu> | 2009-09-11 15:01:28 +0300 |
---|---|---|
committer | Gergely Risko <gergely+context@risko.hu> | 2009-09-11 15:01:28 +0300 |
commit | 39e0bb33b4e37d254aa43e11115dd918e47c469b (patch) | |
tree | 77ea2c7cb70d2700c07d915f9bf31e2b96dbb047 | |
parent | 1e90445d3293699df4160d9d1820144422d795be (diff) | |
parent | a7b641122cae7077de844c9831111ff784304c2e (diff) |
Merge branch 'bluez-plugin' of git@gitorious.org:maemo-af/contextkit into bluez-plugin
-rw-r--r-- | libcontextsubscriber/customer-tests/pluginchanging/pluginchanging.py | 82 | ||||
-rw-r--r-- | libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp (renamed from libcontextsubscriber/customer-tests/testplugins/timeplugin1/time1.context) | 0 | ||||
-rw-r--r-- | libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp (renamed from libcontextsubscriber/customer-tests/testplugins/timeplugin2/time2.context) | 0 | ||||
-rwxr-xr-x | libcontextsubscriber/customer-tests/runTests.sh | 4 | ||||
-rw-r--r-- | libcontextsubscriber/customer-tests/testplugins/timeplugin1/.gitignore | 2 | ||||
-rw-r--r-- | libcontextsubscriber/customer-tests/testplugins/timeplugin2/.gitignore | 2 | ||||
-rw-r--r-- | libcontextsubscriber/src/contextpropertyinfo.cpp | 47 | ||||
-rw-r--r-- | libcontextsubscriber/src/contextpropertyinfo.h | 8 | ||||
-rw-r--r-- | libcontextsubscriber/src/loggingfeatures.h | 1 | ||||
-rw-r--r-- | libcontextsubscriber/src/propertyhandle.cpp | 13 | ||||
-rw-r--r-- | libcontextsubscriber/unit-tests/propertyhandle/contextpropertyinfo.h | 1 |
11 files changed, 141 insertions, 19 deletions
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 <marius.vollmer@nokia.com> +## +## 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/testplugins/timeplugin1/time1.context b/libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp index 33c9d20d..33c9d20d 100644 --- a/libcontextsubscriber/customer-tests/testplugins/timeplugin1/time1.context +++ b/libcontextsubscriber/customer-tests/pluginchanging/time1.context.temp diff --git a/libcontextsubscriber/customer-tests/testplugins/timeplugin2/time2.context b/libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp index ac170272..ac170272 100644 --- a/libcontextsubscriber/customer-tests/testplugins/timeplugin2/time2.context +++ b/libcontextsubscriber/customer-tests/pluginchanging/time2.context.temp 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 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 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 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 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 |