Support NONE policy in storage 00/26300/4
authorAleksander Zdyb <a.zdyb@partner.samsung.com>
Wed, 20 Aug 2014 06:30:23 +0000 (08:30 +0200)
committerAleksander Zdyb <a.zdyb@partner.samsung.com>
Mon, 8 Sep 2014 10:58:04 +0000 (12:58 +0200)
Change-Id: I80d28fee394c5e461bccf102b0d6f7b4ab243174

src/common/exceptions/DefaultBucketSetNoneException.h [new file with mode: 0644]
src/common/types/PolicyResult.h
src/common/types/PolicyType.cpp
src/common/types/PolicyType.h
src/service/storage/Storage.cpp
test/storage/storage/check.cpp
test/storage/storage/fakestoragebackend.h

diff --git a/src/common/exceptions/DefaultBucketSetNoneException.h b/src/common/exceptions/DefaultBucketSetNoneException.h
new file mode 100644 (file)
index 0000000..d9664b3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+/*
+ * @file        DefaultBucketSetNoneException.h
+ * @author      Aleksander Zdyb <a.zdyb@partner.samsung.com>
+ * @version     1.0
+ * @brief       Implementation of DefaultBucketSetNoneException
+ */
+
+#ifndef SRC_COMMON_EXCEPTIONS_DEFAULTBUCKETSETNONEEXCEPTION_H_
+#define SRC_COMMON_EXCEPTIONS_DEFAULTBUCKETSETNONEEXCEPTION_H_
+
+#include <exception>
+
+#include "Exception.h"
+
+namespace Cynara {
+
+class DefaultBucketSetNoneException : public Exception {
+public:
+    DefaultBucketSetNoneException() = default;
+    virtual ~DefaultBucketSetNoneException() noexcept {};
+
+    virtual const std::string message(void) const {
+        return "DefaultBucketSetNoneException";
+    }
+};
+
+} /* namespace Cynara */
+
+#endif // SRC_COMMON_EXCEPTIONS_DEFAULTBUCKETSETNONEEXCEPTION_H_
index a9369d8..0e0c716 100644 (file)
@@ -60,9 +60,17 @@ public:
         return std::tie(m_type, m_metadata) == std::tie(other.m_type, other.m_metadata);
     }
 
+    bool operator !=(const PolicyResult &other) const {
+        return !(*this == other);
+    }
+
     bool operator ==(const PolicyType &policyType) const {
         return (m_type == policyType) && m_metadata.empty();
     }
+
+    bool operator !=(const PolicyType &policyType) const {
+        return !(*this == policyType);
+    }
 };
 
 } // namespace Cynara
index bf022f5..9491f6c 100644 (file)
@@ -29,4 +29,8 @@ bool operator ==(const PolicyType &policyType, const PolicyResult &policyResult)
     return policyResult == policyType;
 }
 
+bool operator !=(const PolicyType &policyType, const PolicyResult &policyResult) {
+    return !(policyResult == policyType);
+}
+
 }  // namespace Cynara
index 9131b1b..e7ad60d 100644 (file)
@@ -33,12 +33,14 @@ typedef std::uint16_t PolicyType;
 
 namespace PredefinedPolicyType  {
     const PolicyType DENY = 0;
+    const PolicyType NONE = 1;
     const PolicyType BUCKET = 0xFFFE;
     const PolicyType ALLOW = 0xFFFF;
 };
 
 class PolicyResult;
 bool operator ==(const PolicyType &policyType, const PolicyResult &policyResult);
+bool operator !=(const PolicyType &policyType, const PolicyResult &policyResult);
 
 }  // namespace Cynara
 
index 8e81edc..108ebe8 100644 (file)
@@ -25,7 +25,8 @@
 #include <vector>
 
 #include <exceptions/BucketNotExistsException.h>
-#include "exceptions/DefaultBucketDeletionException.h"
+#include <exceptions/DefaultBucketDeletionException.h>
+#include <exceptions/DefaultBucketSetNoneException.h>
 #include <types/pointers.h>
 #include <types/Policy.h>
 #include <types/PolicyBucket.h>
@@ -69,7 +70,9 @@ PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey
                     if (recursive == true) {
                         auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key);
                         auto minimumOfBucket = minimalPolicy(bucketResults, key, true);
-                        proposeMinimal(minimumOfBucket);
+                        if (minimumOfBucket != PredefinedPolicyType::NONE) {
+                            proposeMinimal(minimumOfBucket);
+                        }
                     }
                     continue;
                 }
