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

List:       kde-commits
Subject:    [ksecrets] /: Adding the ksecrets_store tests
From:       Valentin Rusu <kde () rusu ! info>
Date:       2015-08-13 15:47:31
Message-ID: E1ZPuj5-00028K-Ew () scm ! kde ! org
[Download RAW message or body]

Git commit 92288f8c476933dfb7d5e37f753c801564c74ea9 by Valentin Rusu.
Committed on 13/08/2015 at 15:47.
Pushed by vrusu into branch 'master'.

Adding the ksecrets_store tests

All now set for secrets store development

M  +302  -16   autotests/ksecrets_store/ksecrets_store_test.cpp
M  +7    -2    autotests/ksecrets_store/ksecrets_store_test.h
M  +1    -0    src/runtime/ksecrets_store/ksecrets_credentials.cpp
M  +91   -0    src/runtime/ksecrets_store/ksecrets_store.cpp
M  +42   -16   src/runtime/ksecrets_store/ksecrets_store.h

http://commits.kde.org/ksecrets/92288f8c476933dfb7d5e37f753c801564c74ea9

diff --git a/autotests/ksecrets_store/ksecrets_store_test.cpp \
b/autotests/ksecrets_store/ksecrets_store_test.cpp index 1a27431..821699e 100644
--- a/autotests/ksecrets_store/ksecrets_store_test.cpp
+++ b/autotests/ksecrets_store/ksecrets_store_test.cpp
@@ -54,22 +54,308 @@ void KSecretServiceStoreTest::initTestCase()
     QVERIFY(credfut.get());
 }
 
