* @brief Implementation of Cynara::StorageSerializer methods
*/
-#include "StorageSerializer.h"
+#include <algorithm>
+#include <ios>
+#include <iostream>
#include "types/PolicyBucket.h"
#include "types/PolicyCollection.h"
-#include <algorithm>
+#include "StorageSerializer.h"
namespace Cynara {
StorageSerializer::StorageSerializer(std::ostream &os) : m_outStream(os) {}
+void StorageSerializer::dump(const InMemoryStorageBackend::Buckets &buckets,
+ BucketStreamOpener streamOpener) {
+
+ for (const auto bucketIter : buckets) {
+ const auto &bucket = bucketIter.second;
+
+ dumpFields(bucket.id(), bucket.defaultPolicy().policyType(),
+ bucket.defaultPolicy().metadata());
+ }
+
+ for (const auto bucketIter : buckets) {
+ const auto &bucketId = bucketIter.first;
+ const auto &bucket = bucketIter.second;
+ auto bucketSerializer = streamOpener(bucketId);
+
+ if (bucketSerializer != nullptr) {
+ bucketSerializer->dump(bucket);
+ } else {
+ // TODO: Throw?
+ }
+ }
+}
+
void StorageSerializer::dump(const PolicyBucket& bucket) {
const auto &policies = bucket.policyCollection();
}
void StorageSerializer::dump(const PolicyType &policyType) {
- outStream() << policyType;
+ auto oldFormat = m_outStream.flags();
+ outStream() << "0x" << std::uppercase << std::hex << policyType;
+ m_outStream.flags(oldFormat);
}
void StorageSerializer::dump(const PolicyResult::PolicyMetadata &metadata) {
#ifndef SRC_SERVICE_STORAGE_STORAGESERIALIZER_H_
#define SRC_SERVICE_STORAGE_STORAGESERIALIZER_H_
+#include "InMemoryStorageBackend.h"
#include "types/PolicyBucketId.h"
#include "types/PolicyCollection.h"
#include "types/PolicyResult.h"
class StorageSerializer {
public:
+ typedef std::function<std::shared_ptr<StorageSerializer>(const PolicyBucketId &)>
+ BucketStreamOpener;
+
StorageSerializer(std::ostream &os);
- void dump(const PolicyBucket &bucket);
+ virtual ~StorageSerializer() = default;
+
+ virtual void dump(const InMemoryStorageBackend::Buckets &buckets,
+ BucketStreamOpener streamOpener);
+ virtual void dump(const PolicyBucket &bucket);
protected:
template<typename Arg1, typename... Args>
- inline void dumpFields(const Arg1 arg1, const Args&... args) {
+ inline void dumpFields(const Arg1 &arg1, const Args&... args) {
dump(arg1);
if (sizeof...(Args) > 0) {
outStream() << fieldSeparator();
storage/serializer/bucket_load.cpp
storage/serializer/deserialize.cpp
storage/serializer/dump.cpp
+ storage/serializer/serialize.cpp
common/types/policybucket.cpp
helpers.cpp
)
* @file dump.cpp
* @author Aleksander Zdyb <a.zdyb@partner.samsung.com>
* @version 1.0
- * @brief Test for dumping feature of Cynara::Serializer
+ * @brief Tests for dumping feature of Cynara::StorageSerializer
*/
#include <gtest/gtest.h>
PolicyKey pk1 = Helpers::generatePolicyKey("1");
PolicyKey pk2 = Helpers::generatePolicyKey("2");
-
PolicyBucket bucket = {{ Policy::simpleWithKey(pk1, PredefinedPolicyType::ALLOW),
Policy::simpleWithKey(pk2, PredefinedPolicyType::DENY) }};
StorageSerializer serializer(outputStream);
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 << pk1.toString() << ";" << PredefinedPolicyType::ALLOW << ";" << "\n"
- << pk2.toString() << ";" << PredefinedPolicyType::DENY << ";" << "\n";
+ expected
+ << std::hex << std::uppercase
+ << pk1.toString() << ";" << "0x" << PredefinedPolicyType::ALLOW << ";" << "\n"
+ << pk2.toString() << ";" << "0x" << PredefinedPolicyType::DENY << ";" << "\n";
ASSERT_EQ(expected.str(), outputStream.str());
}
StorageSerializer serializer(outputStream);
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 << pk1.toString() << ";" << PredefinedPolicyType::BUCKET << ";" << bucketId << "\n"
- << pk2.toString() << ";" << PredefinedPolicyType::DENY << ";" << "\n"
- << pk3.toString() << ";" << PredefinedPolicyType::BUCKET << ";" << bucketId << "\n";
+ expected
+ << std::hex << std::uppercase
+ << pk1.toString() << ";" << "0x" << PredefinedPolicyType::BUCKET << ";" << bucketId << "\n"
+ << pk2.toString() << ";" << "0x" << PredefinedPolicyType::DENY << ";" << "\n"
+ << pk3.toString() << ";" << "0x" << PredefinedPolicyType::BUCKET << ";" << bucketId << "\n";
ASSERT_EQ(expected.str(), outputStream.str());
}
--- /dev/null
+/*
+ * 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 serialize.cpp
+ * @author Aleksander Zdyb <a.zdyb@partner.samsung.com>
+ * @version 1.0
+ * @brief Tests for dumping feature of Cynara::StorageSerializer
+ */
+
+#include <iterator>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <storage/InMemoryStorageBackend.h>
+#include <storage/StorageSerializer.h>
+#include <types/PolicyBucketId.h>
+
+class FakeStreamForBucketId {
+public:
+ MOCK_METHOD1(streamForBucketId,
+ std::shared_ptr<Cynara::StorageSerializer>(const Cynara::PolicyBucketId &));
+
+ Cynara::StorageSerializer::BucketStreamOpener streamOpener() {
+ return std::bind(&FakeStreamForBucketId::streamForBucketId, this, std::placeholders::_1);
+ }
+};
+
+// Fake StorageSerializer for Cynara::PolicyBucket
+class FakeStorageSerializer : public Cynara::StorageSerializer {
+public:
+ FakeStorageSerializer() : Cynara::StorageSerializer(outStream) {}
+ MOCK_METHOD1(dump, void(const Cynara::PolicyBucket &bucket));
+ std::ostringstream outStream;
+};
+
+class StorageSerializerFixture : public ::testing::Test {
+public:
+ virtual ~StorageSerializerFixture() = default;
+
+ Cynara::InMemoryStorageBackend::Buckets buckets;
+ FakeStreamForBucketId fakeStreamOpener;
+};
+
+using namespace Cynara;
+
+// Be sure no calls to streamForBucketId() are made
+// and output stream is not touched
+TEST_F(StorageSerializerFixture, dump_buckets_empty) {
+ std::ostringstream outStream;
+ StorageSerializer serializer(outStream);
+ serializer.dump(InMemoryStorageBackend::Buckets(), fakeStreamOpener.streamOpener());
+
+ // Stream should be empty
+ ASSERT_EQ(0, outStream.tellp());
+}
+
+TEST_F(StorageSerializerFixture, dump_buckets) {
+ using ::testing::_;
+ using ::testing::Property;
+ using ::testing::Return;
+ using ::testing::UnorderedElementsAreArray;
+
+ // Will be returned as serializer for buckets
+ auto fakeBucketSerializer = std::make_shared<FakeStorageSerializer>();
+
+ buckets = {
+ { "bucket1", PolicyBucket("bucket1", PredefinedPolicyType::DENY) },
+ { "bucket2", PolicyBucket("bucket2", PredefinedPolicyType::DENY) },
+ { "bucket3",
+ PolicyBucket("bucket3", PolicyResult(PredefinedPolicyType::BUCKET, "bucket2")) }
+ };
+
+ std::stringstream outStream;
+ StorageSerializer dbSerializer(outStream);
+
+ // Make sure stream was opened for each bucket
+ EXPECT_CALL(fakeStreamOpener, streamForBucketId(_))
+ .Times(buckets.size()).WillRepeatedly(Return(fakeBucketSerializer));
+
+ // Make sure every bucket was dumped
+ for (const auto &bucket : buckets) {
+ EXPECT_CALL(*fakeBucketSerializer, dump(Property(&PolicyBucket::id, bucket.first)));
+ }
+
+ dbSerializer.dump(buckets, fakeStreamOpener.streamOpener());
+
+ std::vector<std::string> expectedRecords = {
+ "bucket1;0x0;",
+ "bucket2;0x0;",
+ "bucket3;0xFFFE;bucket2"
+ };
+
+ // Split stream into records
+ auto actualRecords = std::vector<std::string>(std::istream_iterator<std::string>(outStream),
+ std::istream_iterator<std::string>());
+
+ ASSERT_THAT(actualRecords, UnorderedElementsAreArray(expectedRecords));
+}