#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <map>
+#include <string>
+
#include <types/PolicyBucket.h>
#include <types/PolicyCollection.h>
+#include <types/PolicyKey.h>
#include <storage/Buckets.h>
#include <storage/InMemoryStorageBackend.h>
+#include <TestDataCollection.h>
+
class InMemeoryStorageBackendFixture : public ::testing::Test {
+public:
+ class Filter {
+ public:
+ Filter(const std::string &name, const Cynara::PolicyKey &key) :
+ m_name(name), m_key(key) {}
+
+ const std::string &name(void) const {
+ return m_name;
+ }
+
+ const Cynara::PolicyKey &key(void) const {
+ return m_key;
+ }
+
+ private:
+ std::string m_name;
+ Cynara::PolicyKey m_key;
+ };
+
+ typedef std::vector<Filter> Filters;
protected:
Cynara::Buckets::mapped_type &
virtual ~InMemeoryStorageBackendFixture() {}
+ const Cynara::PolicyCollection &fullPoliciesCollection(void) {
+ using Cynara::PredefinedPolicyType::ALLOW;
+ if (m_fullPolicyCollection.empty()) {
+ m_fullPolicyCollection = {
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cup, ALLOW),
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_wup, ALLOW),
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cwp, ALLOW),
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cuw, ALLOW),
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_cww, ALLOW),
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_wuw, ALLOW),
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_wwp, ALLOW),
+ Cynara::Policy::simpleWithKey(TestDataCollection::Keys::k_www, ALLOW),
+ };
+ }
+ return m_fullPolicyCollection;
+ }
+
+ const Filters &filters(void) {
+ if (m_filters.empty()) {
+ m_filters.push_back(Filter("cup", TestDataCollection::Keys::k_cup));
+ m_filters.push_back(Filter("www", TestDataCollection::Keys::k_www));
+ m_filters.push_back(Filter("wuw", TestDataCollection::Keys::k_wuw));
+ m_filters.push_back(Filter("aaa", TestDataCollection::Keys::k_aaa));
+ m_filters.push_back(Filter("wua", TestDataCollection::Keys::k_wua));
+ m_filters.push_back(Filter("wwa", TestDataCollection::Keys::k_wwa));
+ m_filters.push_back(Filter("aup", TestDataCollection::Keys::k_aup));
+ }
+ return m_filters;
+ }
+
+ const Cynara::PolicyCollection &expectedEraseResult(const std::string &filterName) {
+ if (m_expectedResults.empty()) {
+ const Cynara::PolicyCollection &pc = fullPoliciesCollection();
+ // "cup", "wup", "cwp", "cuw", "cww", "wuw", "wwp", "www"
+ m_expectedResults["cup"] = { pc[1], pc[2], pc[3], pc[4], pc[5], pc[6], pc[7]};
+ m_expectedResults["www"] = {pc[0], pc[1], pc[2], pc[3], pc[4], pc[5], pc[6], };
+ m_expectedResults["wuw"] = {pc[0], pc[1], pc[2], pc[3], pc[4], pc[6], pc[7]};
+ m_expectedResults["aaa"] = { };
+ m_expectedResults["wua"] = {pc[0], pc[2], pc[3], pc[4], pc[6], pc[7]};
+ m_expectedResults["wwa"] = {pc[0], pc[1], pc[2], pc[3], pc[4], pc[5], };
+ m_expectedResults["aup"] = { pc[2], pc[3], pc[4], pc[5], pc[6], pc[7]};
+ }
+
+ return m_expectedResults[filterName];
+ }
+
+ bool isLinkPolicyErased(const std::string &filterName) {
+ if (filterName == "aaa")
+ return true;
+ return false;
+ }
+
// TODO: consider defaulting accessor with ON_CALL
Cynara::Buckets m_buckets;
static const std::string m_indexFileName;
static const std::string m_backupFileNameSuffix;
+
+ //erase helper structures
+ Cynara::PolicyCollection m_fullPolicyCollection;
+ Filters m_filters;
+ std::map<std::string, Cynara::PolicyCollection> m_expectedResults;
};
ASSERT_THAT(bucketPolicies, IsEmpty());
}
}
+
+/**
+ * @brief Erase from non-exiting bucket should throw BucketNotExistsException
+ * @test Scenario:
+ * - For different filter keys:
+ * - try erase policies from "non-existing-bucket"
+ * - expect BucketNotExistsException is thrown
+ */
+TEST_F(InMemeoryStorageBackendFixture, erasePoliciesEmptyBase) {
+ using ::testing::ReturnRef;
+
+ FakeInMemoryStorageBackend backend;
+ EXPECT_CALL(backend, buckets())
+ .WillRepeatedly(ReturnRef(m_buckets));
+
+ PolicyBucketId bucketId = "non-existing-bucket";
+ const bool NON_RECURSIVE = false;
+
+ for (const auto &filter : filters()) {
+ SCOPED_TRACE(filter.name());
+
+ EXPECT_THROW(backend.erasePolicies(bucketId, NON_RECURSIVE, filter.key()),
+ BucketNotExistsException);
+ }
+}
+
+/**
+ * @brief Erase from single bucket
+ * @test Scenario:
+ * - For different filter keys:
+ * - create "test-bucket"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket"
+ * - erase policies from "test-bucket"
+ * - check if received results match expected
+ */
+TEST_F(InMemeoryStorageBackendFixture, erasePoliciesSingleBucket) {
+ using ::testing::ReturnRef;
+ using ::testing::UnorderedElementsAreArray;
+
+ PolicyBucketId bucketId = "test-bucket";
+ const bool NON_RECURSIVE = false;
+
+ for (const auto &filter : filters()) {
+ SCOPED_TRACE(filter.name());
+
+ FakeInMemoryStorageBackend backend;
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+
+ createBucket(bucketId);
+ addToBucket(bucketId, fullPoliciesCollection());
+
+ backend.erasePolicies(bucketId, NON_RECURSIVE, filter.key());
+ ASSERT_THAT(m_buckets.at(bucketId),
+ UnorderedElementsAreArray(expectedEraseResult(filter.name())));
+ }
+}
+
+/**
+ * @brief Verify if recursive erase doesn't propagate to not linked bucket
+ * @test Scenario:
+ * - For different filter keys:
+ * - create "test-bucket"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket"
+ * - create "test-bucket2"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket2"
+ * - erase policies from "test-bucket"
+ * - check if received results match expected in case of "test-bucket"
+ * - check if policies in "test-bucket2" remain unaffected
+ */
+TEST_F(InMemeoryStorageBackendFixture, erasePoliciesRecursiveNotLinkedBuckets) {
+ using ::testing::ReturnRef;
+ using ::testing::UnorderedElementsAreArray;
+
+ PolicyBucketId bucketId = "test-bucket";
+ PolicyBucketId bucketId2 = "test-bucket2";
+ const bool RECURSIVE = true;
+
+ for (const auto &filter : filters()) {
+ SCOPED_TRACE(filter.name());
+
+ FakeInMemoryStorageBackend backend;
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+
+ createBucket(bucketId);
+ addToBucket(bucketId, fullPoliciesCollection());
+
+ createBucket(bucketId2);
+ addToBucket(bucketId2, fullPoliciesCollection());
+
+ backend.erasePolicies(bucketId, RECURSIVE, filter.key());
+ ASSERT_THAT(m_buckets.at(bucketId),
+ UnorderedElementsAreArray(expectedEraseResult(filter.name())));
+ ASSERT_THAT(m_buckets.at(bucketId2),
+ UnorderedElementsAreArray(fullPoliciesCollection()));
+ }
+}
+
+/**
+ * @brief Verify if recursive erase does propagate to linked bucket
+ * @test Scenario:
+ * - For different filter keys:
+ * - create "test-bucket"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket"
+ * - create "test-bucket2"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket2"
+ * - add policy linking test buckets
+ * - erase policies from "test-bucket"
+ * - check if received results match expected in case of "test-bucket"
+ * - check if received results match expected in case of "test-bucket2"
+ */
+TEST_F(InMemeoryStorageBackendFixture, erasePoliciesRecursiveLinkedBuckets) {
+ using ::testing::ReturnRef;
+ using ::testing::UnorderedElementsAreArray;
+
+ PolicyBucketId bucketId = "test-bucket";
+ PolicyBucketId bucketId2 = "test-bucket2";
+ PolicyKey linkKey = Helpers::generatePolicyKey("link");
+ PolicyCollection linkPolicy = {Policy::bucketWithKey(linkKey, bucketId2)};
+ const bool RECURSIVE = true;
+
+ for (const auto &filter : filters()) {
+ SCOPED_TRACE(filter.name());
+
+ FakeInMemoryStorageBackend backend;
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+
+ createBucket(bucketId);
+ addToBucket(bucketId, fullPoliciesCollection());
+
+ createBucket(bucketId2);
+ addToBucket(bucketId2, fullPoliciesCollection());
+
+ addToBucket(bucketId, linkPolicy);
+
+ backend.erasePolicies(bucketId, RECURSIVE, filter.key());
+
+ PolicyCollection expectedResult = expectedEraseResult(filter.name());
+ if (!isLinkPolicyErased(filter.name())) {
+ expectedResult.insert(expectedResult.end(), linkPolicy.begin(), linkPolicy.end());
+ }
+ ASSERT_THAT(m_buckets.at(bucketId),
+ UnorderedElementsAreArray(expectedResult));
+ ASSERT_THAT(m_buckets.at(bucketId2),
+ UnorderedElementsAreArray(expectedEraseResult(filter.name())));
+ }
+}
+
+/**
+ * @brief Verify if recursive erase doesn't propagate backwards to linked bucket
+ * @test Scenario:
+ * - For different filter keys:
+ * - create "test-bucket"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket"
+ * - create "test-bucket2"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket2"
+ * - add policy linking test buckets
+ * - erase policies from "test-bucket2"
+ * - check if policies in "test-bucket" remain unaffected
+ * - check if received results match expected in case of "test-bucket2"
+ */
+TEST_F(InMemeoryStorageBackendFixture, erasePoliciesRecursiveLinkedBucketsNoBackwardPropagation) {
+ using ::testing::ReturnRef;
+ using ::testing::UnorderedElementsAreArray;
+
+ PolicyBucketId bucketId = "test-bucket";
+ PolicyBucketId bucketId2 = "test-bucket2";
+ PolicyKey linkKey = Helpers::generatePolicyKey("link");
+ PolicyCollection linkPolicy = {Policy::bucketWithKey(linkKey, bucketId2)};
+ const bool RECURSIVE = true;
+
+ for (const auto &filter : filters()) {
+ SCOPED_TRACE(filter.name());
+
+ FakeInMemoryStorageBackend backend;
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+
+ createBucket(bucketId);
+ addToBucket(bucketId, fullPoliciesCollection());
+
+ createBucket(bucketId2);
+ addToBucket(bucketId2, fullPoliciesCollection());
+
+ addToBucket(bucketId, linkPolicy);
+
+ backend.erasePolicies(bucketId2, RECURSIVE, filter.key());
+
+ PolicyCollection expectedResult = fullPoliciesCollection();
+ expectedResult.insert(expectedResult.end(), linkPolicy.begin(), linkPolicy.end());
+
+ ASSERT_THAT(m_buckets.at(bucketId),
+ UnorderedElementsAreArray(expectedResult));
+ ASSERT_THAT(m_buckets.at(bucketId2),
+ UnorderedElementsAreArray(expectedEraseResult(filter.name())));
+ }
+}
+
+/**
+ * @brief Verify if non-recursive erase doesn't propagate to linked bucket
+ * @test Scenario:
+ * - For different filter keys:
+ * - create "test-bucket"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket"
+ * - create "test-bucket2"
+ * - add all types of policies (fullPoliciesCollection) into "test-bucket2"
+ * - add policy linking test buckets
+ * - erase policies from "test-bucket"
+ * - check if received results match expected in case of "test-bucket"
+ * - check if policies in "test-bucket2" remain unaffected
+ */
+TEST_F(InMemeoryStorageBackendFixture, erasePoliciesNonRecursiveLinkedBuckets) {
+ using ::testing::ReturnRef;
+ using ::testing::UnorderedElementsAreArray;
+
+ PolicyBucketId bucketId = "test-bucket";
+ PolicyBucketId bucketId2 = "test-bucket2";
+ PolicyKey linkKey = Helpers::generatePolicyKey("link");
+ PolicyCollection linkPolicy = {Policy::bucketWithKey(linkKey, bucketId2)};
+ const bool NON_RECURSIVE = false;
+
+ for (const auto &filter : filters()) {
+ SCOPED_TRACE(filter.name());
+
+ FakeInMemoryStorageBackend backend;
+ EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets));
+
+ createBucket(bucketId);
+ addToBucket(bucketId, fullPoliciesCollection());
+
+ createBucket(bucketId2);
+ addToBucket(bucketId2, fullPoliciesCollection());
+
+ addToBucket(bucketId, linkPolicy);
+
+ backend.erasePolicies(bucketId, NON_RECURSIVE, filter.key());
+
+ PolicyCollection expectedResult = expectedEraseResult(filter.name());
+ if (!isLinkPolicyErased(filter.name())) {
+ expectedResult.insert(expectedResult.end(), linkPolicy.begin(), linkPolicy.end());
+ }
+ ASSERT_THAT(m_buckets.at(bucketId),
+ UnorderedElementsAreArray(expectedResult));
+ ASSERT_THAT(m_buckets.at(bucketId2),
+ UnorderedElementsAreArray(fullPoliciesCollection()));
+ }
+}