-void KSecretServiceStoreTest::testCreateCollection() { QVERIFY(false); }
-void KSecretServiceStoreTest::testCreateItem() { QVERIFY(false); }
-void KSecretServiceStoreTest::testSearchItem() { QVERIFY(false); }
-void KSecretServiceStoreTest::testItem() { QVERIFY(false); }
-void KSecretServiceStoreTest::testDeleteItem() { QVERIFY(false); }
-void KSecretServiceStoreTest::testDirCollections() { QVERIFY(false); }
-void KSecretServiceStoreTest::testReadCollection() { QVERIFY(false); }
-void KSecretServiceStoreTest::testDeleteCollection() { QVERIFY(false); }
-void KSecretServiceStoreTest::cleanupTestCase() { QDir::home().remove(secretsFilePath); }
+static const char* collName1 = "test collection1";
+static const char* collName2 = "test collection2";
+std::time_t createTimeMark;
+
+void KSecretServiceStoreTest::testCreateCollection()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData(), false);
+
+    createTimeMark = std::time(nullptr);
+    auto crval1 = backend.createCollection(collName1);
+    QVERIFY(crval1);
+
+    auto crval2 = backend.createCollection(collName2);
+    QVERIFY(crval2);
+
+    auto crval3 = backend.createCollection(collName1);
+    QVERIFY(!crval3); // should not work as a collection named collName1 is already present
+
+    auto coll2 = crval2.result_;
+    QVERIFY(coll2.get() != nullptr);
+    QVERIFY(coll2->createdTime() > createTimeMark);
+    QVERIFY(coll2->modifiedTime() > createTimeMark);
+    QVERIFY(coll2->createdTime() == coll2->modifiedTime());
+    QVERIFY(coll2->label() == collName2);
+
+    auto sres = coll2->dirItems();
+    QVERIFY(sres.size() == 0);
+
+    KSecretsStore::AttributesMap noAttrs;
+    sres = coll2->searchItems(noAttrs);
+    QVERIFY(sres.size() == 0);
+
+    sres = coll2->searchItems("", noAttrs);
+    QVERIFY(sres.size() == 0);
+
+    sres = coll2->searchItems(nullptr);
+    QVERIFY(sres.size() == 0);
+
+    sres = coll2->searchItems(nullptr, noAttrs);
+    QVERIFY(sres.size() == 0);
+}
+
+void KSecretServiceStoreTest::testCreateCollectionFailOnReadonly()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData());
+
+    createTimeMark = std::time(nullptr);
+    auto crval1 = backend.createCollection(collName1);
+    QVERIFY(!crval1);
+}
+
+void KSecretServiceStoreTest::testDirCollections()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData(), false);
+
+    auto dirres = backend.dirCollections();
+    QVERIFY(dirres);
+    auto colList = dirres.result_;
+    QVERIFY(colList.size() == 2); // we created two collections at testCreateCollection
+    QVERIFY(colList[0] == collName1);
+    QVERIFY(colList[1] == collName2);
+}
+
+void KSecretServiceStoreTest::testReadCollection()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData());
+
+    auto rres = backend.readCollection(collName2);
+    QVERIFY(rres);
+    auto coll = rres.result_;
+    QVERIFY(coll.get() != nullptr);
+    QVERIFY(coll->label() == collName2);
+}
+
+const char *itemName1 = "item1";
+const char *itemName2 = "item2";
+const char *itemName3 = "item3";
+const char *itemNamesWildcard = "item*";
+KSecretsStore::ItemValue emptyValue;
+
+void KSecretServiceStoreTest::testCreateItem()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData(), false);
+
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll = rres.result_;
+    QVERIFY(coll.get() != nullptr);
+
+    auto sres = coll->dirItems();
+    QVERIFY(sres.size() == 0);
+
+    KSecretsStore::AttributesMap emptyAttrs;
+    auto item = coll->createItem(itemName1, emptyAttrs, emptyValue);
+    QVERIFY(item.get() != nullptr);
+
+    auto cres1 = coll->createItem(itemName1, emptyAttrs, emptyValue);
+    QVERIFY(cres1.get() == nullptr); // second time should fail
+
+    QVERIFY(item->label() == collName1);
+    QVERIFY(item->value() == emptyValue);
+    QVERIFY(item->attributes() == emptyAttrs);
+
+    auto item2 = coll->createItem(itemName2, emptyValue);
+    QVERIFY(item2.get() != nullptr);
+    QVERIFY(item->label() == itemName2);
+    QVERIFY(item->value() == emptyValue);
+    QVERIFY(item->attributes() == emptyAttrs);
+
+    std::string testContents = std::string("some test contents");
+    KSecretsStore::ItemValue someValue;
+    someValue.contentType = "test-data";
+    someValue.contents.assign(testContents.begin(), testContents.end());
+    auto item3 = coll->createItem(itemName3, someValue);
+    QVERIFY(item3.get() != nullptr);
+    QVERIFY(item->label() == itemName3);
+    QVERIFY(item->value() == someValue);
+    QVERIFY(item->attributes() == emptyAttrs);
+}
+
+void KSecretServiceStoreTest::testCreateItemFailOnReadonly()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData());
+
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll = rres.result_;
+    QVERIFY(coll.get() != nullptr);
+
+    KSecretsStore::AttributesMap emptyAttrs;
+    auto item = coll->createItem(itemName1, emptyAttrs, emptyValue);
+    QVERIFY(item.get() == nullptr);
+}
+
+void KSecretServiceStoreTest::testSearchItem()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData());
+    // this test expends previous testCreateItem put in some items in collection named \
collName1 +    // so first load that collection
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll = rres.result_;
+    QVERIFY(coll.get() != nullptr);
+
+    auto sres = coll->dirItems();
+    QVERIFY(sres.size() == 0);
 
