[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [KSecretService] 982ccc8: Adapt the non-blocking collection test for
From:       Michael Leupold <lemma () confuego ! org>
Date:       2010-11-09 19:14:24
Message-ID: 20101109191424.7ACECA60CD () git ! kde ! org
[Download RAW message or body]

commit 982ccc8f5ec1d8d38b03964e9cf6775e96ff7338
branch master
Author: Michael Leupold <lemma@confuego.org>
Date:   Fri May 7 05:02:42 2010 +0000

    Adapt the non-blocking collection test for blocking collections using a prompt. \
Test dismissing and prompting prompts. Fix bugs while doing so.  
    CCMAIL: dario.freddi@collabora.co.uk
    
    svn path=/trunk/playground/base/ksecretservice/; revision=1123851

diff --git a/backend/backendmaster.cpp b/backend/backendmaster.cpp
index 9eb304d..56db545 100644
--- a/backend/backendmaster.cpp
+++ b/backend/backendmaster.cpp
@@ -43,6 +43,15 @@ void BackendMaster::addManager(BackendCollectionManager *manager)
    m_collectionManagers.append(manager);
 }
 
+void BackendMaster::removeManager(BackendCollectionManager *manager)
+{
+   manager->disconnect(SIGNAL(collectionCreated(BackendCollection*)), this,
+                       SLOT(slotCollectionCreated(BackendCollection*)));
+   manager->disconnect(SIGNAL(collectionDeleted(BackendCollection*)), this,
+                       SLOT(slotCollectionDeleted(BackendCollection*)));
+   m_collectionManagers.removeAll(manager);
+}
+
 const QList<BackendCollection*> &BackendMaster::collections() const
 {
    return m_collections;
@@ -51,7 +60,7 @@ const QList<BackendCollection*> &BackendMaster::collections() const
 bool BackendMaster::isCallImmediate(AsyncCall::AsyncType type) const
 {
    switch (type) {
-   case AsyncCall::AsyncCreateCollection:
+     case AsyncCall::AsyncCreateCollectionMaster:
       // create collection will be immediate if the list of managers
       // contains only a single manager which can process the call
       // immediately. for all other cases the user needs to choose
@@ -94,7 +103,7 @@ BackendReturn<BackendCollection*> \
                BackendMaster::createCollection(const QString
       // call has to be queued. use an eventloop for waiting for its return.
       QEventLoop loop;
       AsyncCreateCollection *call = new AsyncCreateCollection(label, locked, \
                manager);
-      connect(call, SIGNAL(completed()), &loop, SLOT(quit()));
+      connect(call, SIGNAL(completed(AsyncCall*, bool)), &loop, SLOT(quit()));
       call->enqueue();
       loop.exec();
 
diff --git a/backend/backendmaster.h b/backend/backendmaster.h
index 3ae8dca..384d786 100644
--- a/backend/backendmaster.h
+++ b/backend/backendmaster.h
@@ -68,6 +68,13 @@ public:
    void addManager(BackendCollectionManager *manager);
 
    /**
+    * Remove a collection manager from the list of known managers.
+    *
+    * @param manager collection manager to remove
+    */
+   void removeManager(BackendCollectionManager *manager);
+
+   /**
     * Get the list of known collections.
     *
     * @return The list of known collections
diff --git a/daemon/dbus/promptadaptor.cpp b/daemon/dbus/promptadaptor.cpp
index a01cd9e..44ddda3 100644
--- a/daemon/dbus/promptadaptor.cpp
+++ b/daemon/dbus/promptadaptor.cpp
@@ -29,7 +29,7 @@ PromptAdaptor::PromptAdaptor(PromptBase *prompt)
 {
    Q_ASSERT(prompt);
 
-   connect(prompt, SIGNAL(completed(bool, QVariant)), SIGNAL(Completed(bool, \
QVariant))); +   connect(prompt, SIGNAL(completed(bool, QVariant)), \
SLOT(slotCompleted(bool, QVariant)));  }
 
 void PromptAdaptor::Prompt(const QString &windowId)
@@ -42,6 +42,11 @@ void PromptAdaptor::Dismiss()
    m_prompt->dismiss();
 }
 
+void PromptAdaptor::slotCompleted(bool dismissed, const QVariant &result)
+{
+   emit Completed(dismissed, QDBusVariant(result));
+}
+
 }
 
 #include "promptadaptor.moc"
diff --git a/daemon/dbus/promptadaptor.h b/daemon/dbus/promptadaptor.h
index 12f12f9..8338eca 100644
--- a/daemon/dbus/promptadaptor.h
+++ b/daemon/dbus/promptadaptor.h
@@ -50,8 +50,11 @@ public Q_SLOTS:
    void Dismiss();
 
 Q_SIGNALS:
-   void Completed(bool dismissed, QVariant result);
+   void Completed(bool dismissed, QDBusVariant result);
 
+private Q_SLOTS:
+   void slotCompleted(bool dismissed, const QVariant &result);
+   
 private:
    PromptBase *m_prompt;
 };
diff --git a/daemon/prompt.cpp b/daemon/prompt.cpp
index 6c2730f..9c3e21b 100644
--- a/daemon/prompt.cpp
+++ b/daemon/prompt.cpp
@@ -93,7 +93,7 @@ void PromptBase::slotCompleted(AsyncCall *call, bool dismissed)
 
    // TODO: handle errors
    if (dismissed) {
-      emit completed(true, QVariant());
+      emit completed(true, QVariant(""));
    } else {
       emit completed(false, getResult());
    }
diff --git a/daemon/tests/CMakeLists.txt b/daemon/tests/CMakeLists.txt
index 0ded7b4..a776797 100644
--- a/daemon/tests/CMakeLists.txt
+++ b/daemon/tests/CMakeLists.txt
@@ -7,7 +7,12 @@ INCLUDE_DIRECTORIES (
    ${CMAKE_CURRENT_BINARY_DIR}
 )
 
-KDE4_ADD_EXECUTABLE (ksecretservice_daemon_test servicetest.cpp)
+KDE4_ADD_EXECUTABLE (ksecretservice_daemon_test
+   servicetest.cpp
+   tempblockingcollectionmanager.cpp
+   tempblockingcollection.cpp
+   tempblockingitem.cpp
+)
 TARGET_LINK_LIBRARIES (ksecretservice_daemon_test
    ksecretservicebackend
    ksecretservicedaemon
diff --git a/daemon/tests/servicetest.cpp b/daemon/tests/servicetest.cpp
index 8e1942d..cc4b110 100644
--- a/daemon/tests/servicetest.cpp
+++ b/daemon/tests/servicetest.cpp
@@ -22,6 +22,7 @@
 
 #include "backend/backendmaster.h"
 #include "backend/temporarycollectionmanager.h"
+#include "tempblockingcollectionmanager.h"
 #include "daemon/service.h"
 #include "daemon/dbus/dbustypes.h"
 
@@ -44,7 +45,8 @@ void ServiceTest::initTestCase()
    QCA::init();
    
    m_master = new BackendMaster;
-   m_master->addManager(new TemporaryCollectionManager(m_master));
+   m_tempCollMan = new TemporaryCollectionManager(m_master);
+   m_master->addManager(m_tempCollMan);
    m_service = new Service(m_master);
 }
 
@@ -213,7 +215,7 @@ void ServiceTest::nonBlockingCollection()
    
    // make sure the CollectionChanged signal was sent
    if (changedSpy.size() < 1) {
-      changedSpy.waitForSignal(1);
+      changedSpy.waitForSignal(5000);
    }
    QCOMPARE(changedSpy.size(), 1);
    QCOMPARE(changedSpy.takeFirst(), collectionPath);
@@ -418,6 +420,188 @@ void ServiceTest::nonBlockingItem()
    QDBusInterface("org.freedesktop.Secret", sessionPath.path()).call("Close");
 }
 
+void ServiceTest::reInitTestCase()
+{
+   // remove the TemporaryCollectionManager and replace it with a \
TempBlockingCollectionManager +   m_master->removeManager(m_tempCollMan);
+   delete m_tempCollMan;
+   m_tempBlockCollMan = new TempBlockingCollectionManager(m_master);
+   m_master->addManager(m_tempBlockCollMan);
+}
+
+void ServiceTest::blockingCollection()
+{
+   ClientPrompt *prompt = 0;
+   
+   QDBusInterface ifaceService("org.freedesktop.Secret", \
"/org/freedesktop/secrets"); +   QVERIFY(ifaceService.isValid());
+
+   // create a session
+   // create a session
+   QDBusObjectPath sessionPath;
+   QList<QVariant> sessionInput;
+   sessionInput << QString("plain") << QVariant::fromValue(QDBusVariant(""));
+   QDBusMessage sessionReply = ifaceService.callWithArgumentList(QDBus::Block, \
"OpenSession", +                                                                 \
sessionInput); +   sessionPath = \
sessionReply.arguments().at(1).value<QDBusObjectPath>(); +
+   // listen to CollectionCreated/CollectionDeleted/CollectionChanged signals
+   ObjectPathSignalSpy createdSpy(&ifaceService, \
SIGNAL(CollectionCreated(QDBusObjectPath))); +   QVERIFY(createdSpy.isValid());
+   ObjectPathSignalSpy deletedSpy(&ifaceService, \
SIGNAL(CollectionDeleted(QDBusObjectPath))); +   QVERIFY(deletedSpy.isValid());
+   ObjectPathSignalSpy changedSpy(&ifaceService, \
SIGNAL(CollectionChanged(QDBusObjectPath))); +   QVERIFY(changedSpy.isValid());
+
+   // create a collection
+   QDBusObjectPath promptPath;
+   QMap<QString, QVariant> createProperties;
+   QList<QVariant> createInput;
+   createProperties["Label"] = "test";
+   createProperties["Locked"] = false; // create collection unlocked
+   createInput << QVariant::fromValue(createProperties);
+   QDBusMessage createReply = ifaceService.callWithArgumentList(QDBus::Block, \
"CreateCollection", +                                                                \
createInput); +   QCOMPARE(createReply.type(), QDBusMessage::ReplyMessage);
+   QList<QVariant> createArgs = createReply.arguments();
+   QCOMPARE(createArgs.size(), 2);
+   QCOMPARE(createArgs.at(0).userType(), qMetaTypeId<QDBusObjectPath>());
+   QCOMPARE(createArgs.at(1).userType(), qMetaTypeId<QDBusObjectPath>());
+   // TempBlockingCollection is blocking, so the first output (path) should be "/".
+   QCOMPARE(createArgs.at(0).value<QDBusObjectPath>().path(), QLatin1String("/"));
+   promptPath = createArgs.at(1).value<QDBusObjectPath>();
+   QVERIFY(promptPath.path().startsWith(
+           QLatin1String("/org/freedesktop/secrets/prompts/")));
+
+   // dismiss the prompt and wait for the result.
+   prompt = new ClientPrompt(promptPath);
+   prompt->dismissAndWait(5000);
+   QVERIFY(prompt->completed());
+   QVERIFY(prompt->dismissed());
+   delete prompt;
+
+   createReply = ifaceService.callWithArgumentList(QDBus::Block, "CreateCollection",
+                                                   createInput);
+   QCOMPARE(createReply.type(), QDBusMessage::ReplyMessage);
+   createArgs = createReply.arguments();
+   QCOMPARE(createArgs.size(), 2);
+   QCOMPARE(createArgs.at(0).userType(), qMetaTypeId<QDBusObjectPath>());
+   QCOMPARE(createArgs.at(1).userType(), qMetaTypeId<QDBusObjectPath>());
+   // TempBlockingCollection is blocking, so the first output (path) should be "/".
+   QCOMPARE(createArgs.at(0).value<QDBusObjectPath>().path(), QLatin1String("/"));
+   promptPath = createArgs.at(1).value<QDBusObjectPath>();
+   QVERIFY(promptPath.path().startsWith(
+           QLatin1String("/org/freedesktop/secrets/prompts/")));
+
+   // prompt and wait for the result.
+   prompt = new ClientPrompt(promptPath);
+   prompt->promptAndWait(5000);
+   QVERIFY(prompt->completed());
+   QVERIFY(!prompt->dismissed());
+   QCOMPARE(prompt->result().userType(), qMetaTypeId<QDBusObjectPath>());
+   QDBusObjectPath collectionPath = prompt->result().value<QDBusObjectPath>();
+   QVERIFY(collectionPath.path().startsWith(
+           QLatin1String("/org/freedesktop/secrets/collection/")));
+   QDBusInterface ifaceCollection("org.freedesktop.Secret", collectionPath.path(),
+                                  "org.freedesktop.Secret.Collection");
+   QVERIFY(ifaceCollection.isValid());
+   delete prompt;
+
+   // make sure the CollectionCreated signal was sent
+   if (createdSpy.size() < 1) {
+      createdSpy.waitForSignal(5000);
+   }
+   QCOMPARE(createdSpy.size(), 1);
+   QCOMPARE(createdSpy.takeFirst(), collectionPath);
+
+   // read collection properties
+   QVariant propItems = ifaceCollection.property("Items");
+   QVERIFY(propItems.isValid());
+   QVERIFY(propItems.canConvert<QList<QDBusObjectPath> >());
+   QList<QDBusObjectPath> propItemsList = propItems.value<QList<QDBusObjectPath> \
>(); +   QVERIFY(propItemsList.isEmpty());
+   QVariant propLabel = ifaceCollection.property("Label");
+   QVERIFY(propLabel.isValid());
+   QCOMPARE(propLabel.type(), QVariant::String);
+   QCOMPARE(propLabel.value<QString>(), QString("test"));
+   QVariant propLocked = ifaceCollection.property("Locked");
+   QVERIFY(propLocked.isValid());
+   QCOMPARE(propLocked.value<bool>(), false);
+   QVariant propCreated = ifaceCollection.property("Created");
+   QVERIFY(propCreated.isValid());
+   QCOMPARE(propCreated.type(), QVariant::ULongLong);
+   qulonglong propCreatedUll = propCreated.value<qulonglong>();
+   QVERIFY(QDateTime::currentDateTime().toTime_t() - propCreatedUll < 60);
+   QVariant propModified = ifaceCollection.property("Modified");
+   QVERIFY(propModified.isValid());
+   QCOMPARE(propModified.type(), QVariant::ULongLong);
+   QCOMPARE(propModified.value<qulonglong>(), propCreatedUll);
+
+   // set the label and re-read it.
+   ifaceCollection.setProperty("Label", QString("test2"));
+   propLabel = ifaceCollection.property("Label");
+   QVERIFY(propLabel.isValid());
+   QCOMPARE(propLabel.type(), QVariant::String);
+   QCOMPARE(propLabel.value<QString>(), QString("test2"));
+
+   // make sure the CollectionChanged signal was sent
+   if (changedSpy.size() < 1) {
+      changedSpy.waitForSignal(5000);
+   }
+   QCOMPARE(changedSpy.size(), 1);
+   QCOMPARE(changedSpy.takeFirst(), collectionPath);
+
+   // delete the collection
+   QDBusMessage deleteReply = ifaceCollection.call(QDBus::Block, "Delete");
+   QCOMPARE(deleteReply.type(), QDBusMessage::ReplyMessage);
+   QList<QVariant> deleteArgs = deleteReply.arguments();
+   QCOMPARE(deleteArgs.size(), 1);
+   QCOMPARE(deleteArgs.at(0).userType(), qMetaTypeId<QDBusObjectPath>());
+   // TempBlockingCollection is blocking, so the output (prompt) should be a valid \
one. +   promptPath = deleteArgs.at(0).value<QDBusObjectPath>();
+   QVERIFY(promptPath.path().startsWith(QLatin1String("/org/freedesktop/secrets/prompts/")));
 +
+   // dismiss the prompt and wait for the result.
+   prompt = new ClientPrompt(promptPath);
+   prompt->dismissAndWait(5000);
+   QVERIFY(prompt->completed());
+   QVERIFY(prompt->dismissed());
+   delete prompt;
+
+   // retry and complete the prompt this time
+   deleteReply = ifaceCollection.call(QDBus::Block, "Delete");
+   QCOMPARE(deleteReply.type(), QDBusMessage::ReplyMessage);
+   deleteArgs = deleteReply.arguments();
+   QCOMPARE(deleteArgs.size(), 1);
+   QCOMPARE(deleteArgs.at(0).userType(), qMetaTypeId<QDBusObjectPath>());
+   // TempBlockingCollection is blocking, so the output (prompt) should be a valid \
one. +   promptPath = deleteArgs.at(0).value<QDBusObjectPath>();
+   QVERIFY(promptPath.path().startsWith(QLatin1String("/org/freedesktop/secrets/prompts/")));
 +   prompt = new ClientPrompt(promptPath);
+   prompt->promptAndWait(5000);
+   QVERIFY(prompt->completed());
+   QVERIFY(!prompt->dismissed());
+   delete prompt;
+
+   // make sure the collection is gone
+   QCOMPARE(ifaceCollection.call("Introspect").type(), QDBusMessage::ErrorMessage);
+
+   // make sure the CollectionDeleted signal was sent
+   if (deletedSpy.size() < 1) {
+      deletedSpy.waitForSignal(5000);
+   }
+   QCOMPARE(deletedSpy.size(), 1);
+   QCOMPARE(deletedSpy.takeFirst(), collectionPath);
+
+   // close the session
+   QDBusInterface("org.freedesktop.Secret", sessionPath.path()).call("Close");
+}
+
+void ServiceTest::blockingItem()
+{
+   // TODO: test
+}
+
 void ServiceTest::cleanupTestCase()
 {
    delete m_service;
@@ -464,4 +648,43 @@ void ObjectPathSignalSpy::slotReceived(const QDBusObjectPath \
&objectPath)  }
 }
 
+ClientPrompt::ClientPrompt(QDBusObjectPath promptPath)
+ : m_completed(false), m_dismissed(false),
+   m_interface("org.freedesktop.Secret", promptPath.path())
+{
+   Q_ASSERT(m_interface.isValid());
+   connect(&m_interface, SIGNAL(Completed(bool, QDBusVariant)),
+                         SLOT(slotCompleted(bool, QDBusVariant)));
+}
+
+void ClientPrompt::promptAndWait(int time)
+{
+   QDBusMessage reply = m_interface.call(QDBus::Block, "Prompt", QString(""));
+   Q_ASSERT(reply.type() == QDBusMessage::ReplyMessage);
+   justWait(time);
+}
+
+void ClientPrompt::dismissAndWait(int time)
+{
+   QDBusMessage reply = m_interface.call(QDBus::Block, "Dismiss");
+   Q_ASSERT(reply.type() == QDBusMessage::ReplyMessage);
+   justWait(time);
+}
+
+void ClientPrompt::slotCompleted(bool dismissed, const QDBusVariant &result)
+{
+   m_completed = true;
+   m_dismissed = dismissed;
+   m_result = result.variant();
+   m_loop.quit();
+}
+
+void ClientPrompt::justWait(int time)
+{
+   if (time > 0) {
+      QTimer::singleShot(time, &m_loop, SLOT(quit()));
+   }
+   m_loop.exec();
+}
+
 #include "servicetest.moc"
diff --git a/daemon/tests/servicetest.h b/daemon/tests/servicetest.h
index 8320c0c..4f9dbb3 100644
--- a/daemon/tests/servicetest.h
+++ b/daemon/tests/servicetest.h
@@ -23,11 +23,16 @@
 
 #include <QtCore/QObject>
 #include <QtCore/QList>
+#include <QtCore/QVariant>
+#include <QtCore/QEventLoop>
+#include <QtDBus/QDBusVariant>
 #include <QtDBus/QDBusObjectPath>
+#include <QtDBus/QDBusInterface>
 
 class BackendMaster;
+class TemporaryCollectionManager;
+class TempBlockingCollectionManager;
 class Service;
-class QDBusInterface;
 class QDBusAbstractInterface;
 
 /**
@@ -39,6 +44,8 @@ class ServiceTest : public QObject
 
 private:
    BackendMaster *m_master;
+   TemporaryCollectionManager *m_tempCollMan;
+   TempBlockingCollectionManager *m_tempBlockCollMan;
    Service *m_service;
 
 private Q_SLOTS:
@@ -57,6 +64,15 @@ private Q_SLOTS:
    // create and remove items
    void nonBlockingItem();
 
+   // change some of the parameters of the testcase needed for the tests to come
+   void reInitTestCase();
+   
+   // create and remove blocking collections
+   void blockingCollection();
+
+   // create and remove blocking items
+   void blockingItem();
+
    // cleanup
    void cleanupTestCase();
 };
@@ -95,4 +111,52 @@ private:
    int m_numWaiting;
 };
 
+/**
+ * Client mini-stub for org.freedesktop.Secret.Prompt.
+ */
+class ClientPrompt : public QObject
+{
+   Q_OBJECT
+
+public:
+   // constructor. wraps around the prompt at promptPath.
+   ClientPrompt(QDBusObjectPath promptPath);
+
+   // Call the Prompt method and wait some time for completion
+   // (sends bogus window-id)
+   void promptAndWait(int time);
+
+   // Call the Dismiss method and wait some time for completion
+   void dismissAndWait(int time);
+
+   // check if the call has been completed
+   bool completed() const {
+      return m_completed;
+   }
+
+   // check if the call was dismissed
+   bool dismissed() const {
+      return m_dismissed;
+   }
+
+   // get the call's result
+   const QVariant &result() const {
+      return m_result;
+   }
+
+private Q_SLOTS:
+   // listens for Completed signals of the D-Bus prompt.
+   void slotCompleted(bool dismissed, const QDBusVariant &result);
+
+private:
+   // just wait (called by *AndWait methods)
+   void justWait(int time);
+   
+   bool m_completed;
+   bool m_dismissed;
+   QVariant m_result;
+   QDBusInterface m_interface;
+   QEventLoop m_loop;
+};
+
 #endif


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic