${COMMON_PATH}/system/signals.cpp
${COMMON_PATH}/types/PolicyBucket.cpp
${COMMON_PATH}/types/PolicyKey.cpp
+ ${COMMON_PATH}/types/PolicyKeyHelpers.cpp
)
IF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
* @brief Implementation of Cynara::PolicyBucket methods
*/
+#include <sstream>
+
+#include <types/PolicyCollection.h>
+#include <types/PolicyKeyHelpers.h>
#include "PolicyBucket.h"
PolicyBucket PolicyBucket::filtered(const PolicyKey &key) const {
PolicyBucket result;
- const auto &policies = policyCollection();
- std::copy_if(policies.begin(), policies.end(), std::back_inserter(result.policyCollection()),
- [=] (PolicyCollection::value_type policy) {
- return policy->key() == key;
- });
+ const auto &policies = m_policyCollection;
+ const auto variants = PolicyKeyHelpers::keyVariants(key);
+
+ for (const auto &variant : variants) {
+ const auto policyIter = policies.find(variant);
+ if (policyIter != policies.end()) {
+ result.m_policyCollection[policyIter->first] = policyIter->second;
+ }
+ }
// Inherit original policy
result.setDefaultPolicy(defaultPolicy());
return result;
}
+void PolicyBucket::insertPolicy(PolicyPtr policy) {
+ const auto gluedKey = PolicyKeyHelpers::glueKey(policy->key());
+ m_policyCollection[gluedKey] = policy;
+}
+
+void PolicyBucket::deletePolicy(const PolicyKey &key) {
+ const auto gluedKey = PolicyKeyHelpers::glueKey(key);
+ m_policyCollection.erase(gluedKey);
+}
+
+void PolicyBucket::deletePolicy(std::function<bool(PolicyPtr)> predicate) {
+ auto &policies = m_policyCollection;
+
+ for (auto iter = policies.begin(); iter != policies.end(); ) {
+ if (predicate(iter->second)) {
+ policies.erase(iter++);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+PolicyMap PolicyBucket::makePolicyMap(const PolicyCollection &policies) {
+ PolicyMap result;
+ for (const auto &policy : policies) {
+ const auto gluedKey = PolicyKeyHelpers::glueKey(policy->key());
+ result[gluedKey] = policy;
+ }
+ return result;
+}
+
} // namespace Cynara
#ifndef SRC_COMMON_TYPES_POLICYBUCKET_H_
#define SRC_COMMON_TYPES_POLICYBUCKET_H_
-#include "PolicyCollection.h"
-#include "PolicyKey.h"
-#include "Policy.h"
-#include "exceptions/NotImplementedException.h"
-#include "types/pointers.h"
-#include "types/PolicyType.h"
-#include "PolicyBucketId.h"
-
-#include <string>
-#include <memory>
#include <algorithm>
+#include <memory>
+#include <string>
+
+#include <exceptions/NotImplementedException.h>
+#include <types/pointers.h>
+#include <types/Policy.h>
+#include <types/PolicyBucketId.h>
+#include <types/PolicyCollection.h>
+#include <types/PolicyKey.h>
+#include <types/PolicyType.h>
namespace Cynara {
class PolicyBucket {
public:
+ typedef PolicyCollection::value_type value_type;
+ typedef const_policy_iterator const_iterator;
+
PolicyBucket() : m_defaultPolicy(PredefinedPolicyType::DENY) {}
PolicyBucket(const PolicyBucketId &id, const PolicyResult &defaultPolicy)
: m_defaultPolicy(defaultPolicy), m_id(id) {}
PolicyBucket(const PolicyCollection &policies)
- : m_policyCollection(policies),
+ : m_policyCollection(makePolicyMap(policies)),
m_defaultPolicy(PredefinedPolicyType::DENY) {}
PolicyBucket filtered(const PolicyKey &key) const;
+ void insertPolicy(PolicyPtr policy);
+ void deletePolicy(const PolicyKey &key);
+
+ // TODO: Try to change interface, so this method is not needed
+ void deletePolicy(std::function<bool(PolicyPtr)> predicate);
+
+ static PolicyMap makePolicyMap(const PolicyCollection &policies);
private:
- PolicyCollection m_policyCollection;
+ PolicyMap m_policyCollection;
PolicyResult m_defaultPolicy;
PolicyBucketId m_id;
public:
- const PolicyResult &defaultPolicy() const {
- return m_defaultPolicy;
+
+ const_policy_iterator begin(void) const {
+ return const_policy_iterator(m_policyCollection.begin());
}
- const PolicyBucketId &id() const {
- return m_id;
+ const_policy_iterator end(void) const {
+ return const_policy_iterator(m_policyCollection.end());
+ }
+
+ PolicyMap::size_type size(void) const noexcept {
+ return m_policyCollection.size();
+ }
+
+ bool empty(void) const noexcept {
+ return m_policyCollection.empty();
}
- PolicyCollection &policyCollection() {
- return m_policyCollection;
+ const PolicyResult &defaultPolicy(void) const {
+ return m_defaultPolicy;
}
- const PolicyCollection &policyCollection() const {
- return m_policyCollection;
+ const PolicyBucketId &id(void) const {
+ return m_id;
}
// TODO: Consider StorageBackend to be only one to alter this property
void setDefaultPolicy(const PolicyResult &defaultPolicy) {
m_defaultPolicy = defaultPolicy;
}
-
- void setPolicyCollection(const PolicyCollection &policies) {
- m_policyCollection = policies;
- }
};
} /* namespace Cynara */
* @brief This file defines a collection of policies
*/
-#ifndef CYNARA_COMMON_TYPES_POLICYCOLLECTION_H
-#define CYNARA_COMMON_TYPES_POLICYCOLLECTION_H
-
-#include "types/pointers.h"
+#ifndef SRC_COMMON_TYPES_POLICYCOLLECTION_H_
+#define SRC_COMMON_TYPES_POLICYCOLLECTION_H_
+#include <unordered_map>
#include <vector>
+#include "types/pointers.h"
+
namespace Cynara {
typedef std::vector<PolicyPtr> PolicyCollection;
+typedef std::unordered_map<std::string, PolicyPtr> PolicyMap;
+
+class const_policy_iterator : public PolicyMap::const_iterator
+{
+ public:
+ const_policy_iterator() : PolicyMap::const_iterator() {};
+ const_policy_iterator(const PolicyMap::const_iterator &other)
+ : PolicyMap::const_iterator(other) {};
+
+ PolicyPtr operator*(void) {
+ return PolicyMap::const_iterator::operator*().second;
+ }
+};
} // namespace Cynara
-#endif /* CYNARA_COMMON_TYPES_POLICYCOLLECTION_H */
+#endif /* SRC_COMMON_TYPES_POLICYCOLLECTION_H_ */
void InMemoryStorageBackend::insertPolicy(const PolicyBucketId &bucketId, PolicyPtr policy) {
try {
auto &bucket = buckets().at(bucketId);
- auto &policies = bucket.policyCollection();
- policies.push_back(policy);
+ bucket.insertPolicy(policy);
} catch (const std::out_of_range &) {
throw BucketNotExistsException(bucketId);
}
try {
// TODO: Move the erase code to PolicyCollection maybe?
auto &bucket = buckets().at(bucketId);
- auto &policies = bucket.policyCollection();
- policies.erase(remove_if(policies.begin(), policies.end(),
- [key](PolicyPtr policy) -> bool {
- return policy->key() == key;
- }), policies.end());
+ bucket.deletePolicy(key);
} catch (const std::out_of_range &) {
throw BucketNotExistsException(bucketId);
}
};
for (auto &bucketIter : buckets()) {
- // TODO: Move the erase code to PolicyCollection maybe?
auto &bucket = bucketIter.second;
- auto &policies = bucket.policyCollection();
- policies.erase(remove_if(policies.begin(), policies.end(), bucketIdMatches),
- policies.end());
+ bucket.deletePolicy(bucketIdMatches);
}
}
bool hasMinimal = false;
PolicyResult minimal = bucket.defaultPolicy();
- const auto &policies = bucket.policyCollection();
-
auto proposeMinimal = [&minimal, &hasMinimal](const PolicyResult &candidate) {
if (hasMinimal == false) {
minimal = candidate;
hasMinimal = true;
};
- for (const auto &policyRecord : policies) {
- const auto &policyResult = policyRecord->result();
+ for (const auto policy : bucket) {
+ const auto &policyResult = policy->result();
switch (policyResult.policyType()) {
case PredefinedPolicyType::DENY:
const PolicyBucketId &bucketId = group.first;
const auto &policies = group.second;
for (const auto &policy : policies) {
- auto existingPolicies = m_backend.searchBucket(bucketId, policy.key());
- for (auto existingPolicy : existingPolicies.policyCollection()) {
- m_backend.deletePolicy(bucketId, existingPolicy->key());
- }
m_backend.insertPolicy(bucketId, std::make_shared<Policy>(policy));
}
}
auto bucketDeserializer = m_bucketStreamOpener(bucketId);
if (bucketDeserializer != nullptr) {
- bucket.setPolicyCollection(bucketDeserializer->loadPolicies());
+ const auto policies = bucketDeserializer->loadPolicies();
+ for (const auto policy : policies) {
+ bucket.insertPolicy(policy);
+ }
} else {
throw BucketDeserializationException(bucketId);
}
}
void StorageSerializer::dump(const PolicyBucket& bucket) {
- const auto &policies = bucket.policyCollection();
-
- for (auto it = std::begin(policies); it != std::end(policies); ++it) {
+ for (auto it = std::begin(bucket); it != std::end(bucket); ++it) {
const auto &policy = *it;
dump(policy);
}
SET(CYNARA_SOURCES_FOR_TESTS
${CYNARA_SRC}/service/storage/Storage.cpp
${CYNARA_SRC}/common/types/PolicyBucket.cpp
+ ${CYNARA_SRC}/common/types/PolicyKeyHelpers.cpp
${CYNARA_SRC}/service/storage/InMemoryStorageBackend.cpp
${CYNARA_SRC}/service/storage/BucketDeserializer.cpp
${CYNARA_SRC}/service/storage/StorageDeserializer.cpp
* @brief Tests for Cynara::PolicyBucket
*/
-#include <gtest/gtest.h>
+#include <algorithm>
+#include <tuple>
+#include <vector>
+
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include "types/PolicyBucket.h"
-#include "types/PolicyKey.h"
#include "types/PolicyCollection.h"
+#include "types/PolicyKey.h"
#include "../../helpers.h"
-#include <algorithm>
-#include <tuple>
-
using namespace Cynara;
class PolicyBucketFixture : public ::testing::Test {
Policy::simpleWithKey(PolicyKey("*", "*", "p1"), PredefinedPolicyType::ALLOW),
Policy::simpleWithKey(PolicyKey("*", "*", "*"), PredefinedPolicyType::ALLOW)
};
-
- PolicyCollection filterHelper(const PolicyCollection &original,
- std::function<bool(const PolicyCollection::value_type &)> pred) {
- PolicyCollection filtered(original.size());
- auto endIt = std::copy_if(std::begin(original), std::end(original),
- std::begin(filtered), pred);
- filtered.resize(std::distance(std::begin(filtered), endIt));
- return filtered;
- }
-
- PolicyCollection filterHelper(const PolicyCollection &original, std::vector<unsigned> idx) {
- PolicyCollection filtered;
- filtered.reserve(idx.size());
- for (const auto &i : idx) {
- filtered.push_back(original.at(i));
- }
- return filtered;
- }
};
TEST_F(PolicyBucketFixture, filtered) {
- using ::testing::UnorderedElementsAreArray;
using ::testing::UnorderedElementsAre;
- using ::testing::IsEmpty;
PolicyBucket bucket(pkPolicies);
bucket.setDefaultPolicy(PredefinedPolicyType::DENY);
auto filtered = bucket.filtered(pk1);
// Elements match
- ASSERT_THAT(filtered.policyCollection(), UnorderedElementsAre(pkPolicies.at(0)));
+ ASSERT_THAT(filtered, UnorderedElementsAre(pkPolicies.at(0)));
// default policy matches
ASSERT_EQ(PredefinedPolicyType::DENY, filtered.defaultPolicy());
}
TEST_F(PolicyBucketFixture, filtered_other) {
- using ::testing::UnorderedElementsAreArray;
- using ::testing::UnorderedElementsAre;
using ::testing::IsEmpty;
PolicyBucket bucket(pkPolicies);
auto filtered = bucket.filtered(otherPk);
// No policies should be found
- ASSERT_THAT(filtered.policyCollection(), IsEmpty());
+ ASSERT_THAT(filtered, IsEmpty());
// default policy should be preserved
ASSERT_EQ(PredefinedPolicyType::DENY, filtered.defaultPolicy());
using ::testing::UnorderedElementsAreArray;
// Leave policies with given client, given user and any privilege
- auto policiesToStay = filterHelper(wildcardPolicies, { 0, 1, 3 });
+ auto policiesToStay = Helpers::pickFromCollection(wildcardPolicies, { 0, 1, 3 });
PolicyBucket bucket(wildcardPolicies);
auto filtered = bucket.filtered(PolicyKey("c1", "u1", "p2"));
- ASSERT_THAT(filtered.policyCollection(), UnorderedElementsAreArray(policiesToStay));
+ ASSERT_THAT(filtered, UnorderedElementsAreArray(policiesToStay));
}
TEST_F(PolicyBucketFixture, filtered_wildcard_2) {
using ::testing::UnorderedElementsAreArray;
// Leave policies with given client, given user and any privilege
- auto policiesToStay = filterHelper(wildcardPolicies, std::vector<unsigned>{ 2, 3 });
+ auto policiesToStay = Helpers::pickFromCollection(wildcardPolicies, { 2, 3 });
PolicyBucket bucket(wildcardPolicies);
auto filtered = bucket.filtered(PolicyKey("cccc", "u1", "p1"));
- ASSERT_THAT(filtered.policyCollection(), UnorderedElementsAreArray(policiesToStay));
+ ASSERT_THAT(filtered, UnorderedElementsAreArray(policiesToStay));
}
TEST_F(PolicyBucketFixture, filtered_wildcard_3) {
using ::testing::UnorderedElementsAreArray;
// Leave policies with given client, given user and any privilege
- auto policiesToStay = filterHelper(wildcardPolicies, std::vector<unsigned>{ 0, 3 });
+ auto policiesToStay = Helpers::pickFromCollection(wildcardPolicies, { 0, 3 });
PolicyBucket bucket(wildcardPolicies);
auto filtered = bucket.filtered(PolicyKey("c1", "u1", "pppp"));
- ASSERT_THAT(filtered.policyCollection(), UnorderedElementsAreArray(policiesToStay));
+ ASSERT_THAT(filtered, UnorderedElementsAreArray(policiesToStay));
}
TEST_F(PolicyBucketFixture, filtered_wildcard_4) {
using ::testing::UnorderedElementsAreArray;
// Leave policies with given client, given user and any privilege
- auto policiesToStay = filterHelper(wildcardPolicies, std::vector<unsigned>{ 3 });
+ auto policiesToStay = Helpers::pickFromCollection(wildcardPolicies, { 3 });
PolicyBucket bucket(wildcardPolicies);
auto filtered = bucket.filtered(PolicyKey("cccc", "uuuu", "pppp"));
- ASSERT_THAT(filtered.policyCollection(), UnorderedElementsAreArray(policiesToStay));
+ ASSERT_THAT(filtered, UnorderedElementsAreArray(policiesToStay));
}
TEST_F(PolicyBucketFixture, filtered_wildcard_none) {
PolicyBucket bucket({ wildcardPolicies.begin(), wildcardPolicies.begin() + 3 });
auto filtered = bucket.filtered(PolicyKey("cccc", "uuuu", "pppp"));
- ASSERT_THAT(filtered.policyCollection(), IsEmpty());
+ ASSERT_THAT(filtered, IsEmpty());
}
#ifndef HELPERS_H
#define HELPERS_H
+#include <vector>
+
#include "types/PolicyKey.h"
#include "types/PolicyBucketId.h"
namespace Cynara {
+
namespace Helpers {
PolicyKey generatePolicyKey(const PolicyKeyFeature::ValueType &sufix = "");
PolicyBucketId generateBucketId(const PolicyBucketId &sufix = "");
+template <class Collection>
+Collection pickFromCollection(const Collection &original, const std::vector<unsigned> &idx) {
+ Collection filtered;
+ filtered.reserve(idx.size());
+ for (const auto &i : idx) {
+ filtered.push_back(original.at(i));
+ }
+ return filtered;
+}
+
} // namespace Helpers
+
} // namespace Cynara
#endif // HELPERS_H
ASSERT_EQ(1, m_buckets.size());
ASSERT_NE(m_buckets.end(), m_buckets.find(bucketId));
ASSERT_EQ(defaultPolicy, m_buckets.at(bucketId).defaultPolicy());
- ASSERT_THAT(m_buckets.at(bucketId).policyCollection(), IsEmpty());
+ ASSERT_THAT(m_buckets.at(bucketId), IsEmpty());
}
TEST_F(InMemeoryStorageBackendFixture, updateBucket) {
return m_buckets.insert({ bucketId, bucket }).first->second;
}
+ Cynara::Buckets::mapped_type &
+ createBucket(const Cynara::PolicyBucketId &bucketId, const Cynara::PolicyCollection &policies) {
+ auto bucket = Cynara::PolicyBucket(policies);
+ return m_buckets.insert({ bucketId, bucket }).first->second;
+ }
+
void addToBucket(Cynara::PolicyBucketId bucketId, const Cynara::PolicyCollection &policies) {
- std::copy(policies.begin(), policies.end(),
- std::back_inserter(m_buckets[bucketId].policyCollection()));
+ // TODO: Consider altering PolicyMap directly
+ for (const auto &policy : policies) {
+ m_buckets[bucketId].insertPolicy(policy);
+ }
}
virtual ~InMemeoryStorageBackendFixture() {}
* @brief Tests of InMemeoryStorageBackend
*/
-#include <gtest/gtest.h>
#include <gmock/gmock.h>
+#include <gtest/gtest.h>
-#include "types/PolicyType.h"
-#include "types/PolicyKey.h"
-#include "types/PolicyResult.h"
-#include "types/PolicyCollection.h"
#include "exceptions/DefaultBucketDeletionException.h"
#include "exceptions/BucketNotExistsException.h"
-#include "storage/StorageBackend.h"
#include "storage/InMemoryStorageBackend.h"
+#include "storage/StorageBackend.h"
+#include "types/PolicyCollection.h"
+#include "types/PolicyKey.h"
+#include "types/PolicyResult.h"
+#include "types/PolicyType.h"
#include "../../helpers.h"
#include "fakeinmemorystoragebackend.h"
ASSERT_EQ(PredefinedPolicyType::DENY, defaultPolicy.policyType());
}
+// TODO: Refactorize this test to be shorter and clearer
TEST_F(InMemeoryStorageBackendFixture, deleteLinking) {
using ::testing::ReturnRef;
using ::testing::IsEmpty;
// Should delete 1st and 2nd policy from 1st bucket
backend.deleteLinking(testBucket2);
- ASSERT_THAT(m_buckets.at(testBucket1).policyCollection(),
+ ASSERT_THAT(m_buckets.at(testBucket1),
UnorderedElementsAre(policiesToStay.at(0)));
- ASSERT_THAT(m_buckets.at(testBucket2).policyCollection(),
+ ASSERT_THAT(m_buckets.at(testBucket2),
UnorderedElementsAre(policiesToStay.at(1), policiesToStay.at(2)));
- ASSERT_THAT(m_buckets.at(testBucket3).policyCollection(), IsEmpty());
+ ASSERT_THAT(m_buckets.at(testBucket3), IsEmpty());
}
TEST_F(InMemeoryStorageBackendFixture, insertPolicy) {
using ::testing::ReturnRef;
- using ::testing::IsEmpty;
using ::testing::UnorderedElementsAre;
+ using PredefinedPolicyType::ALLOW;
FakeInMemoryStorageBackend backend;
EXPECT_CALL(backend, buckets())
PolicyBucketId bucketId = "test-bucket";
createBucket(bucketId);
- auto policyToAdd = Policy::simpleWithKey(Helpers::generatePolicyKey(), PredefinedPolicyType::ALLOW);
+ auto policyToAdd = Policy::simpleWithKey(Helpers::generatePolicyKey(), ALLOW);
backend.insertPolicy(bucketId, policyToAdd);
- ASSERT_THAT(m_buckets.at(bucketId).policyCollection(), UnorderedElementsAre(policyToAdd));
+ ASSERT_THAT(m_buckets.at(bucketId), UnorderedElementsAre(policyToAdd));
}
TEST_F(InMemeoryStorageBackendFixture, insertPolicyToNonexistentBucket) {
using ::testing::ReturnRef;
- using ::testing::IsEmpty;
- using ::testing::UnorderedElementsAre;
FakeInMemoryStorageBackend backend;
EXPECT_CALL(backend, buckets())
using ::testing::ReturnRef;
using ::testing::IsEmpty;
using ::testing::UnorderedElementsAre;
+ using ::testing::UnorderedElementsAreArray;
using ::testing::ContainerEq;
+ using PredefinedPolicyType::ALLOW;
FakeInMemoryStorageBackend backend;
EXPECT_CALL(backend, buckets())
PolicyBucketId bucketId = "test-bucket";
createBucket(bucketId);
- auto policyToDelete = Policy::simpleWithKey(Helpers::generatePolicyKey(), PredefinedPolicyType::ALLOW);
+ auto policyToDelete = Policy::simpleWithKey(Helpers::generatePolicyKey(), ALLOW);
PolicyCollection otherPolicies = {
- Policy::simpleWithKey(Helpers::generatePolicyKey("other-policy-1"), PredefinedPolicyType::ALLOW),
- Policy::simpleWithKey(Helpers::generatePolicyKey("other-policy-2"), PredefinedPolicyType::ALLOW),
- Policy::simpleWithKey(Helpers::generatePolicyKey("other-policy-3"), PredefinedPolicyType::ALLOW),
+ Policy::simpleWithKey(Helpers::generatePolicyKey("other-policy-1"), ALLOW),
+ Policy::simpleWithKey(Helpers::generatePolicyKey("other-policy-2"), ALLOW),
+ Policy::simpleWithKey(Helpers::generatePolicyKey("other-policy-3"), ALLOW),
};
addToBucket(bucketId, {
backend.deletePolicy(bucketId, policyToDelete->key());
// Check if only policyToDelete has been deleted
- EXPECT_THAT(m_buckets.at(bucketId).policyCollection(), ContainerEq(otherPolicies));
+ EXPECT_THAT(m_buckets.at(bucketId), UnorderedElementsAreArray(otherPolicies));
}
TEST_F(InMemeoryStorageBackendFixture, deletePolicyFromNonexistentBucket) {
EXPECT_CALL(backend, buckets())
.WillOnce(ReturnRef(m_buckets));
- EXPECT_THROW(backend.deletePolicy("non-existent", Helpers::generatePolicyKey()), BucketNotExistsException);
+ EXPECT_THROW(backend.deletePolicy("non-existent", Helpers::generatePolicyKey()),
+ BucketNotExistsException);
}
* @brief Tests of search in InMemeoryStorageBackend
*/
+#include <memory>
+
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "inmemeorystoragebackendfixture.h"
-#include "fakeinmemorystoragebackend.h"
-
#include "types/PolicyBucket.h"
#include "../../helpers.h"
-
-#include <memory>
+#include "fakeinmemorystoragebackend.h"
+#include "inmemeorystoragebackendfixture.h"
using namespace Cynara;
TEST_F(InMemeoryStorageBackendFixture, searchDefault) {
using ::testing::ReturnRef;
- using ::testing::UnorderedElementsAre;
+ using ::testing::UnorderedElementsAreArray;
using ::testing::IsEmpty;
auto pk1 = Helpers::generatePolicyKey("1");
auto pk2 = Helpers::generatePolicyKey("2");
+ auto pk3 = PolicyKey(PolicyKeyFeature::createWildcard(), pk1.user(), pk1.privilege());
auto otherPk = Helpers::generatePolicyKey("-");
- const auto &defaultBucket = createBucket(defaultPolicyBucketId);
-
- addToBucket(defaultPolicyBucketId, {
+ PolicyCollection policies = {
Policy::simpleWithKey(pk1, PredefinedPolicyType::ALLOW),
Policy::simpleWithKey(pk2, PredefinedPolicyType::DENY),
- Policy::simpleWithKey(pk1, PredefinedPolicyType::DENY),
- });
+ Policy::simpleWithKey(pk3, PredefinedPolicyType::DENY),
+ };
+
+ createBucket(defaultPolicyBucketId, policies);
// Just override buckets() accessor
FakeInMemoryStorageBackend backend;
EXPECT_CALL(backend, buckets())
.WillRepeatedly(ReturnRef(m_buckets));
- auto searchDefaultBucket = [&backend](const PolicyKey &key) -> PolicyCollection {
- return backend.searchDefaultBucket(key).policyCollection();
- };
-
- auto defaultPolicyAt = [&defaultBucket] (PolicyCollection::size_type idx) {
- return defaultBucket.policyCollection().at(idx);
- };
+ auto policiesToStay1 = Helpers::pickFromCollection(policies, { 0, 2 });
+ auto policiesToStay2 = Helpers::pickFromCollection(policies, { 1 });
- ASSERT_THAT(searchDefaultBucket(pk1),
- UnorderedElementsAre(defaultPolicyAt(0),defaultPolicyAt(2)));
- ASSERT_THAT(searchDefaultBucket(pk2), UnorderedElementsAre(defaultPolicyAt(1)));
- ASSERT_THAT(searchDefaultBucket(otherPk), IsEmpty());
+ ASSERT_THAT(backend.searchDefaultBucket(pk1), UnorderedElementsAreArray(policiesToStay1));
+ ASSERT_THAT(backend.searchDefaultBucket(pk2), UnorderedElementsAreArray(policiesToStay2));
+ ASSERT_THAT(backend.searchDefaultBucket(otherPk), IsEmpty());
}
));
// Check policy was inserted into bucket
- ASSERT_THAT(buckets.at("").policyCollection(), UnorderedElementsAre(
+ ASSERT_THAT(buckets.at(""), UnorderedElementsAre(
Pointee(Policy(PolicyKey("c", "u", "p"), PolicyResult(PredefinedPolicyType::DENY, "meta")))
));
}
}
TEST(serializer_dump, dump_bucket) {
+ using ::testing::UnorderedElementsAreArray;
+ using PredefinedPolicyType::ALLOW;
+ using PredefinedPolicyType::DENY;
+
PolicyKey pk1 = Helpers::generatePolicyKey("1");
PolicyKey pk2 = Helpers::generatePolicyKey("2");
- PolicyBucket bucket = {{ Policy::simpleWithKey(pk1, PredefinedPolicyType::ALLOW),
- Policy::simpleWithKey(pk2, PredefinedPolicyType::DENY) }};
+ PolicyBucket bucket = {{ Policy::simpleWithKey(pk1, ALLOW),
+ Policy::simpleWithKey(pk2, DENY) }};
- auto outputStream = std::make_shared<std::ostringstream>();
- StorageSerializer serializer(outputStream);
+ auto outStream = std::make_shared<std::stringstream>();
+ StorageSerializer serializer(outStream);
serializer.dump(bucket);
- // TODO: Cynara::PolicyCollection is a vector, but in future version this may change
- // and so, we should not expect the exact order of records in serialized stream
- // See: StorageSerializerFixture::dump_buckets in serialize.cpp
- std::stringstream expected;
- expected
- << expectedPolicyKey(pk1) << ";" << expectedPolicyType(PredefinedPolicyType::ALLOW)<< ";"
- << std::endl
- << expectedPolicyKey(pk2) << ";" << expectedPolicyType(PredefinedPolicyType::DENY) << ";"
- << std::endl;
-
- ASSERT_EQ(expected.str(), outputStream->str());
+ // Split stream into records
+ auto actualRecords = std::vector<std::string>(std::istream_iterator<std::string>(*outStream),
+ std::istream_iterator<std::string>());
+
+ std::vector<std::string> expectedRecords = {
+ expectedPolicyKey(pk1) + ";" + expectedPolicyType(ALLOW) + ";",
+ expectedPolicyKey(pk2) + ";" + expectedPolicyType(DENY) + ";"
+ };
+
+ ASSERT_THAT(actualRecords, UnorderedElementsAreArray(expectedRecords));
}
TEST(serializer_dump, dump_bucket_bucket) {
+ using ::testing::UnorderedElementsAreArray;
+ using PredefinedPolicyType::BUCKET;
+ using PredefinedPolicyType::DENY;
+
PolicyKey pk1 = Helpers::generatePolicyKey("1");
PolicyKey pk2 = Helpers::generatePolicyKey("2");
PolicyKey pk3 = Helpers::generatePolicyKey("3");
PolicyBucketId bucketId = Helpers::generateBucketId();
PolicyBucket bucket = {{ Policy::bucketWithKey(pk1, bucketId),
- Policy::simpleWithKey(pk2, PredefinedPolicyType::DENY),
+ Policy::simpleWithKey(pk2, DENY),
Policy::bucketWithKey(pk3, bucketId) }};
- auto outputStream = std::make_shared<std::ostringstream>();
- StorageSerializer serializer(outputStream);
+ auto outStream = std::make_shared<std::stringstream>();
+ StorageSerializer serializer(outStream);
serializer.dump(bucket);
- // TODO: Cynara::PolicyCollection is a vector, but in future version this may change
- // and so, we should not expect the exact order of records in serialized stream
- // See: StorageSerializerFixture::dump_buckets in serialize.cpp
- std::stringstream expected;
- expected
- << expectedPolicyKey(pk1) << ";" << expectedPolicyType(PredefinedPolicyType::BUCKET) << ";"
- << bucketId << std::endl
- << expectedPolicyKey(pk2) << ";" << expectedPolicyType(PredefinedPolicyType::DENY) << ";"
- << std::endl
- << expectedPolicyKey(pk3) << ";" << expectedPolicyType(PredefinedPolicyType::BUCKET) << ";"
- << bucketId << std::endl;
-
- ASSERT_EQ(expected.str(), outputStream->str());
+ // Split stream into records
+ auto actualRecords = std::vector<std::string>(std::istream_iterator<std::string>(*outStream),
+ std::istream_iterator<std::string>());
+
+ std::vector<std::string> expectedRecords = {
+ expectedPolicyKey(pk1) + ";" + expectedPolicyType(BUCKET) + ";" + bucketId,
+ expectedPolicyKey(pk2) + ";" + expectedPolicyType(DENY) + ";",
+ expectedPolicyKey(pk3) + ";" + expectedPolicyType(BUCKET) + ";" + bucketId
+ };
+
+ ASSERT_THAT(actualRecords, UnorderedElementsAreArray(expectedRecords));
}
BucketDeserializer deserializer(ioStream);
const auto loadedPolicies = deserializer.loadPolicies();
- const auto &expectedPolicies = bucket.policyCollection();
+ PolicyCollection expectedPolicies;
+ std::copy(bucket.begin(), bucket.end(), std::back_inserter(expectedPolicies));
ASSERT_THAT(loadedPolicies, UnorderedElementsAre(
PolicyAtPtrEq(expectedPolicies.at(0)),
ASSERT_EQ(PredefinedPolicyType::DENY, storage.checkPolicy(pk).policyType());
// Add ALLOW to default bucket -- return ALLOW
- bucket.policyCollection().push_back(Policy::simpleWithKey(pk, PredefinedPolicyType::ALLOW));
+ bucket.insertPolicy(Policy::simpleWithKey(pk, PredefinedPolicyType::ALLOW));
ASSERT_EQ(PredefinedPolicyType::ALLOW, storage.checkPolicy(pk).policyType());
// Add DENY to default bucket -- return DENY
- bucket.policyCollection().push_back(Policy::simpleWithKey(pk, PredefinedPolicyType::DENY));
+ bucket.insertPolicy(Policy::simpleWithKey(pk, PredefinedPolicyType::DENY));
ASSERT_EQ(PredefinedPolicyType::DENY, storage.checkPolicy(pk).policyType());
}
ASSERT_EQ(PredefinedPolicyType::DENY, storage.checkPolicy(pk).policyType());
// Add ALLOW to bucket, so return ALLOW
- additionalBucket.policyCollection().push_back(Policy::simpleWithKey(pk, PredefinedPolicyType::ALLOW));
+ additionalBucket.insertPolicy(Policy::simpleWithKey(pk, PredefinedPolicyType::ALLOW));
ASSERT_EQ(PredefinedPolicyType::ALLOW, storage.checkPolicy(pk).policyType());
// Add DENY to default bucket -- return DENY, even though ALLOW in other bucket
- defaultBucket.policyCollection().push_back(Policy::simpleWithKey(pk, PredefinedPolicyType::DENY));
+ defaultBucket.insertPolicy(Policy::simpleWithKey(pk, PredefinedPolicyType::DENY));
ASSERT_EQ(PredefinedPolicyType::DENY, storage.checkPolicy(pk).policyType());
}
const auto &policies = group.second;
for (const auto &policy : policies) {
- EXPECT_CALL(backend, searchBucket(bucketId, policy.key()))
- .WillOnce(Return(PolicyBucket()));
- EXPECT_CALL(backend, insertPolicy(bucketId, Pointee(policy)));
- }
- }
-
- storage.insertPolicies(policiesToInsert);
-}
-
-TEST(storage, updatePolicies) {
- using ::testing::Pointee;
- using ::testing::Return;
- FakeStorageBackend backend;
- Storage storage(backend);
-
- PolicyBucketId testBucket1 = "test-bucket-1";
- PolicyBucketId testBucket2 = "test-bucket-2";
-
- typedef std::pair<PolicyBucketId, std::vector<Policy>> BucketPolicyPair;
-
- auto createPolicy = [] (const std::string &keySuffix, const PolicyType &type) -> Policy {
- return Policy(Helpers::generatePolicyKey(keySuffix), type);
- };
-
- std::map<PolicyBucketId, std::vector<Policy>> policiesToInsert = {
- BucketPolicyPair(testBucket1, {
- createPolicy("1", PredefinedPolicyType::ALLOW),
- createPolicy("2", PredefinedPolicyType::DENY),
- createPolicy("3", PredefinedPolicyType::DENY)
- }),
- BucketPolicyPair(testBucket2, {
- createPolicy("4", PredefinedPolicyType::ALLOW),
- createPolicy("5", PredefinedPolicyType::ALLOW)
- })
- };
-
- for (const auto &group : policiesToInsert) {
- const auto &bucketId = group.first;
- const auto &policies = group.second;
-
- for (const auto &policy : policies) {
- PolicyBucket searchResult(PolicyCollection { std::make_shared<Policy>(policy) });
- EXPECT_CALL(backend, searchBucket(bucketId, policy.key()))
- .WillOnce(Return(searchResult));
- EXPECT_CALL(backend, deletePolicy(bucketId, policy.key()));
EXPECT_CALL(backend, insertPolicy(bucketId, Pointee(policy)));
}
}