-// void KSecretServiceStoreTest::testOpen()
-// {
-//     KSecretsStore backend;
-//     auto setupfut =
-//     backend.setup(secretsFilePath.toLocal8Bit().constData());
-//     QVERIFY(setupfut.get());
-// }
+    // ok, now the test
+    auto list1 = coll->searchItems(itemName1);
+    QVERIFY(list1.size() == 1); // we used exact match so it should find one item
+    QVERIFY(list1.front()->label() == itemName1);
+
+    auto listN = coll->searchItems(itemNamesWildcard);
+    QVERIFY(listN.size() == 3); // we should find all 3 items here
+
+    auto list3 = coll->searchItems(itemName3);
+    QVERIFY(list3.size() == 1);
+    QVERIFY(list1.front()->label() == itemName3);
+}
+
+void KSecretServiceStoreTest::testItem() {
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData(), false);
+    // this test expends previous testCreateItem put in some items in collection named \
collName1 +    // so first load that collection
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll = rres.result_;
+    QVERIFY(coll.get() != nullptr);
+
+    auto list1 = coll->searchItems(itemName1);
+    QVERIFY(list1.size() == 1); // we used exact match so it should find one item
+    QVERIFY(list1.front()->label() == itemName1);
+
+    // ok, now the test
+    auto item = list1.front();
+
+    QVERIFY(item->createdTime() > createTimeMark);
+    QVERIFY(item->modifiedTime() > createTimeMark);
+    const char* newLabel1 = "new label 1";
+    QVERIFY(item->setLabel(newLabel1));
+    QVERIFY(item->label() == newLabel1);
+
+    const char *newContentType = "changed-content-type";
+    std::string newContents = "some other contents";
+    auto val = item->value();
+    val.contentType = newContentType;
+    val.contents.assign(newContents.begin(), newContents.end());
+    QVERIFY(item->setValue(val));
+
+    auto val1 = item->value();
+    QVERIFY(val1 == val);
+
+}
+
+void KSecretServiceStoreTest::testItemModifyFailOnReadonly()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData());
+    // this test expends previous testCreateItem put in some items in collection named \
collName1 +    // so first load that collection
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll = rres.result_;
+    QVERIFY(coll.get() != nullptr);
+
+    auto list1 = coll->searchItems(itemName1);
+    QVERIFY(list1.size() == 1); // we used exact match so it should find one item
+    QVERIFY(list1.front()->label() == itemName1);
+
+    // ok, now the test
+    auto item = list1.front();
+    QVERIFY(!item->setLabel("dummy"));
+
+    auto val = item->value();
+    val.contentType = "new-content-type";
+    QVERIFY(!item->setValue(val));
+
+    auto attrs = item->attributes();
+    attrs.emplace("test.kde.org", "test attr");
+    QVERIFY(!item->setAttributes(attrs));
+}
+
+void KSecretServiceStoreTest::testDeleteItem() {
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData(), false);
+
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll1 = rres.result_;
+
+    auto dres1 = coll1->dirItems();
+
+    auto il1 = coll1->searchItems(itemName2);
+    QVERIFY(il1.size() == 1);
+    QVERIFY(coll1->deleteItem(il1.front()));
+
+    auto dres2 = coll1->dirItems();
+    QVERIFY(dres2.size() < dres1.size());
+
+    il1 = coll1->searchItems(itemName2);
+    QVERIFY(il1.size() == 0);
+}
+
+void KSecretServiceStoreTest::testDeleteItemFailOnReadonly() {
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData());
+
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll1 = rres.result_;
+
+    auto dres1 = coll1->dirItems();
+
+    auto il1 = coll1->searchItems(itemName2);
+    QVERIFY(il1.size() == 1);
+    QVERIFY(!coll1->deleteItem(il1.front()));
+
+    auto dres2 = coll1->dirItems();
+    QVERIFY(dres2.size() == dres1.size());
+}
+
+void KSecretServiceStoreTest::testDeleteCollection()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData(), false);
+
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll1 = rres.result_;
+    auto dres = backend.deleteCollection(coll1);
+    QVERIFY(dres);
+
+    // try to read it again
+    rres = backend.readCollection(collName1);
+    QVERIFY(!rres);
+}
+
+void KSecretServiceStoreTest::testDeleteCollectionFailOnReadonly()
+{
+    KSecretsStore backend;
+    auto setupfut = backend.setup(secretsFilePath.toLocal8Bit().constData());
+
+    auto list1 = backend.dirCollections().result_;
+
+    auto rres = backend.readCollection(collName1);
+    QVERIFY(rres);
+    auto coll1 = rres.result_;
+    auto dres = backend.deleteCollection(coll1);
+    QVERIFY(!dres);
+
+    auto list2 = backend.dirCollections().result_;
+    QVERIFY(list1 == list2);
+}
+
+void KSecretServiceStoreTest::cleanupTestCase() { QDir::home().remove(secretsFilePath); }
 
 // vim: tw=220 ts=4