@@ -112,7 +115,12 @@ void Storage::insertPolicies(const std::map<PolicyBucketId, std::vector<Policy>>
     }
 }
 
-void Storage::addOrUpdateBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultBucketPolicy) {
+void Storage::addOrUpdateBucket(const PolicyBucketId &bucketId,
+                                const PolicyResult &defaultBucketPolicy) {
+
+    if (bucketId == defaultPolicyBucketId && defaultBucketPolicy == PredefinedPolicyType::NONE)
+        throw DefaultBucketSetNoneException();
+
     if (m_backend.hasBucket(bucketId)) {
         m_backend.updateBucket(bucketId, defaultBucketPolicy);
     } else {
index f56e7fe..e1f6505 100644 (file)
@@ -189,3 +189,76 @@ TEST(storage, checkNonrecursive) {
 
     ASSERT_EQ(PredefinedPolicyType::ALLOW, storage.checkPolicy(pk, bucketId, false));
 }
+
+/*
+ * bucket1 contains policy (with key pk) pointing to bucket2
+ * bucket2 is empty and it's default policy is NONE
+ * Because NONE policy in bucket2, check should yield default policy of bucket1 and not of bucket2
+ */
+TEST(storage, noneBucket) {
+    using ::testing::ReturnPointee;
+    using PredefinedPolicyType::ALLOW;
+    using PredefinedPolicyType::NONE;
+
+    auto pk = Helpers::generatePolicyKey();
+
+    PolicyBucket bucket2("bucket-2", NONE);
+    PolicyBucket bucket1("bucket-1", ALLOW, { Policy::bucketWithKey(pk, bucket2.id()) });
+
+    FakeStorageBackend backend;
+    Cynara::Storage storage(backend);
+
+    EXPECT_CALL(backend, searchBucket(bucket1.id(), pk))
+        .WillOnce(ReturnPointee(&bucket1));
+    EXPECT_CALL(backend, searchBucket(bucket2.id(), pk))
+        .WillOnce(ReturnPointee(&bucket2));
+
+    ASSERT_EQ(ALLOW, storage.checkPolicy(pk, bucket1.id(), true));
+}
+
+/*
+ * Scenario similar to noneBucket, but bucket2 contains matching policy.
+ * In this case this policy should be returned.
+ */
+TEST(storage, noneBucketNotEmpty) {
+    using ::testing::ReturnPointee;
+    using PredefinedPolicyType::ALLOW;
+    using PredefinedPolicyType::DENY;
+    using PredefinedPolicyType::NONE;
+
+    auto pk = Helpers::generatePolicyKey();
+
+    PolicyBucket bucket2("bucket-2", NONE, { Policy::simpleWithKey(pk, DENY) });
+    PolicyBucket bucket1("bucket-1", ALLOW, { Policy::bucketWithKey(pk, bucket2.id()) });
+
+    FakeStorageBackend backend;
+    Cynara::Storage storage(backend);
+
+    EXPECT_CALL(backend, searchBucket(bucket1.id(), pk))
+        .WillOnce(ReturnPointee(&bucket1));
+    EXPECT_CALL(backend, searchBucket(bucket2.id(), pk))
+        .WillOnce(ReturnPointee(&bucket2));
+
+    ASSERT_EQ(DENY, storage.checkPolicy(pk, bucket1.id(), true));
+}
+
+/*
+ * Single empty bucket with default policy of NONE
+ * -- searching for any key should yield NONE
+ */
+TEST(storage, singleNoneBucket) {
+    using ::testing::ReturnPointee;
+    using PredefinedPolicyType::NONE;
+
+    auto pk = Helpers::generatePolicyKey();
+
+    PolicyBucket bucket("bucket", NONE, {});
+
+    FakeStorageBackend backend;
+    Cynara::Storage storage(backend);
+
+    EXPECT_CALL(backend, searchBucket(bucket.id(), pk))
+        .WillOnce(ReturnPointee(&bucket));
+
+    ASSERT_EQ(NONE, storage.checkPolicy(pk, bucket.id(), true));
+}
index b1e8b69..fa8898b 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef FAKESTORAGEBACKEND_H_
 #define FAKESTORAGEBACKEND_H_
 
+#include <storage/StorageBackend.h>
+
 using namespace Cynara;
 
 class FakeStorageBackend : public StorageBackend {