diff --git a/autotests/ksecrets_store/ksecrets_store_test.h \
b/autotests/ksecrets_store/ksecrets_store_test.h index a9a68ed..5e332a0 100644
--- a/autotests/ksecrets_store/ksecrets_store_test.h
+++ b/autotests/ksecrets_store/ksecrets_store_test.h
@@ -30,13 +30,18 @@ public:
 private Q_SLOTS:
     void initTestCase();
     void testCreateCollection();
+    void testCreateCollectionFailOnReadonly();
+    void testDirCollections();
+    void testReadCollection();
     void testCreateItem();
+    void testCreateItemFailOnReadonly();
     void testSearchItem();
     void testItem();
+    void testItemModifyFailOnReadonly();
     void testDeleteItem();
-    void testDirCollections();
-    void testReadCollection();
+    void testDeleteItemFailOnReadonly();
     void testDeleteCollection();
+    void testDeleteCollectionFailOnReadonly();
     void cleanupTestCase();
 };
 
diff --git a/src/runtime/ksecrets_store/ksecrets_credentials.cpp \
b/src/runtime/ksecrets_store/ksecrets_credentials.cpp index b59352e..135db0a 100644
--- a/src/runtime/ksecrets_store/ksecrets_credentials.cpp
+++ b/src/runtime/ksecrets_store/ksecrets_credentials.cpp
@@ -191,6 +191,7 @@ int KSECRETS_STORE_EXPORT kss_can_change_password()
 extern "C"
 int KSECRETS_STORE_EXPORT kss_change_password(const char* new_password)
 {
+    UNUSED(new_password);
     syslog(LOG_INFO, "kss_change_password");
     return TRUE;
 }
diff --git a/src/runtime/ksecrets_store/ksecrets_store.cpp \
b/src/runtime/ksecrets_store/ksecrets_store.cpp index edeb777..290ee00 100644
--- a/src/runtime/ksecrets_store/ksecrets_store.cpp
+++ b/src/runtime/ksecrets_store/ksecrets_store.cpp
@@ -230,4 +230,95 @@ KSecretsStore::DeleteCollectionResult \
KSecretsStore::deleteCollection(const char  // TODO
     return DeleteCollectionResult();
 }
+
+std::time_t KSecretsStore::Collection::createdTime() const {
+    // TODO
+    return std::time_t();
+}
+
+std::time_t KSecretsStore::Collection::modifiedTime() const {
+    //TODO
+    return std::time_t();
+}
+
+std::string KSecretsStore::Collection::label() const {
+    // TODO
+    return "";
+}
+
+KSecretsStore::Collection::ItemList KSecretsStore::Collection::dirItems() const {
+    // TODO
+    return ItemList();
+}
+
+KSecretsStore::Collection::ItemList KSecretsStore::Collection::searchItems(const AttributesMap \
&) const { +    // TODO
+    return ItemList();
+}
+
+KSecretsStore::Collection::ItemList KSecretsStore::Collection::searchItems(const char*, const \
AttributesMap &) const { +    // TODO
+    return ItemList();
+}
+
+KSecretsStore::Collection::ItemList KSecretsStore::Collection::searchItems(const char*) const \
{ +    // TODO
+    return ItemList();
+}
+
+KSecretsStore::ItemPtr KSecretsStore::Collection::createItem(const char*, AttributesMap, \
ItemValue) { +    // TODO
+    return ItemPtr();
+}
+
+bool KSecretsStore::Collection::deleteItem(ItemPtr) {
+    // TODO
+    return false;
+}
+
+KSecretsStore::ItemPtr KSecretsStore::Collection::createItem(const char*, ItemValue) {
+    // TODO
+    return ItemPtr();
+}
+
+std::time_t KSecretsStore::Item::createdTime() const {
+    // TODO
+    return std::time_t();
+}
+
+std::time_t KSecretsStore::Item::modifiedTime() const {
+    // TODO
+    return std::time_t();
+}
+
+std::string KSecretsStore::Item::label() const {
+    // TODO
+    return "";
+}
+
+bool KSecretsStore::Item::setLabel(const char*) {
+    // TODO
+    return false;
+}
+
+KSecretsStore::ItemValue KSecretsStore::Item::value() const {
+    // TODO
+    return ItemValue();
+}
+
+bool KSecretsStore::Item::setValue(ItemValue) {
+    // TODO
+    return false;
+}
+
+KSecretsStore::AttributesMap KSecretsStore::Item::attributes() const {
+    // TODO
+    return AttributesMap();
+}
+
+bool KSecretsStore::Item::setAttributes(AttributesMap) {
+    // TODO
+    return false;
+}
+
 // vim: tw=220:ts=4
diff --git a/src/runtime/ksecrets_store/ksecrets_store.h \
b/src/runtime/ksecrets_store/ksecrets_store.h index dacdedc..19b8632 100644
--- a/src/runtime/ksecrets_store/ksecrets_store.h
+++ b/src/runtime/ksecrets_store/ksecrets_store.h
@@ -81,6 +81,7 @@ public:
     struct ItemValue {
         std::string contentType;
         std::vector<char> contents;
+        bool operator == (const ItemValue& that) const noexcept { return contentType == \
that.contentType && contents == that.contents; }  };
 
     /* Holds a secret value.
@@ -92,6 +93,7 @@ public:
      * @see Collection
      */
     class Item {
+    public:
         Item(const Item&) = default;
         Item& operator=(const Item&) = default;
 
@@ -99,10 +101,18 @@ public:
         bool setLabel(const char*) noexcept;
 
         AttributesMap attributes() const;
-        void setAttributes(AttributesMap&&) noexcept;
+        /**
+         * @brief
+         *
+         * @note This method uses C++11 move semantics so the AttributesMap local variable \
used to call this member +         * will no longer be valid upon call return.
+         *
+         * @param AttributesMap
+         */
+        bool setAttributes(AttributesMap) noexcept;
 
         ItemValue value() const noexcept;
-        bool setValue(ItemValue&&) noexcept;
+        bool setValue(ItemValue) noexcept;
 
         std::time_t createdTime() const noexcept;
         std::time_t modifiedTime() const noexcept;
@@ -132,9 +142,7 @@ public:
      * the items having attribute value containing that partially specified value.
      */
     class Collection {
-        Collection(const Collection&) = default;
-        Collection& operator=(const Collection&) = default;
-
+    public:
         std::string label() const noexcept;
         bool setLabel(const char*) noexcept;
 
@@ -142,9 +150,10 @@ public:
         std::time_t modifiedTime() const noexcept;
 
         using ItemList = std::vector<ItemPtr>;
-        ItemList searchItems(AttributesMap&&) noexcept;
-        ItemList searchItems(const char*) noexcept;
-        ItemList searchItems(const char*, AttributesMap&&) noexcept;
+        ItemList dirItems() const noexcept;
+        ItemList searchItems(const AttributesMap&) const noexcept;
+        ItemList searchItems(const char*) const noexcept;
+        ItemList searchItems(const char*, const AttributesMap&) const noexcept;
 
         /**
          * Creates an item in the collection in one go. This is more efficient than
@@ -152,11 +161,14 @@ public:
          * the value. The returned item may still be modified, keep in mind that each
          * method call will trigger an store file update.
          *
+         * @note This member uses C++11 move semantics for the AttributesMap and ItemValue
+         *
          * @return ItemPtr which can be empty if creating the item was not
          * possible. So please check it via it's operator bool() before using
-         * it.
+         * it. Open possible failure reason is that an item with the same label already
+         * exists in the collection.
          */
-        ItemPtr createItem(const char*, AttributesMap&&, ItemValue&&) noexcept;
+        ItemPtr createItem(const char*, AttributesMap, ItemValue) noexcept;
         /**
          * Convenience method for creating items without supplemental
          * attributes.
@@ -165,12 +177,14 @@ public:
          * possible. So please check it via it's operator bool() before using
          * it.
          */
-        ItemPtr createItem(const char* label, ItemValue&&) noexcept;
+        ItemPtr createItem(const char* label, ItemValue) noexcept;
 
         bool deleteItem(ItemPtr) noexcept;
 
     protected:
         Collection();
+        Collection(const Collection&) = default;
+        Collection& operator=(const Collection&) = default;
         friend class KSecretsStore;
 
     private:
@@ -222,11 +236,15 @@ public:
         operator bool() const { return status_ == G; }
     };
 
+    template <typename T> struct AlwaysGoodPred { bool operator()(const T&) const noexcept { \
return true; }};  /**
-     * @brief Small structure returned by API calls that create things
+     * @brief Small structure returned by API calls that create things. It's possible to check \
the returned +     *        value by giving this template a custom OK_PRED of type equivalent \
                to std::function<bool(const R&)>
      */
-    template <StoreStatus G, typename R> struct CallResultWithValue : public CallResult<G> {
+    template <StoreStatus G, typename R, typename OK_PRED = AlwaysGoodPred<R> >
+        struct CallResultWithValue : public CallResult<G> {
         R result_;
+        operator bool() const noexcept { return CallResult<G>::operator bool() && \
OK_PRED()(result_); }  };
 
     using SetupResult = CallResult<StoreStatus::Good>;
@@ -259,7 +277,8 @@ public:
     using DirCollectionsResult = CallResultWithValue<StoreStatus::Good, CollectionNames>;
     DirCollectionsResult dirCollections() const noexcept;
 
-    using CreateCollectionResult = CallResultWithValue<StoreStatus::Good, CollectionPtr>;
+    template <typename P> struct IsGoodSmartPtr { bool operator()(const P& p) { return p.get() \
!= nullptr; }}; +    using CreateCollectionResult = CallResultWithValue<StoreStatus::Good, \
CollectionPtr, IsGoodSmartPtr<CollectionPtr> >;  /**
      * @return CollectionPtr which can empty if the call did not succeed
      *         Please check that with operator bool()
@@ -268,7 +287,7 @@ public:
      */
     CreateCollectionResult createCollection(const char*) noexcept;
 
-    using ReadCollectionResult = CallResultWithValue<StoreStatus::Good, CollectionPtr>;
+    using ReadCollectionResult = CallResultWithValue<StoreStatus::Good, CollectionPtr, \
IsGoodSmartPtr<CollectionPtr> >;  /**
      * @return CollectionPtr which can empty if the call did not succeed, e.g.
      * the collection was not found
@@ -276,7 +295,12 @@ public:
      */
     ReadCollectionResult readCollection(const char*) const noexcept;
 
-    using DeleteCollectionResult = CallResultWithValue<StoreStatus::Good, bool>;
+    /**
+     * @brief Return value for deleteCollection method variants. Please note the operator \
bool() can be used to both +     * check the collection's status after the deleteCollection \
call, and the result of the delete operation, as it's +     * using the `bool` specialized \
version of the IsGoodPred +     */
+    using DeleteCollectionResult = CallResultWithValue<StoreStatus::Good, bool, \
AlwaysGoodPred<bool> >;  DeleteCollectionResult deleteCollection(CollectionPtr) noexcept;
     DeleteCollectionResult deleteCollection(const char*) noexcept;
 
@@ -284,5 +308,7 @@ private:
     std::unique_ptr<KSecretsStorePrivate> d;
 };
 
+template <> struct KSecretsStore::AlwaysGoodPred<bool> { bool operator()(const bool& b) const \
noexcept { return b; }}; +
 #endif
 // vim: tw=220:ts=4


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

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