format code base in Mozilla style

This commit is contained in:
Mindaugas Vinkelis
2022-12-01 13:50:03 +02:00
parent d690908541
commit 3e02d0ca44
106 changed files with 15083 additions and 12518 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,24 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/brief_syntax.h>
#include <bitsery/brief_syntax/array.h>
@@ -40,421 +40,464 @@
#include <bitsery/brief_syntax/tuple.h>
#include <bitsery/brief_syntax/variant.h>
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::tuple and std::variant brief syntax tests")
#pragma message( \
"C++17 and /Zc:__cplusplus option is required to enable std::tuple and std::variant brief syntax tests")
#else
#pragma message("C++17 is required to enable std::tuple and std::variant brief syntax tests")
#pragma message( \
"C++17 is required to enable std::tuple and std::variant brief syntax tests")
#endif
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
#include <atomic>
#include <utility>
using testing::Eq;
TEST(BriefSyntax, FundamentalTypesAndBool) {
int ti = 8745;
MyEnumClass te = MyEnumClass::E4;
float tf = 485.042f;
double td = -454184.48445;
bool tb = true;
SerializationContext ctx{};
ctx.createSerializer()(ti, te, tf, td, tb);
TEST(BriefSyntax, FundamentalTypesAndBool)
{
int ti = 8745;
MyEnumClass te = MyEnumClass::E4;
float tf = 485.042f;
double td = -454184.48445;
bool tb = true;
SerializationContext ctx{};
ctx.createSerializer()(ti, te, tf, td, tb);
//result
int ri{};
MyEnumClass re{};
float rf{};
double rd{};
bool rb{};
ctx.createDeserializer()(ri, re, rf, rd, rb);
// result
int ri{};
MyEnumClass re{};
float rf{};
double rd{};
bool rb{};
ctx.createDeserializer()(ri, re, rf, rd, rb);
//test
EXPECT_THAT(ri, Eq(ti));
EXPECT_THAT(re, Eq(te));
EXPECT_THAT(rf, Eq(tf));
EXPECT_THAT(rd, Eq(td));
EXPECT_THAT(rb, Eq(tb));
// test
EXPECT_THAT(ri, Eq(ti));
EXPECT_THAT(re, Eq(te));
EXPECT_THAT(rf, Eq(tf));
EXPECT_THAT(rd, Eq(td));
EXPECT_THAT(rb, Eq(tb));
}
TEST(BriefSyntax, UseObjectFncInsteadOfValueN) {
int ti = 8745;
MyEnumClass te = MyEnumClass::E4;
float tf = 485.042f;
double td = -454184.48445;
bool tb = true;
SerializationContext ctx;
auto& ser = ctx.createSerializer();
ser.object(ti);
ser.object(te);
ser.object(tf);
ser.object(td);
ser.object(tb);
TEST(BriefSyntax, UseObjectFncInsteadOfValueN)
{
int ti = 8745;
MyEnumClass te = MyEnumClass::E4;
float tf = 485.042f;
double td = -454184.48445;
bool tb = true;
SerializationContext ctx;
auto& ser = ctx.createSerializer();
ser.object(ti);
ser.object(te);
ser.object(tf);
ser.object(td);
ser.object(tb);
//result
int ri{};
MyEnumClass re{};
float rf{};
double rd{};
bool rb{};
auto& des = ctx.createDeserializer();
des.object(ri);
des.object(re);
des.object(rf);
des.object(rd);
des.object(rb);
// result
int ri{};
MyEnumClass re{};
float rf{};
double rd{};
bool rb{};
auto& des = ctx.createDeserializer();
des.object(ri);
des.object(re);
des.object(rf);
des.object(rd);
des.object(rb);
//test
EXPECT_THAT(ri, Eq(ti));
EXPECT_THAT(re, Eq(te));
EXPECT_THAT(rf, Eq(tf));
EXPECT_THAT(rd, Eq(td));
EXPECT_THAT(rb, Eq(tb));
// test
EXPECT_THAT(ri, Eq(ti));
EXPECT_THAT(re, Eq(te));
EXPECT_THAT(rf, Eq(tf));
EXPECT_THAT(rd, Eq(td));
EXPECT_THAT(rb, Eq(tb));
}
TEST(BriefSyntax, MixDifferentSyntax) {
int ti = 8745;
MyEnumClass te = MyEnumClass::E4;
float tf = 485.042f;
double td = -454184.48445;
bool tb = true;
SerializationContext ctx;
auto& ser = ctx.createSerializer();
ser.value<sizeof(ti)>(ti);
ser(te, tf, td);
ser.object(tb);
TEST(BriefSyntax, MixDifferentSyntax)
{
int ti = 8745;
MyEnumClass te = MyEnumClass::E4;
float tf = 485.042f;
double td = -454184.48445;
bool tb = true;
SerializationContext ctx;
auto& ser = ctx.createSerializer();
ser.value<sizeof(ti)>(ti);
ser(te, tf, td);
ser.object(tb);
//result
int ri{};
MyEnumClass re{};
float rf{};
double rd{};
bool rb{};
auto& des = ctx.createDeserializer();
des(ri, re, rf);
des.value8b(rd);
des.object(rb);
// result
int ri{};
MyEnumClass re{};
float rf{};
double rd{};
bool rb{};
auto& des = ctx.createDeserializer();
des(ri, re, rf);
des.value8b(rd);
des.object(rb);
//test
EXPECT_THAT(ri, Eq(ti));
EXPECT_THAT(re, Eq(te));
EXPECT_THAT(rf, Eq(tf));
EXPECT_THAT(rd, Eq(td));
EXPECT_THAT(rb, Eq(tb));
// test
EXPECT_THAT(ri, Eq(ti));
EXPECT_THAT(re, Eq(te));
EXPECT_THAT(rf, Eq(tf));
EXPECT_THAT(rd, Eq(td));
EXPECT_THAT(rb, Eq(tb));
}
template<typename T>
T procBriefSyntax(const T& testData) {
SerializationContext ctx;
ctx.createSerializer()(testData);
T res{};
ctx.createDeserializer()(res);
return res;
T
procBriefSyntax(const T& testData)
{
SerializationContext ctx;
ctx.createSerializer()(testData);
T res{};
ctx.createDeserializer()(res);
return res;
}
template<typename T>
T&& procBriefSyntaxRvalue(T&& init_value, const T& testData) {
SerializationContext ctx;
ctx.createSerializer()(testData);
ctx.createDeserializer()(init_value);
return std::move(init_value);
T&&
procBriefSyntaxRvalue(T&& init_value, const T& testData)
{
SerializationContext ctx;
ctx.createSerializer()(testData);
ctx.createDeserializer()(init_value);
return std::move(init_value);
}
template<typename T>
T procBriefSyntaxWithMaxSize(const T& testData) {
SerializationContext ctx;
ctx.createSerializer()(bitsery::maxSize(testData, 100));
T res{};
ctx.createDeserializer()(bitsery::maxSize(res, 100));
return res;
T
procBriefSyntaxWithMaxSize(const T& testData)
{
SerializationContext ctx;
ctx.createSerializer()(bitsery::maxSize(testData, 100));
T res{};
ctx.createDeserializer()(bitsery::maxSize(res, 100));
return res;
}
TEST(BriefSyntax, CStyleArrayForValueTypesAsContainer) {
const int t1[3]{8748, -484, 45};
int r1[3]{0, 0, 0};
TEST(BriefSyntax, CStyleArrayForValueTypesAsContainer)
{
const int t1[3]{ 8748, -484, 45 };
int r1[3]{ 0, 0, 0 };
SerializationContext ctx;
ctx.createSerializer()(bitsery::asContainer(t1));
ctx.createDeserializer()(bitsery::asContainer(r1));
SerializationContext ctx;
ctx.createSerializer()(bitsery::asContainer(t1));
ctx.createDeserializer()(bitsery::asContainer(r1));
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
}
TEST(BriefSyntax, CStyleArrayForIntegralTypesAsText) {
const char t1[3]{"hi"};
char r1[3]{0, 0, 0};
TEST(BriefSyntax, CStyleArrayForIntegralTypesAsText)
{
const char t1[3]{ "hi" };
char r1[3]{ 0, 0, 0 };
SerializationContext ctx;
ctx.createSerializer()(bitsery::asText(t1));
ctx.createDeserializer()(bitsery::asText(r1));
SerializationContext ctx;
ctx.createSerializer()(bitsery::asText(t1));
ctx.createDeserializer()(bitsery::asText(r1));
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
}
TEST(BriefSyntax, CStyleArray) {
const MyEnumClass t1[3]{MyEnumClass::E1, MyEnumClass::E4, MyEnumClass::E2};
MyEnumClass r1[3]{};
TEST(BriefSyntax, CStyleArray)
{
const MyEnumClass t1[3]{ MyEnumClass::E1, MyEnumClass::E4, MyEnumClass::E2 };
MyEnumClass r1[3]{};
SerializationContext ctx;
ctx.createSerializer()(t1);
ctx.createDeserializer()(r1);
SerializationContext ctx;
ctx.createSerializer()(t1);
ctx.createDeserializer()(r1);
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
EXPECT_THAT(r1, ::testing::ContainerEq(t1));
}
TEST(BriefSyntax, StdString) {
std::string t1{"my nice string"};
std::string t2{};
TEST(BriefSyntax, StdString)
{
std::string t1{ "my nice string" };
std::string t2{};
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
}
TEST(BriefSyntax, StdArray) {
std::array<int, 3> t1{8748, -484, 45};
std::array<int, 0> t2{};
TEST(BriefSyntax, StdArray)
{
std::array<int, 3> t1{ 8748, -484, 45 };
std::array<int, 0> t2{};
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
}
TEST(BriefSyntax, StdVector) {
std::vector<int> t1{8748, -484, 45};
std::vector<float> t2{5.f, 0.198f};
TEST(BriefSyntax, StdVector)
{
std::vector<int> t1{ 8748, -484, 45 };
std::vector<float> t2{ 5.f, 0.198f };
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
}
TEST(BriefSyntax, StdList) {
std::list<int> t1{8748, -484, 45};
std::list<float> t2{5.f, 0.198f};
TEST(BriefSyntax, StdList)
{
std::list<int> t1{ 8748, -484, 45 };
std::list<float> t2{ 5.f, 0.198f };
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
}
TEST(BriefSyntax, StdForwardList) {
std::forward_list<int> t1{8748, -484, 45};
std::forward_list<float> t2{5.f, 0.198f};
TEST(BriefSyntax, StdForwardList)
{
std::forward_list<int> t1{ 8748, -484, 45 };
std::forward_list<float> t2{ 5.f, 0.198f };
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
}
TEST(BriefSyntax, StdDeque) {
std::deque<int> t1{8748, -484, 45};
std::deque<float> t2{5.f, 0.198f};
TEST(BriefSyntax, StdDeque)
{
std::deque<int> t1{ 8748, -484, 45 };
std::deque<float> t2{ 5.f, 0.198f };
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t2), Eq(t2));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t2), Eq(t2));
}
TEST(BriefSyntax, StdQueue) {
std::queue<std::string> t1;
t1.push("first");
t1.push("second string");
TEST(BriefSyntax, StdQueue)
{
std::queue<std::string> t1;
t1.push("first");
t1.push("second string");
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
}
TEST(BriefSyntax, StdPriorityQueue) {
std::priority_queue<std::string> t1;
t1.push("first");
t1.push("second string");
t1.push("third");
t1.push("fourth");
auto r1 = procBriefSyntax(t1);
//we cannot compare priority queue directly
TEST(BriefSyntax, StdPriorityQueue)
{
std::priority_queue<std::string> t1;
t1.push("first");
t1.push("second string");
t1.push("third");
t1.push("fourth");
auto r1 = procBriefSyntax(t1);
// we cannot compare priority queue directly
EXPECT_THAT(r1.size(), Eq(t1.size()));
for (auto i = 0u; i < r1.size(); ++i) {
EXPECT_THAT(r1.top(), Eq(t1.top()));
r1.pop();
t1.pop();
}
EXPECT_THAT(r1.size(), Eq(t1.size()));
for (auto i = 0u; i < r1.size(); ++i) {
EXPECT_THAT(r1.top(), Eq(t1.top()));
r1.pop();
t1.pop();
}
}
TEST(BriefSyntax, StdStack) {
std::stack<std::string> t1;
t1.push("first");
t1.push("second string");
TEST(BriefSyntax, StdStack)
{
std::stack<std::string> t1;
t1.push("first");
t1.push("second string");
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
}
TEST(BriefSyntax, StdUnorderedMap) {
std::unordered_map<int, int> t1;
t1.emplace(3423, 624);
t1.emplace(-5484, -845);
TEST(BriefSyntax, StdUnorderedMap)
{
std::unordered_map<int, int> t1;
t1.emplace(3423, 624);
t1.emplace(-5484, -845);
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
}
TEST(BriefSyntax, StdUnorderedMultiMap) {
std::unordered_multimap<std::string, int> t1;
t1.emplace("one", 624);
t1.emplace("two", -845);
t1.emplace("one", 897);
TEST(BriefSyntax, StdUnorderedMultiMap)
{
std::unordered_multimap<std::string, int> t1;
t1.emplace("one", 624);
t1.emplace("two", -845);
t1.emplace("one", 897);
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
}
TEST(BriefSyntax, StdMap) {
std::map<int, int> t1;
t1.emplace(3423, 624);
t1.emplace(-5484, -845);
TEST(BriefSyntax, StdMap)
{
std::map<int, int> t1;
t1.emplace(3423, 624);
t1.emplace(-5484, -845);
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
}
TEST(BriefSyntax, StdMultiMap) {
std::multimap<std::string, int> t1;
t1.emplace("one", 624);
t1.emplace("two", -845);
t1.emplace("one", 897);
TEST(BriefSyntax, StdMultiMap)
{
std::multimap<std::string, int> t1;
t1.emplace("one", 624);
t1.emplace("two", -845);
t1.emplace("one", 897);
auto res = procBriefSyntax(t1);
//same key values is not ordered, and operator == compares each element at same position
//so we need to compare our selves
EXPECT_THAT(res.size(), Eq(3));
for (auto it = t1.begin(); it != t1.end();) {
const auto lr = t1.equal_range(it->first);
const auto rr = res.equal_range(it->first);
EXPECT_TRUE(std::distance(lr.first, lr.second) == std::distance(rr.first, rr.second));
EXPECT_TRUE(std::is_permutation(lr.first, lr.second, rr.first));
it = lr.second;
}
auto res = procBriefSyntax(t1);
// same key values is not ordered, and operator == compares each element at
// same position so we need to compare our selves
EXPECT_THAT(res.size(), Eq(3));
for (auto it = t1.begin(); it != t1.end();) {
const auto lr = t1.equal_range(it->first);
const auto rr = res.equal_range(it->first);
EXPECT_TRUE(std::distance(lr.first, lr.second) ==
std::distance(rr.first, rr.second));
EXPECT_TRUE(std::is_permutation(lr.first, lr.second, rr.first));
it = lr.second;
}
}
TEST(BriefSyntax, StdUnorderedSet) {
std::unordered_set<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
TEST(BriefSyntax, StdUnorderedSet)
{
std::unordered_set<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
}
TEST(BriefSyntax, StdUnorderedMultiSet) {
std::unordered_multiset<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
t1.emplace("one");
TEST(BriefSyntax, StdUnorderedMultiSet)
{
std::unordered_multiset<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
t1.emplace("one");
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
}
TEST(BriefSyntax, StdSet) {
std::set<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
TEST(BriefSyntax, StdSet)
{
std::set<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
}
TEST(BriefSyntax, StdMultiSet) {
std::multiset<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
t1.emplace("one");
t1.emplace("two");
TEST(BriefSyntax, StdMultiSet)
{
std::multiset<std::string> t1;
t1.emplace("one");
t1.emplace("two");
t1.emplace("three");
t1.emplace("one");
t1.emplace("two");
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
EXPECT_TRUE(procBriefSyntax(t1) == t1);
EXPECT_TRUE(procBriefSyntaxWithMaxSize(t1) == t1);
}
TEST(BriefSyntax, StdSmartPtr) {
std::shared_ptr<int> dataShared1(new int{4});
std::weak_ptr<int> dataWeak1(dataShared1);
std::unique_ptr<std::string> dataUnique1{new std::string{"hello world"}};
TEST(BriefSyntax, StdSmartPtr)
{
std::shared_ptr<int> dataShared1(new int{ 4 });
std::weak_ptr<int> dataWeak1(dataShared1);
std::unique_ptr<std::string> dataUnique1{ new std::string{ "hello world" } };
bitsery::ext::PointerLinkingContext plctx1{};
BasicSerializationContext<bitsery::ext::PointerLinkingContext> ctx;
ctx.createSerializer(plctx1)(dataShared1, dataWeak1, dataUnique1);
bitsery::ext::PointerLinkingContext plctx1{};
BasicSerializationContext<bitsery::ext::PointerLinkingContext> ctx;
ctx.createSerializer(plctx1)(dataShared1, dataWeak1, dataUnique1);
std::shared_ptr<int> resShared1{};
std::weak_ptr<int> resWeak1{};
std::unique_ptr<std::string> resUnique1{};
ctx.createDeserializer(plctx1)(resShared1, resWeak1, resUnique1);
//clear shared state from pointer linking context
plctx1.clearSharedState();
std::shared_ptr<int> resShared1{};
std::weak_ptr<int> resWeak1{};
std::unique_ptr<std::string> resUnique1{};
ctx.createDeserializer(plctx1)(resShared1, resWeak1, resUnique1);
// clear shared state from pointer linking context
plctx1.clearSharedState();
EXPECT_TRUE(plctx1.isValid());
EXPECT_THAT(*resShared1, Eq(*dataShared1));
EXPECT_THAT(*resWeak1.lock(), Eq(*dataWeak1.lock()));
EXPECT_THAT(*resUnique1, Eq(*dataUnique1));
EXPECT_TRUE(plctx1.isValid());
EXPECT_THAT(*resShared1, Eq(*dataShared1));
EXPECT_THAT(*resWeak1.lock(), Eq(*dataWeak1.lock()));
EXPECT_THAT(*resUnique1, Eq(*dataUnique1));
}
TEST(BriefSyntax, StdDuration) {
std::chrono::duration<int64_t, std::milli> t1{54654};
EXPECT_TRUE(procBriefSyntax(t1) == t1);
TEST(BriefSyntax, StdDuration)
{
std::chrono::duration<int64_t, std::milli> t1{ 54654 };
EXPECT_TRUE(procBriefSyntax(t1) == t1);
}
TEST(BriefSyntax, StdTimePoint) {
using Duration = std::chrono::duration<double, std::milli>;
using TP = std::chrono::time_point<std::chrono::system_clock, Duration>;
TEST(BriefSyntax, StdTimePoint)
{
using Duration = std::chrono::duration<double, std::milli>;
using TP = std::chrono::time_point<std::chrono::system_clock, Duration>;
TP data{Duration{874656.4798}};
EXPECT_TRUE(procBriefSyntax(data) == data);
TP data{ Duration{ 874656.4798 } };
EXPECT_TRUE(procBriefSyntax(data) == data);
}
TEST(BriefSyntax, StdAtomic) {
std::atomic<int32_t> atm0{54654};
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<int32_t>{}, atm0) == atm0);
TEST(BriefSyntax, StdAtomic)
{
std::atomic<int32_t> atm0{ 54654 };
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<int32_t>{}, atm0) == atm0);
std::atomic<bool> atm1{false};
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<bool>{}, atm1) == atm1);
std::atomic<bool> atm1{ false };
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<bool>{}, atm1) == atm1);
std::atomic<bool> atm2{true};
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<bool>{}, atm2) == atm2);
std::atomic<bool> atm2{ true };
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<bool>{}, atm2) == atm2);
std::atomic<uint16_t> atm3;
atm3.store(0x1337);
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<uint16_t>{}, atm3).load() == 0x1337);
std::atomic<uint16_t> atm3;
atm3.store(0x1337);
EXPECT_TRUE(procBriefSyntaxRvalue(std::atomic<uint16_t>{}, atm3).load() ==
0x1337);
}
#if __cplusplus > 201402L
TEST(BriefSyntax, StdTuple) {
std::tuple<int, std::string, std::vector<char>> t1{5,"hello hello", {'A','B','C'}};
EXPECT_TRUE(procBriefSyntax(t1) == t1);
TEST(BriefSyntax, StdTuple)
{
std::tuple<int, std::string, std::vector<char>> t1{ 5,
"hello hello",
{ 'A', 'B', 'C' } };
EXPECT_TRUE(procBriefSyntax(t1) == t1);
}
TEST(BriefSyntax, StdVariant) {
std::variant<float, std::string, std::chrono::milliseconds> t1{std::string("hello hello")};
EXPECT_TRUE(procBriefSyntax(t1) == t1);
TEST(BriefSyntax, StdVariant)
{
std::variant<float, std::string, std::chrono::milliseconds> t1{ std::string(
"hello hello") };
EXPECT_TRUE(procBriefSyntax(t1) == t1);
}
#endif
TEST(BriefSyntax, NestedTypes) {
std::unordered_map<std::string, std::vector<std::string>> t1;
t1.emplace("my key", std::vector<std::string>{"very", "nice", "string"});
t1.emplace("other key", std::vector<std::string>{"just a string"});
TEST(BriefSyntax, NestedTypes)
{
std::unordered_map<std::string, std::vector<std::string>> t1;
t1.emplace("my key", std::vector<std::string>{ "very", "nice", "string" });
t1.emplace("other key", std::vector<std::string>{ "just a string" });
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
EXPECT_THAT(procBriefSyntax(t1), Eq(t1));
EXPECT_THAT(procBriefSyntaxWithMaxSize(t1), Eq(t1));
}

View File

@@ -1,184 +1,195 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/deserializer.h>
#include <bitsery/ext/value_range.h>
#include <bitsery/serializer.h>
#include <bitsery/deserializer.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
using testing::ContainerEq;
using bitsery::EndiannessType;
using bitsery::DefaultConfig;
using bitsery::EndiannessType;
using testing::ContainerEq;
using testing::Eq;
constexpr EndiannessType getInverseEndianness(EndiannessType e) {
return e == EndiannessType::LittleEndian
? EndiannessType::BigEndian
: EndiannessType::LittleEndian;
constexpr EndiannessType
getInverseEndianness(EndiannessType e)
{
return e == EndiannessType::LittleEndian ? EndiannessType::BigEndian
: EndiannessType::LittleEndian;
}
struct InverseEndiannessConfig {
static constexpr bitsery::EndiannessType Endianness = getInverseEndianness(DefaultConfig::Endianness);
static constexpr bool CheckDataErrors = true;
static constexpr bool CheckAdapterErrors = true;
struct InverseEndiannessConfig
{
static constexpr bitsery::EndiannessType Endianness =
getInverseEndianness(DefaultConfig::Endianness);
static constexpr bool CheckDataErrors = true;
static constexpr bool CheckAdapterErrors = true;
};
struct IntegralTypes {
int64_t a;
uint32_t b;
int16_t c;
uint8_t d;
int8_t e;
struct IntegralTypes
{
int64_t a;
uint32_t b;
int16_t c;
uint8_t d;
int8_t e;
};
using InverseReader = bitsery::InputBufferAdapter<Buffer, InverseEndiannessConfig>;
using InverseReader =
bitsery::InputBufferAdapter<Buffer, InverseEndiannessConfig>;
TEST(DataEndianness, WhenWriteBytesThenBytesAreSwapped)
{
// fill initial values
IntegralTypes src{};
src.a = static_cast<int64_t>(0x1122334455667788u);
src.b = 0xBBCCDDEEu;
src.c = static_cast<int16_t>(0xCCDDu);
src.d = static_cast<uint8_t>(0xDDu);
src.e = static_cast<int8_t>(0xEEu);
TEST(DataEndianness, WhenWriteBytesThenBytesAreSwapped) {
//fill initial values
IntegralTypes src{};
src.a = static_cast<int64_t>(0x1122334455667788u);
src.b = 0xBBCCDDEEu;
src.c = static_cast<int16_t>(0xCCDDu);
src.d = static_cast<uint8_t>(0xDDu);
src.e = static_cast<int8_t>(0xEEu);
// fill expected result after swap
IntegralTypes resInv{};
resInv.a = static_cast<int64_t>(0x8877665544332211u);
resInv.b = 0xEEDDCCBBu;
resInv.c = static_cast<int16_t>(0xDDCCu);
resInv.d = static_cast<uint8_t>(0xDDu);
resInv.e = static_cast<int8_t>(0xEEu);
//fill expected result after swap
IntegralTypes resInv{};
resInv.a = static_cast<int64_t>(0x8877665544332211u);
resInv.b = 0xEEDDCCBBu;
resInv.c = static_cast<int16_t>(0xDDCCu);
resInv.d = static_cast<uint8_t>(0xDDu);
resInv.e = static_cast<int8_t>(0xEEu);
//create and write to buffer
Buffer buf{};
Writer bw{buf};
bw.writeBytes<8>(src.a);
bw.writeBytes<4>(src.b);
bw.writeBytes<2>(src.c);
bw.writeBytes<1>(src.d);
bw.writeBytes<1>(src.e);
bw.flush();
//read from buffer using inverse endianness config
InverseReader br{buf.begin(), bw.writtenBytesCount()};
IntegralTypes res{};
br.readBytes<8>(res.a);
br.readBytes<4>(res.b);
br.readBytes<2>(res.c);
br.readBytes<1>(res.d);
br.readBytes<1>(res.e);
//check results
EXPECT_THAT(res.a, Eq(resInv.a));
EXPECT_THAT(res.b, Eq(resInv.b));
EXPECT_THAT(res.c, Eq(resInv.c));
EXPECT_THAT(res.d, Eq(resInv.d));
EXPECT_THAT(res.e, Eq(resInv.e));
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
bw.writeBytes<8>(src.a);
bw.writeBytes<4>(src.b);
bw.writeBytes<2>(src.c);
bw.writeBytes<1>(src.d);
bw.writeBytes<1>(src.e);
bw.flush();
// read from buffer using inverse endianness config
InverseReader br{ buf.begin(), bw.writtenBytesCount() };
IntegralTypes res{};
br.readBytes<8>(res.a);
br.readBytes<4>(res.b);
br.readBytes<2>(res.c);
br.readBytes<1>(res.d);
br.readBytes<1>(res.e);
// check results
EXPECT_THAT(res.a, Eq(resInv.a));
EXPECT_THAT(res.b, Eq(resInv.b));
EXPECT_THAT(res.c, Eq(resInv.c));
EXPECT_THAT(res.d, Eq(resInv.d));
EXPECT_THAT(res.e, Eq(resInv.e));
}
TEST(DataEndianness, WhenWrite1ByteValuesThenEndiannessIsIgnored) {
//fill initial values
constexpr size_t SIZE = 4;
uint8_t src[SIZE] = {0xAA, 0xBB, 0xCC, 0xDD};
uint8_t res[SIZE] = {};
//create and write to buffer
Buffer buf{};
Writer bw{buf};
bw.writeBuffer<1>(src, SIZE);
bw.flush();
//read from buffer using inverse endianness config
InverseReader br{buf.begin(), bw.writtenBytesCount()};
br.readBuffer<1>(res, SIZE);
//result is identical, because we write separate values, of size 1byte, that requires no swapping
//check results
EXPECT_THAT(res, ContainerEq(src));
TEST(DataEndianness, WhenWrite1ByteValuesThenEndiannessIsIgnored)
{
// fill initial values
constexpr size_t SIZE = 4;
uint8_t src[SIZE] = { 0xAA, 0xBB, 0xCC, 0xDD };
uint8_t res[SIZE] = {};
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
bw.writeBuffer<1>(src, SIZE);
bw.flush();
// read from buffer using inverse endianness config
InverseReader br{ buf.begin(), bw.writtenBytesCount() };
br.readBuffer<1>(res, SIZE);
// result is identical, because we write separate values, of size 1byte, that
// requires no swapping check results
EXPECT_THAT(res, ContainerEq(src));
}
TEST(DataEndianness, WhenWriteMoreThan1ByteValuesThenValuesAreSwapped) {
//fill initial values
constexpr size_t SIZE = 4;
uint16_t src[SIZE] = {0xAA00, 0xBB11, 0xCC22, 0xDD33};
uint16_t resInv[SIZE] = {0x00AA, 0x11BB, 0x22CC, 0x33DD};
uint16_t res[SIZE] = {};
//create and write to buffer
Buffer buf{};
Writer bw{buf};
bw.writeBuffer<2>(src, SIZE);
bw.flush();
//read from buffer using inverse endianness config
InverseReader br{buf.begin(), bw.writtenBytesCount()};
br.readBuffer<2>(res, SIZE);
//result is identical, because we write separate values, of size 1byte, that requires no swapping
//check results
EXPECT_THAT(res, ContainerEq(resInv));
TEST(DataEndianness, WhenWriteMoreThan1ByteValuesThenValuesAreSwapped)
{
// fill initial values
constexpr size_t SIZE = 4;
uint16_t src[SIZE] = { 0xAA00, 0xBB11, 0xCC22, 0xDD33 };
uint16_t resInv[SIZE] = { 0x00AA, 0x11BB, 0x22CC, 0x33DD };
uint16_t res[SIZE] = {};
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
bw.writeBuffer<2>(src, SIZE);
bw.flush();
// read from buffer using inverse endianness config
InverseReader br{ buf.begin(), bw.writtenBytesCount() };
br.readBuffer<2>(res, SIZE);
// result is identical, because we write separate values, of size 1byte, that
// requires no swapping check results
EXPECT_THAT(res, ContainerEq(resInv));
}
template <typename T>
constexpr size_t getBits(T v) {
return bitsery::details::calcRequiredBits<T>({}, v);
template<typename T>
constexpr size_t
getBits(T v)
{
return bitsery::details::calcRequiredBits<T>({}, v);
}
struct IntegralUnsignedTypes {
uint64_t a;
uint32_t b;
uint16_t c;
uint8_t d;
struct IntegralUnsignedTypes
{
uint64_t a;
uint32_t b;
uint16_t c;
uint8_t d;
};
TEST(DataEndianness, WhenValueTypeIs1ByteThenBitOperationsIsNotAffectedByEndianness) {
//fill initial values
constexpr IntegralUnsignedTypes src {
0x0000334455667788,
0x00CCDDEE,
0x00DD,
0x0F,
};
TEST(DataEndianness,
WhenValueTypeIs1ByteThenBitOperationsIsNotAffectedByEndianness)
{
// fill initial values
constexpr IntegralUnsignedTypes src{
0x0000334455667788,
0x00CCDDEE,
0x00DD,
0x0F,
};
constexpr size_t aBITS = getBits(src.a) + 8;
constexpr size_t bBITS = getBits(src.b) + 0;
constexpr size_t cBITS = getBits(src.c) + 5;
constexpr size_t dBITS = getBits(src.d) + 2;
//create and write to buffer
Buffer buf{};
Writer bw{buf};
bitsery::details::OutputAdapterBitPackingWrapper<Writer> bpw{bw};
bpw.writeBits(src.a, aBITS);
bpw.writeBits(src.b, bBITS);
bpw.writeBits(src.c, cBITS);
bpw.writeBits(src.d, dBITS);
bpw.flush();
//read from buffer using inverse endianness config
InverseReader br{buf.begin(), bpw.writtenBytesCount()};
bitsery::details::InputAdapterBitPackingWrapper<InverseReader> bpr{br};
IntegralUnsignedTypes res{};
bpr.readBits(res.a, aBITS);
bpr.readBits(res.b, bBITS);
bpr.readBits(res.c, cBITS);
bpr.readBits(res.d, dBITS);
//check results
EXPECT_THAT(res.a, Eq(src.a));
EXPECT_THAT(res.b, Eq(src.b));
EXPECT_THAT(res.c, Eq(src.c));
EXPECT_THAT(res.d, Eq(src.d));
constexpr size_t aBITS = getBits(src.a) + 8;
constexpr size_t bBITS = getBits(src.b) + 0;
constexpr size_t cBITS = getBits(src.c) + 5;
constexpr size_t dBITS = getBits(src.d) + 2;
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
bitsery::details::OutputAdapterBitPackingWrapper<Writer> bpw{ bw };
bpw.writeBits(src.a, aBITS);
bpw.writeBits(src.b, bBITS);
bpw.writeBits(src.c, cBITS);
bpw.writeBits(src.d, dBITS);
bpw.flush();
// read from buffer using inverse endianness config
InverseReader br{ buf.begin(), bpw.writtenBytesCount() };
bitsery::details::InputAdapterBitPackingWrapper<InverseReader> bpr{ br };
IntegralUnsignedTypes res{};
bpr.readBits(res.a, aBITS);
bpr.readBits(res.b, bBITS);
bpr.readBits(res.c, cBITS);
bpr.readBits(res.d, dBITS);
// check results
EXPECT_THAT(res.a, Eq(src.a));
EXPECT_THAT(res.b, Eq(src.b));
EXPECT_THAT(res.c, Eq(src.c));
EXPECT_THAT(res.d, Eq(src.d));
}

View File

@@ -1,410 +1,419 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/deserializer.h>
#include <bitsery/ext/value_range.h>
#include <bitsery/serializer.h>
#include <bitsery/deserializer.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using testing::Eq;
using testing::ContainerEq;
using testing::Eq;
using AdapterBitPackingWriter = bitsery::details::OutputAdapterBitPackingWrapper<Writer>;
using AdapterBitPackingReader = bitsery::details::InputAdapterBitPackingWrapper<Reader>;
using AdapterBitPackingWriter =
bitsery::details::OutputAdapterBitPackingWrapper<Writer>;
using AdapterBitPackingReader =
bitsery::details::InputAdapterBitPackingWrapper<Reader>;
struct IntegralUnsignedTypes {
uint32_t a;
uint16_t b;
uint8_t c;
uint8_t d;
uint64_t e;
struct IntegralUnsignedTypes
{
uint32_t a;
uint16_t b;
uint8_t c;
uint8_t d;
uint64_t e;
};
template <typename T>
constexpr size_t getBits(T v) {
return bitsery::details::calcRequiredBits<T>({}, v);
template<typename T>
constexpr size_t
getBits(T v)
{
return bitsery::details::calcRequiredBits<T>({}, v);
}
// *** bits operations
TEST(DataBitsAndBytesOperations, WriteAndReadBitsMaxTypeValues) {
Buffer buf;
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
bpw.writeBits(std::numeric_limits<uint64_t>::max(), 64);
bpw.writeBits(std::numeric_limits<uint32_t>::max(), 32);
bpw.writeBits(std::numeric_limits<uint16_t>::max(), 16);
bpw.writeBits(std::numeric_limits<uint8_t>::max(), 8);
bpw.flush();
TEST(DataBitsAndBytesOperations, WriteAndReadBitsMaxTypeValues)
{
Buffer buf;
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
bpw.writeBits(std::numeric_limits<uint64_t>::max(), 64);
bpw.writeBits(std::numeric_limits<uint32_t>::max(), 32);
bpw.writeBits(std::numeric_limits<uint16_t>::max(), 16);
bpw.writeBits(std::numeric_limits<uint8_t>::max(), 8);
bpw.flush();
Reader br{buf.begin(), bpw.writtenBytesCount()};
AdapterBitPackingReader bpr{br};
uint64_t v64{};
uint32_t v32{};
uint16_t v16{};
uint8_t v8{};
bpr.readBits(v64, 64);
bpr.readBits(v32, 32);
bpr.readBits(v16, 16);
bpr.readBits(v8, 8);
Reader br{ buf.begin(), bpw.writtenBytesCount() };
AdapterBitPackingReader bpr{ br };
uint64_t v64{};
uint32_t v32{};
uint16_t v16{};
uint8_t v8{};
bpr.readBits(v64, 64);
bpr.readBits(v32, 32);
bpr.readBits(v16, 16);
bpr.readBits(v8, 8);
EXPECT_THAT(v64, Eq(std::numeric_limits<uint64_t>::max()));
EXPECT_THAT(v32, Eq(std::numeric_limits<uint32_t>::max()));
EXPECT_THAT(v16, Eq(std::numeric_limits<uint16_t>::max()));
EXPECT_THAT(v8, Eq(std::numeric_limits<uint8_t>::max()));
EXPECT_THAT(v64, Eq(std::numeric_limits<uint64_t>::max()));
EXPECT_THAT(v32, Eq(std::numeric_limits<uint32_t>::max()));
EXPECT_THAT(v16, Eq(std::numeric_limits<uint16_t>::max()));
EXPECT_THAT(v8, Eq(std::numeric_limits<uint8_t>::max()));
}
TEST(DataBitsAndBytesOperations, WriteAndReadBits) {
//setup data
constexpr IntegralUnsignedTypes data{
485454,//bits 19
45978,//bits 16
0,//bits 1
36,//bits 6
479845648946//bits 39
};
TEST(DataBitsAndBytesOperations, WriteAndReadBits)
{
// setup data
constexpr IntegralUnsignedTypes data{
485454, // bits 19
45978, // bits 16
0, // bits 1
36, // bits 6
479845648946 // bits 39
};
constexpr size_t aBITS = getBits(data.a) + 2;
constexpr size_t bBITS = getBits(data.b) + 0;
constexpr size_t cBITS = getBits(data.c) + 2;
constexpr size_t dBITS = getBits(data.d) + 1;
constexpr size_t eBITS = getBits(data.e) + 8;
constexpr size_t aBITS = getBits(data.a) + 2;
constexpr size_t bBITS = getBits(data.b) + 0;
constexpr size_t cBITS = getBits(data.c) + 2;
constexpr size_t dBITS = getBits(data.d) + 1;
constexpr size_t eBITS = getBits(data.e) + 8;
//create and write to buffer
Buffer buf;
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
// create and write to buffer
Buffer buf;
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
bpw.writeBits(data.a, aBITS);
bpw.writeBits(data.b, bBITS);
bpw.writeBits(data.c, cBITS);
bpw.writeBits(data.d, dBITS);
bpw.writeBits(data.e, eBITS);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
auto bytesCount = ((aBITS + bBITS + cBITS + dBITS + eBITS) / 8) +1 ;
EXPECT_THAT(writtenSize, Eq(bytesCount));
//read from buffer
Reader br{buf.begin(), writtenSize};
AdapterBitPackingReader bpr{br};
bpw.writeBits(data.a, aBITS);
bpw.writeBits(data.b, bBITS);
bpw.writeBits(data.c, cBITS);
bpw.writeBits(data.d, dBITS);
bpw.writeBits(data.e, eBITS);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
auto bytesCount = ((aBITS + bBITS + cBITS + dBITS + eBITS) / 8) + 1;
EXPECT_THAT(writtenSize, Eq(bytesCount));
// read from buffer
Reader br{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr{ br };
IntegralUnsignedTypes res{};
IntegralUnsignedTypes res{};
bpr.readBits(res.a, aBITS);
bpr.readBits(res.b, bBITS);
bpr.readBits(res.c, cBITS);
bpr.readBits(res.d, dBITS);
bpr.readBits(res.e, eBITS);
EXPECT_THAT(res.a, Eq(data.a));
EXPECT_THAT(res.b, Eq(data.b));
EXPECT_THAT(res.c, Eq(data.c));
EXPECT_THAT(res.d, Eq(data.d));
EXPECT_THAT(res.e, Eq(data.e));
bpr.readBits(res.a, aBITS);
bpr.readBits(res.b, bBITS);
bpr.readBits(res.c, cBITS);
bpr.readBits(res.d, dBITS);
bpr.readBits(res.e, eBITS);
EXPECT_THAT(res.a, Eq(data.a));
EXPECT_THAT(res.b, Eq(data.b));
EXPECT_THAT(res.c, Eq(data.c));
EXPECT_THAT(res.d, Eq(data.d));
EXPECT_THAT(res.e, Eq(data.e));
}
TEST(DataBitsAndBytesOperations, WrittenSizeIsCountedPerByteNotPerBit) {
//setup data
TEST(DataBitsAndBytesOperations, WrittenSizeIsCountedPerByteNotPerBit)
{
// setup data
//create and write to buffer
Buffer buf;
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
// create and write to buffer
Buffer buf;
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
bpw.writeBits(7u,3);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(1));
bpw.writeBits(7u, 3);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(1));
//read from buffer
Reader br{buf.begin(), writtenSize};
AdapterBitPackingReader bpr{br};
uint16_t tmp;
bpr.readBits(tmp,4);
bpr.readBits(tmp,2);
bpr.readBits(tmp,2);
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
bpr.readBits(tmp,2);
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::DataOverflow));//false
// read from buffer
Reader br{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr{ br };
uint16_t tmp;
bpr.readBits(tmp, 4);
bpr.readBits(tmp, 2);
bpr.readBits(tmp, 2);
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
bpr.readBits(tmp, 2);
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::DataOverflow)); // false
//part of next byte
Reader br1{buf.begin(), writtenSize};
AdapterBitPackingReader bpr1{br1};
bpr1.readBits(tmp,2);
EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError));
bpr1.readBits(tmp,7);
EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::DataOverflow));//false
// part of next byte
Reader br1{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr1{ br1 };
bpr1.readBits(tmp, 2);
EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError));
bpr1.readBits(tmp, 7);
EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::DataOverflow)); // false
//bigger than byte
Reader br2{buf.begin(), writtenSize};
AdapterBitPackingReader bpr2{br2};
bpr2.readBits(tmp,9);
EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::DataOverflow));//false
// bigger than byte
Reader br2{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr2{ br2 };
bpr2.readBits(tmp, 9);
EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::DataOverflow)); // false
}
TEST(DataBitsAndBytesOperations, ConsecutiveCallsToAlignHasNoEffect) {
Buffer buf;
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
TEST(DataBitsAndBytesOperations, ConsecutiveCallsToAlignHasNoEffect)
{
Buffer buf;
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
bpw.writeBits(3u, 2);
//3 calls to align after 1st data
bpw.align();
bpw.align();
bpw.align();
bpw.writeBits(7u, 3);
//1 call to align after 2nd data
bpw.align();
bpw.writeBits(15u, 4);
bpw.flush();
bpw.writeBits(3u, 2);
// 3 calls to align after 1st data
bpw.align();
bpw.align();
bpw.align();
bpw.writeBits(7u, 3);
// 1 call to align after 2nd data
bpw.align();
bpw.writeBits(15u, 4);
bpw.flush();
unsigned char tmp;
Reader br{buf.begin(), bpw.writtenBytesCount()};
AdapterBitPackingReader bpr{br};
bpr.readBits(tmp,2);
EXPECT_THAT(tmp, Eq(3u));
bpr.align();
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
bpr.readBits(tmp,3);
bpr.align();
bpr.align();
bpr.align();
EXPECT_THAT(tmp, Eq(7u));
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
unsigned char tmp;
Reader br{ buf.begin(), bpw.writtenBytesCount() };
AdapterBitPackingReader bpr{ br };
bpr.readBits(tmp, 2);
EXPECT_THAT(tmp, Eq(3u));
bpr.align();
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
bpr.readBits(tmp, 3);
bpr.align();
bpr.align();
bpr.align();
EXPECT_THAT(tmp, Eq(7u));
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
bpr.readBits(tmp,4);
EXPECT_THAT(tmp, Eq(15u));
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
bpr.readBits(tmp, 4);
EXPECT_THAT(tmp, Eq(15u));
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
}
TEST(DataBitsAndBytesOperations, AlignWritesZerosBits) {
//setup data
TEST(DataBitsAndBytesOperations, AlignWritesZerosBits)
{
// setup data
//create and write to buffer
Buffer buf;
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
// create and write to buffer
Buffer buf;
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
//write 2 bits and align
bpw.writeBits(3u, 2);
bpw.align();
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(1));
unsigned char tmp;
Reader br1{buf.begin(), writtenSize};
AdapterBitPackingReader bpr1{br1};
bpr1.readBits(tmp,2);
//read aligned bits
bpr1.readBits(tmp,6);
EXPECT_THAT(tmp, Eq(0));
// write 2 bits and align
bpw.writeBits(3u, 2);
bpw.align();
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(1));
unsigned char tmp;
Reader br1{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr1{ br1 };
bpr1.readBits(tmp, 2);
// read aligned bits
bpr1.readBits(tmp, 6);
EXPECT_THAT(tmp, Eq(0));
Reader br2{buf.begin(), writtenSize};
AdapterBitPackingReader bpr2{br2};
//read 2 bits
bpr2.readBits(tmp,2);
bpr2.align();
EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::NoError));
Reader br2{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr2{ br2 };
// read 2 bits
bpr2.readBits(tmp, 2);
bpr2.align();
EXPECT_THAT(bpr2.error(), Eq(bitsery::ReaderError::NoError));
}
// *** bytes operations
struct IntegralTypes {
int64_t a;
uint32_t b;
int16_t c;
uint8_t d;
int8_t e;
int8_t f[2];
struct IntegralTypes
{
int64_t a;
uint32_t b;
int16_t c;
uint8_t d;
int8_t e;
int8_t f[2];
};
TEST(DataBitsAndBytesOperations, WriteAndReadBytes) {
//setup data
IntegralTypes data;
data.a = -4894541654564;
data.b = 94545646;
data.c = -8778;
data.d = 200;
data.e = -98;
data.f[0] = 43;
data.f[1] = -45;
TEST(DataBitsAndBytesOperations, WriteAndReadBytes)
{
// setup data
IntegralTypes data;
data.a = -4894541654564;
data.b = 94545646;
data.c = -8778;
data.d = 200;
data.e = -98;
data.f[0] = 43;
data.f[1] = -45;
//create and write to buffer
Buffer buf{};
Writer bw{buf};
bw.writeBytes<4>(data.b);
bw.writeBytes<2>(data.c);
bw.writeBytes<1>(data.d);
bw.writeBytes<8>(data.a);
bw.writeBytes<1>(data.e);
bw.writeBuffer<1>(data.f, 2);
bw.flush();
auto writtenSize = bw.writtenBytesCount();
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
bw.writeBytes<4>(data.b);
bw.writeBytes<2>(data.c);
bw.writeBytes<1>(data.d);
bw.writeBytes<8>(data.a);
bw.writeBytes<1>(data.e);
bw.writeBuffer<1>(data.f, 2);
bw.flush();
auto writtenSize = bw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(18));
//read from buffer
Reader br{buf.begin(), writtenSize};
IntegralTypes res{};
br.readBytes<4>(res.b);
br.readBytes<2>(res.c);
br.readBytes<1>(res.d);
br.readBytes<8>(res.a);
br.readBytes<1>(res.e);
br.readBuffer<1>(res.f, 2);
EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError));
//assert results
EXPECT_THAT(data.a, Eq(res.a));
EXPECT_THAT(data.b, Eq(res.b));
EXPECT_THAT(data.c, Eq(res.c));
EXPECT_THAT(data.d, Eq(res.d));
EXPECT_THAT(data.e, Eq(res.e));
EXPECT_THAT(data.f, ContainerEq(res.f));
EXPECT_THAT(writtenSize, Eq(18));
// read from buffer
Reader br{ buf.begin(), writtenSize };
IntegralTypes res{};
br.readBytes<4>(res.b);
br.readBytes<2>(res.c);
br.readBytes<1>(res.d);
br.readBytes<8>(res.a);
br.readBytes<1>(res.e);
br.readBuffer<1>(res.f, 2);
EXPECT_THAT(br.error(), Eq(bitsery::ReaderError::NoError));
// assert results
EXPECT_THAT(data.a, Eq(res.a));
EXPECT_THAT(data.b, Eq(res.b));
EXPECT_THAT(data.c, Eq(res.c));
EXPECT_THAT(data.d, Eq(res.d));
EXPECT_THAT(data.e, Eq(res.e));
EXPECT_THAT(data.f, ContainerEq(res.f));
}
TEST(DataBitsAndBytesOperations, WriteAndReadBytesWithBitPackingWrapper) {
//setup data
IntegralTypes data;
data.a = -4894541654564;
data.b = 94545646;
data.c = -8778;
data.d = 200;
data.e = -98;
data.f[0] = 43;
data.f[1] = -45;
TEST(DataBitsAndBytesOperations, WriteAndReadBytesWithBitPackingWrapper)
{
// setup data
IntegralTypes data;
data.a = -4894541654564;
data.b = 94545646;
data.c = -8778;
data.d = 200;
data.e = -98;
data.f[0] = 43;
data.f[1] = -45;
//create and write to buffer
Buffer buf{};
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
bpw.writeBytes<4>(data.b);
bpw.writeBytes<2>(data.c);
bpw.writeBytes<1>(data.d);
bpw.writeBytes<8>(data.a);
bpw.writeBytes<1>(data.e);
bpw.writeBuffer<1>(data.f, 2);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
bpw.writeBytes<4>(data.b);
bpw.writeBytes<2>(data.c);
bpw.writeBytes<1>(data.d);
bpw.writeBytes<8>(data.a);
bpw.writeBytes<1>(data.e);
bpw.writeBuffer<1>(data.f, 2);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(18));
//read from buffer
Reader br{buf.begin(), writtenSize};
AdapterBitPackingReader bpr{br};
IntegralTypes res{};
bpr.readBytes<4>(res.b);
bpr.readBytes<2>(res.c);
bpr.readBytes<1>(res.d);
bpr.readBytes<8>(res.a);
bpr.readBytes<1>(res.e);
bpr.readBuffer<1>(res.f, 2);
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
//assert results
EXPECT_THAT(data.a, Eq(res.a));
EXPECT_THAT(data.b, Eq(res.b));
EXPECT_THAT(data.c, Eq(res.c));
EXPECT_THAT(data.d, Eq(res.d));
EXPECT_THAT(data.e, Eq(res.e));
EXPECT_THAT(data.f, ContainerEq(res.f));
EXPECT_THAT(writtenSize, Eq(18));
// read from buffer
Reader br{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr{ br };
IntegralTypes res{};
bpr.readBytes<4>(res.b);
bpr.readBytes<2>(res.c);
bpr.readBytes<1>(res.d);
bpr.readBytes<8>(res.a);
bpr.readBytes<1>(res.e);
bpr.readBuffer<1>(res.f, 2);
EXPECT_THAT(bpr.error(), Eq(bitsery::ReaderError::NoError));
// assert results
EXPECT_THAT(data.a, Eq(res.a));
EXPECT_THAT(data.b, Eq(res.b));
EXPECT_THAT(data.c, Eq(res.c));
EXPECT_THAT(data.d, Eq(res.d));
EXPECT_THAT(data.e, Eq(res.e));
EXPECT_THAT(data.f, ContainerEq(res.f));
}
TEST(DataBitsAndBytesOperations, ReadWriteFncCanAcceptSignedData) {
//setup data
constexpr size_t DATA_SIZE = 3;
int16_t src[DATA_SIZE] {54,-4877,30067};
//create and write to buffer
Buffer buf{};
Writer bw{buf};
bw.writeBuffer<2>(src, DATA_SIZE);
bw.flush();
//read from buffer
Reader br1{buf.begin(), bw.writtenBytesCount()};
int16_t dst[DATA_SIZE]{};
br1.readBuffer<2>(dst, DATA_SIZE);
EXPECT_THAT(br1.error(), Eq(bitsery::ReaderError::NoError));
EXPECT_THAT(dst, ContainerEq(src));
TEST(DataBitsAndBytesOperations, ReadWriteFncCanAcceptSignedData)
{
// setup data
constexpr size_t DATA_SIZE = 3;
int16_t src[DATA_SIZE]{ 54, -4877, 30067 };
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
bw.writeBuffer<2>(src, DATA_SIZE);
bw.flush();
// read from buffer
Reader br1{ buf.begin(), bw.writtenBytesCount() };
int16_t dst[DATA_SIZE]{};
br1.readBuffer<2>(dst, DATA_SIZE);
EXPECT_THAT(br1.error(), Eq(bitsery::ReaderError::NoError));
EXPECT_THAT(dst, ContainerEq(src));
}
TEST(DataBitsAndBytesOperations, ReadWriteCanWorkOnUnalignedData) {
//setup data
constexpr size_t DATA_SIZE = 3;
int16_t src[DATA_SIZE] {54,-4877,30067};
//create and write to buffer
Buffer buf{};
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
bpw.writeBits(15u, 4);
bpw.writeBuffer<2>(src, DATA_SIZE);
bpw.writeBits(12u, 4);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(sizeof(src) + 1));
TEST(DataBitsAndBytesOperations, ReadWriteCanWorkOnUnalignedData)
{
// setup data
constexpr size_t DATA_SIZE = 3;
int16_t src[DATA_SIZE]{ 54, -4877, 30067 };
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
bpw.writeBits(15u, 4);
bpw.writeBuffer<2>(src, DATA_SIZE);
bpw.writeBits(12u, 4);
bpw.flush();
auto writtenSize = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize, Eq(sizeof(src) + 1));
//read from buffer
Reader br1{buf.begin(), writtenSize};
AdapterBitPackingReader bpr1{br1};
int16_t dst[DATA_SIZE]{};
uint8_t tmp{};
bpr1.readBits(tmp, 4);
EXPECT_THAT(tmp, Eq(15));
bpr1.readBuffer<2>(dst, DATA_SIZE);
EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError));
EXPECT_THAT(dst, ContainerEq(src));
bpr1.readBits(tmp, 4);
EXPECT_THAT(tmp, Eq(12));
// read from buffer
Reader br1{ buf.begin(), writtenSize };
AdapterBitPackingReader bpr1{ br1 };
int16_t dst[DATA_SIZE]{};
uint8_t tmp{};
bpr1.readBits(tmp, 4);
EXPECT_THAT(tmp, Eq(15));
bpr1.readBuffer<2>(dst, DATA_SIZE);
EXPECT_THAT(bpr1.error(), Eq(bitsery::ReaderError::NoError));
EXPECT_THAT(dst, ContainerEq(src));
bpr1.readBits(tmp, 4);
EXPECT_THAT(tmp, Eq(12));
}
TEST(DataBitsAndBytesOperations, RegressionTestReadBytesAfterReadBitsWithLotsOfZeroBits) {
//setup data
int16_t data[2]{0x0000, 0x7FFF};
int16_t res[2]{};
//create and write to buffer
Buffer buf{};
Writer bw{buf};
AdapterBitPackingWriter bpw{bw};
bpw.writeBits(2u, 2);
bpw.writeBytes<2>(data[0]);
bpw.writeBytes<2>(data[1]);
bpw.align();
bpw.flush();
TEST(DataBitsAndBytesOperations,
RegressionTestReadBytesAfterReadBitsWithLotsOfZeroBits)
{
// setup data
int16_t data[2]{ 0x0000, 0x7FFF };
int16_t res[2]{};
// create and write to buffer
Buffer buf{};
Writer bw{ buf };
AdapterBitPackingWriter bpw{ bw };
bpw.writeBits(2u, 2);
bpw.writeBytes<2>(data[0]);
bpw.writeBytes<2>(data[1]);
bpw.align();
bpw.flush();
//read from buffer
Reader br{buf.begin(), bpw.writtenBytesCount()};
AdapterBitPackingReader bpr{br};
uint8_t tmp{};
bpr.readBits(tmp, 2);
EXPECT_THAT(tmp, Eq(2));
bpr.readBytes<2>(res[0]);
bpr.readBytes<2>(res[1]);
bpr.align();
EXPECT_THAT(res[0], Eq(data[0]));
EXPECT_THAT(res[1], Eq(data[1]));
// read from buffer
Reader br{ buf.begin(), bpw.writtenBytesCount() };
AdapterBitPackingReader bpr{ br };
uint8_t tmp{};
bpr.readBits(tmp, 2);
EXPECT_THAT(tmp, Eq(2));
bpr.readBytes<2>(res[0]);
bpr.readBytes<2>(res[1]);
bpr.align();
EXPECT_THAT(res[0], Eq(data[0]));
EXPECT_THAT(res[1], Eq(data[1]));
}

View File

@@ -1,111 +1,117 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/details/serialization_common.h>
#include <bitsery/traits/array.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
using testing::ContainerEq;
using bitsery::EndiannessType;
using testing::ContainerEq;
using testing::Eq;
template <typename BufType>
class DataWriting:public testing::Test {
template<typename BufType>
class DataWriting : public testing::Test
{
public:
using TWriter = bitsery::OutputBufferAdapter<BufType>;
using TBuffer = BufType;
using TWriter = bitsery::OutputBufferAdapter<BufType>;
using TBuffer = BufType;
};
using NonFixedContainer = std::vector<uint8_t>;
using FixedContainer = std::array<uint8_t, 100>;
using ContainerTypes = ::testing::Types<FixedContainer,NonFixedContainer>;
using ContainerTypes = ::testing::Types<FixedContainer, NonFixedContainer>;
TYPED_TEST_SUITE(DataWriting, ContainerTypes,);
TYPED_TEST_SUITE(DataWriting, ContainerTypes, );
static constexpr size_t DATA_SIZE = 14u;
template <typename BW>
void writeData(BW& bw) {
uint16_t tmp1{45}, tmp2{6543}, tmp3{46533};
uint32_t tmp4{8979445}, tmp5{7987564};
bw.template writeBytes<2>(tmp1);
bw.template writeBytes<2>(tmp2);
bw.template writeBytes<2>(tmp3);
bw.template writeBytes<4>(tmp4);
bw.template writeBytes<4>(tmp5);
template<typename BW>
void
writeData(BW& bw)
{
uint16_t tmp1{ 45 }, tmp2{ 6543 }, tmp3{ 46533 };
uint32_t tmp4{ 8979445 }, tmp5{ 7987564 };
bw.template writeBytes<2>(tmp1);
bw.template writeBytes<2>(tmp2);
bw.template writeBytes<2>(tmp3);
bw.template writeBytes<4>(tmp4);
bw.template writeBytes<4>(tmp5);
}
TYPED_TEST(DataWriting, GetWrittenBytesCountReturnsActualBytesWritten) {
using TWriter = typename TestFixture::TWriter;
using TBuffer = typename TestFixture::TBuffer;
TBuffer buf{};
TWriter bw{buf};
writeData(bw);
bw.flush();
auto writtenSize = bw.writtenBytesCount();
EXPECT_THAT(writtenSize, DATA_SIZE);
EXPECT_THAT(buf.size(), ::testing::Ge(DATA_SIZE));
TYPED_TEST(DataWriting, GetWrittenBytesCountReturnsActualBytesWritten)
{
using TWriter = typename TestFixture::TWriter;
using TBuffer = typename TestFixture::TBuffer;
TBuffer buf{};
TWriter bw{ buf };
writeData(bw);
bw.flush();
auto writtenSize = bw.writtenBytesCount();
EXPECT_THAT(writtenSize, DATA_SIZE);
EXPECT_THAT(buf.size(), ::testing::Ge(DATA_SIZE));
}
TYPED_TEST(DataWriting, WhenWritingBitsThenMustFlushWriter) {
using TWriter = typename TestFixture::TWriter;
using TBuffer = typename TestFixture::TBuffer;
TBuffer buf{};
TWriter bw{buf};
bitsery::details::OutputAdapterBitPackingWrapper<TWriter> bpw{bw};
bpw.writeBits(3u, 2);
auto writtenSize1 = bpw.writtenBytesCount();
bpw.flush();
auto writtenSize2 = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize1, Eq(0));
EXPECT_THAT(writtenSize2, Eq(1));
TYPED_TEST(DataWriting, WhenWritingBitsThenMustFlushWriter)
{
using TWriter = typename TestFixture::TWriter;
using TBuffer = typename TestFixture::TBuffer;
TBuffer buf{};
TWriter bw{ buf };
bitsery::details::OutputAdapterBitPackingWrapper<TWriter> bpw{ bw };
bpw.writeBits(3u, 2);
auto writtenSize1 = bpw.writtenBytesCount();
bpw.flush();
auto writtenSize2 = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize1, Eq(0));
EXPECT_THAT(writtenSize2, Eq(1));
}
TYPED_TEST(DataWriting, WhenDataAlignedThenFlushHasNoEffect) {
using TWriter = typename TestFixture::TWriter;
using TBuffer = typename TestFixture::TBuffer;
TBuffer buf{};
TWriter bw{buf};
bitsery::details::OutputAdapterBitPackingWrapper<TWriter> bpw{bw};
bpw.writeBits(3u, 2);
bpw.align();
auto writtenSize1 = bpw.writtenBytesCount();
bpw.flush();
auto writtenSize2 = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize1, Eq(1));
EXPECT_THAT(writtenSize2, Eq(1));
TYPED_TEST(DataWriting, WhenDataAlignedThenFlushHasNoEffect)
{
using TWriter = typename TestFixture::TWriter;
using TBuffer = typename TestFixture::TBuffer;
TBuffer buf{};
TWriter bw{ buf };
bitsery::details::OutputAdapterBitPackingWrapper<TWriter> bpw{ bw };
bpw.writeBits(3u, 2);
bpw.align();
auto writtenSize1 = bpw.writtenBytesCount();
bpw.flush();
auto writtenSize2 = bpw.writtenBytesCount();
EXPECT_THAT(writtenSize1, Eq(1));
EXPECT_THAT(writtenSize2, Eq(1));
}
TEST(DataWritingNonFixedBufferContainer, ContainerIsAlwaysResizedToCapacity) {
NonFixedContainer buf{};
bitsery::OutputBufferAdapter<NonFixedContainer> bw{buf};
for (auto i = 0; i < 5; ++i) {
uint32_t tmp{};
bw.writeBytes<4>(tmp);
bw.writeBytes<4>(tmp);
EXPECT_TRUE(buf.size() == buf.capacity());
}
TEST(DataWritingNonFixedBufferContainer, ContainerIsAlwaysResizedToCapacity)
{
NonFixedContainer buf{};
bitsery::OutputBufferAdapter<NonFixedContainer> bw{ buf };
for (auto i = 0; i < 5; ++i) {
uint32_t tmp{};
bw.writeBytes<4>(tmp);
bw.writeBytes<4>(tmp);
EXPECT_TRUE(buf.size() == buf.capacity());
}
}

View File

@@ -1,351 +1,394 @@
//MIT License
// MIT License
//
//Copyright (c) 2019 Mindaugas Vinkelis
// Copyright (c) 2019 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <forward_list>
#include <bitsery/traits/forward_list.h>
#include <bitsery/ext/std_set.h>
#include <bitsery/ext/std_map.h>
#include <bitsery/ext/pointer.h>
#include <bitsery/ext/std_map.h>
#include <bitsery/ext/std_set.h>
#include <bitsery/ext/std_smart_ptr.h>
#include <bitsery/traits/forward_list.h>
#include <forward_list>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::ContainerEq;
using testing::Eq;
//forward declare, for testing with std::unordered_map
// forward declare, for testing with std::unordered_map
class HasherForNonDefaultConstructible;
class NonDefaultConstructible {
int32_t i{0};
friend class HasherForNonDefaultConstructible;
class NonDefaultConstructible
{
int32_t i{ 0 };
friend class HasherForNonDefaultConstructible;
friend class bitsery::Access;
NonDefaultConstructible() = default;
friend class bitsery::Access;
NonDefaultConstructible() = default;
template <typename S>
void serialize(S& s) {
s.value4b(i);
}
template<typename S>
void serialize(S& s)
{
s.value4b(i);
}
public:
explicit NonDefaultConstructible(int32_t v)
: i{ v }
{
}
explicit NonDefaultConstructible(int32_t v):i{v} {}
bool operator==(const NonDefaultConstructible& other) const
{
return i == other.i;
}
bool operator == (const NonDefaultConstructible& other) const {
return i == other.i;
}
bool operator < (const NonDefaultConstructible& other) const {
return i < other.i;
}
bool operator<(const NonDefaultConstructible& other) const
{
return i < other.i;
}
};
class HasherForNonDefaultConstructible {
class HasherForNonDefaultConstructible
{
public:
size_t operator()(const NonDefaultConstructible& o) const {
return std::hash<int32_t>()(o.i);
}
size_t operator()(const NonDefaultConstructible& o) const
{
return std::hash<int32_t>()(o.i);
}
};
TEST(DeserializeNonDefaultConstructible, Container)
{
SerializationContext ctx{};
std::vector<NonDefaultConstructible> data{};
data.emplace_back(1);
data.emplace_back(2);
data.emplace_back(3);
std::vector<NonDefaultConstructible> res{};
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
EXPECT_THAT(res, ContainerEq(data));
}
// this test is here, because when object is not constructible we cannot simple
// "resize" container
TEST(DeserializeNonDefaultConstructible, ResultContainerShouldShrink)
{
SerializationContext ctx{};
std::vector<NonDefaultConstructible> data{};
data.emplace_back(1);
std::vector<NonDefaultConstructible> res{};
res.emplace_back(2);
res.emplace_back(3);
res.emplace_back(4);
TEST(DeserializeNonDefaultConstructible, Container) {
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
EXPECT_THAT(res, ContainerEq(data));
}
TEST(DeserializeNonDefaultConstructible, ResultStdForwardListShouldShrink)
{
// forward list doesn't have .erase function, bet has erase_after
// in this case, if new size is 0 it must call clear, so we need to check two
// cases
{
// 1) when result should have more than 0 elements
SerializationContext ctx{};
std::vector<NonDefaultConstructible> data{};
data.emplace_back(1);
data.emplace_back(2);
data.emplace_back(3);
std::vector<NonDefaultConstructible> res{};
std::forward_list<NonDefaultConstructible> data{};
data.push_front(NonDefaultConstructible{ 1 });
std::forward_list<NonDefaultConstructible> res{};
res.push_front(NonDefaultConstructible{ 21 });
res.push_front(NonDefaultConstructible{ 14 });
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
EXPECT_THAT(res, ContainerEq(data));
}
//this test is here, because when object is not constructible we cannot simple "resize" container
TEST(DeserializeNonDefaultConstructible, ResultContainerShouldShrink) {
auto resIt = res.begin();
for (auto it = data.begin(); it != data.end(); ++it, ++resIt) {
EXPECT_THAT(*resIt, Eq(*it));
}
EXPECT_THAT(resIt, Eq(res.end()));
}
{
// 1) when result should have 0 elements
SerializationContext ctx{};
std::vector<NonDefaultConstructible> data{};
data.emplace_back(1);
std::vector<NonDefaultConstructible> res{};
res.emplace_back(2);
res.emplace_back(3);
res.emplace_back(4);
std::forward_list<NonDefaultConstructible> data{};
std::forward_list<NonDefaultConstructible> res{};
res.push_front(NonDefaultConstructible{ 1 });
res.push_front(NonDefaultConstructible{ 14 });
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
EXPECT_THAT(res, ContainerEq(data));
}
EXPECT_THAT(res.begin(), Eq(res.end()));
}
TEST(DeserializeNonDefaultConstructible, ResultStdForwardListShouldShrink) {
// forward list doesn't have .erase function, bet has erase_after
// in this case, if new size is 0 it must call clear, so we need to check two cases
{
// 1) when result should have more than 0 elements
SerializationContext ctx{};
std::forward_list<NonDefaultConstructible> data{};
data.push_front(NonDefaultConstructible{1});
std::forward_list<NonDefaultConstructible> res{};
res.push_front(NonDefaultConstructible{21});
res.push_front(NonDefaultConstructible{14});
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
auto resIt = res.begin();
for (auto it = data.begin(); it != data.end(); ++it, ++resIt) {
EXPECT_THAT(*resIt, Eq(*it));
}
EXPECT_THAT(resIt, Eq(res.end()));
}
{
// 1) when result should have 0 elements
SerializationContext ctx{};
std::forward_list<NonDefaultConstructible> data{};
std::forward_list<NonDefaultConstructible> res{};
res.push_front(NonDefaultConstructible{1});
res.push_front(NonDefaultConstructible{14});
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
EXPECT_THAT(res.begin(), Eq(res.end()));
}
{
// also check if correctly expands if source is bigger than destination
SerializationContext ctx{};
std::forward_list<NonDefaultConstructible> data{};
data.push_front(NonDefaultConstructible{1});
data.push_front(NonDefaultConstructible{14});
std::forward_list<NonDefaultConstructible> res{};
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
auto resIt = res.begin();
for (auto it = data.begin(); it != data.end(); ++it, ++resIt) {
EXPECT_THAT(*resIt, Eq(*it));
}
EXPECT_THAT(resIt, Eq(res.end()));
}
}
TEST(DeserializeNonDefaultConstructible, StdSet) {
{
// also check if correctly expands if source is bigger than destination
SerializationContext ctx{};
std::set<NonDefaultConstructible> data;
data.insert(NonDefaultConstructible{1});
data.insert(NonDefaultConstructible{2});
std::set<NonDefaultConstructible> res{};
data.insert(NonDefaultConstructible{3});
std::forward_list<NonDefaultConstructible> data{};
data.push_front(NonDefaultConstructible{ 1 });
data.push_front(NonDefaultConstructible{ 14 });
std::forward_list<NonDefaultConstructible> res{};
ctx.createSerializer().ext(data, bitsery::ext::StdSet{10});
ctx.createDeserializer().ext(res, bitsery::ext::StdSet{10});
ctx.createSerializer().container(data, 10);
ctx.createDeserializer().container(res, 10);
EXPECT_THAT(res, ContainerEq(data));
auto resIt = res.begin();
for (auto it = data.begin(); it != data.end(); ++it, ++resIt) {
EXPECT_THAT(*resIt, Eq(*it));
}
EXPECT_THAT(resIt, Eq(res.end()));
}
}
TEST(DeserializeNonDefaultConstructible, StdMap) {
SerializationContext ctx{};
std::unordered_map<NonDefaultConstructible, NonDefaultConstructible, HasherForNonDefaultConstructible> data;
data.emplace(NonDefaultConstructible{2}, NonDefaultConstructible{3});
TEST(DeserializeNonDefaultConstructible, StdSet)
{
SerializationContext ctx{};
std::set<NonDefaultConstructible> data;
data.insert(NonDefaultConstructible{ 1 });
data.insert(NonDefaultConstructible{ 2 });
std::set<NonDefaultConstructible> res{};
data.insert(NonDefaultConstructible{ 3 });
std::unordered_map<NonDefaultConstructible, NonDefaultConstructible, HasherForNonDefaultConstructible> res{};
data.emplace(NonDefaultConstructible{2}, NonDefaultConstructible{3});
data.emplace(NonDefaultConstructible{4}, NonDefaultConstructible{4});
ctx.createSerializer().ext(data, bitsery::ext::StdSet{ 10 });
ctx.createDeserializer().ext(res, bitsery::ext::StdSet{ 10 });
auto& ser = ctx.createSerializer();
ser.ext(data, bitsery::ext::StdMap{10},[](decltype(ser)& ser, NonDefaultConstructible& key, NonDefaultConstructible& value) {
ser.object(key);
ser.object(value);
});
auto& des = ctx.createDeserializer();
des.ext(res, bitsery::ext::StdMap{10},[](decltype(des)& des, NonDefaultConstructible& key, NonDefaultConstructible& value) {
des.object(key);
des.object(value);
});
EXPECT_THAT(res, ContainerEq(data));
EXPECT_THAT(res, ContainerEq(data));
}
TEST(DeserializeNonDefaultConstructible, StdMap)
{
SerializationContext ctx{};
std::unordered_map<NonDefaultConstructible,
NonDefaultConstructible,
HasherForNonDefaultConstructible>
data;
data.emplace(NonDefaultConstructible{ 2 }, NonDefaultConstructible{ 3 });
struct NonPolymorphicPointers {
NonDefaultConstructible* pp;
std::unique_ptr<NonDefaultConstructible> up;
std::shared_ptr<NonDefaultConstructible> sp;
std::weak_ptr<NonDefaultConstructible> wp;
std::unordered_map<NonDefaultConstructible,
NonDefaultConstructible,
HasherForNonDefaultConstructible>
res{};
data.emplace(NonDefaultConstructible{ 2 }, NonDefaultConstructible{ 3 });
data.emplace(NonDefaultConstructible{ 4 }, NonDefaultConstructible{ 4 });
auto& ser = ctx.createSerializer();
ser.ext(data,
bitsery::ext::StdMap{ 10 },
[](decltype(ser)& ser,
NonDefaultConstructible& key,
NonDefaultConstructible& value) {
ser.object(key);
ser.object(value);
});
auto& des = ctx.createDeserializer();
des.ext(res,
bitsery::ext::StdMap{ 10 },
[](decltype(des)& des,
NonDefaultConstructible& key,
NonDefaultConstructible& value) {
des.object(key);
des.object(value);
});
EXPECT_THAT(res, ContainerEq(data));
}
struct NonPolymorphicPointers
{
NonDefaultConstructible* pp;
std::unique_ptr<NonDefaultConstructible> up;
std::shared_ptr<NonDefaultConstructible> sp;
std::weak_ptr<NonDefaultConstructible> wp;
};
template <typename S>
void serialize(S& s, NonPolymorphicPointers& o) {
s.ext(o.pp, bitsery::ext::PointerOwner{});
s.ext(o.up, bitsery::ext::StdSmartPtr{});
s.ext(o.sp, bitsery::ext::StdSmartPtr{});
s.ext(o.wp, bitsery::ext::StdSmartPtr{});
template<typename S>
void
serialize(S& s, NonPolymorphicPointers& o)
{
s.ext(o.pp, bitsery::ext::PointerOwner{});
s.ext(o.up, bitsery::ext::StdSmartPtr{});
s.ext(o.sp, bitsery::ext::StdSmartPtr{});
s.ext(o.wp, bitsery::ext::StdSmartPtr{});
}
TEST(DeserializeNonDefaultConstructible, NonPolymorphicPointerAndSmartPointer) {
using SerContext = BasicSerializationContext<bitsery::ext::PointerLinkingContext>;
SerContext ctx{};
NonPolymorphicPointers data{};
data.pp = new NonDefaultConstructible{3};
data.up = std::unique_ptr<NonDefaultConstructible>(new NonDefaultConstructible{54});
data.sp = std::shared_ptr<NonDefaultConstructible>(new NonDefaultConstructible{-481});
data.wp = data.sp;
TEST(DeserializeNonDefaultConstructible, NonPolymorphicPointerAndSmartPointer)
{
using SerContext =
BasicSerializationContext<bitsery::ext::PointerLinkingContext>;
SerContext ctx{};
NonPolymorphicPointers data{};
data.pp = new NonDefaultConstructible{ 3 };
data.up =
std::unique_ptr<NonDefaultConstructible>(new NonDefaultConstructible{ 54 });
data.sp = std::shared_ptr<NonDefaultConstructible>(
new NonDefaultConstructible{ -481 });
data.wp = data.sp;
NonPolymorphicPointers res{};
bitsery::ext::PointerLinkingContext plctx1{};
ctx.createSerializer(plctx1).object(data);
ctx.createDeserializer(plctx1).object(res);
NonPolymorphicPointers res{};
bitsery::ext::PointerLinkingContext plctx1{};
ctx.createSerializer(plctx1).object(data);
ctx.createDeserializer(plctx1).object(res);
EXPECT_THAT(*res.pp, Eq(*data.pp));
delete res.pp;
delete data.pp;
EXPECT_THAT(*res.up, Eq(*data.up));
EXPECT_THAT(*res.sp, Eq(*data.sp));
EXPECT_THAT(*(res.wp.lock()), Eq(*(data.wp.lock())));
EXPECT_THAT(*res.pp, Eq(*data.pp));
delete res.pp;
delete data.pp;
EXPECT_THAT(*res.up, Eq(*data.up));
EXPECT_THAT(*res.sp, Eq(*data.sp));
EXPECT_THAT(*(res.wp.lock()), Eq(*(data.wp.lock())));
}
class PolymorphicNDCBase {
class PolymorphicNDCBase
{
public:
virtual ~PolymorphicNDCBase() = 0;
template <typename S>
void serialize(S& ) {}
virtual ~PolymorphicNDCBase() = 0;
template<typename S>
void serialize(S&)
{
}
};
PolymorphicNDCBase::~PolymorphicNDCBase() = default;
class PolymorphicNDC1:public PolymorphicNDCBase {
int8_t i{};
friend class bitsery::Access;
class PolymorphicNDC1 : public PolymorphicNDCBase
{
int8_t i{};
friend class bitsery::Access;
template<typename S>
void serialize(S& s)
{
s.value1b(i);
}
template <typename S>
void serialize(S& s) {
s.value1b(i);
}
public:
PolymorphicNDC1() = default;
PolymorphicNDC1(int8_t v):i{v} {}
bool operator == (const PolymorphicNDC1& other) const {
return i == other.i;
}
PolymorphicNDC1() = default;
PolymorphicNDC1(int8_t v)
: i{ v }
{
}
bool operator==(const PolymorphicNDC1& other) const { return i == other.i; }
};
class PolymorphicNDC2:public PolymorphicNDCBase {
uint16_t ui{};
class PolymorphicNDC2 : public PolymorphicNDCBase
{
uint16_t ui{};
friend class bitsery::Access;
friend class bitsery::Access;
template<typename S>
void serialize(S& s)
{
s.value2b(ui);
}
template <typename S>
void serialize(S& s) {
s.value2b(ui);
}
public:
PolymorphicNDC2() = default;
PolymorphicNDC2(uint16_t v):ui{v} {}
bool operator == (const PolymorphicNDC2& other) const {
return ui == other.ui;
}
PolymorphicNDC2() = default;
PolymorphicNDC2(uint16_t v)
: ui{ v }
{
}
bool operator==(const PolymorphicNDC2& other) const { return ui == other.ui; }
};
namespace bitsery {
namespace ext {
namespace ext {
template<>
struct PolymorphicBaseClass<PolymorphicNDCBase> : PolymorphicDerivedClasses<PolymorphicNDC1, PolymorphicNDC2> {
};
}
template<>
struct PolymorphicBaseClass<PolymorphicNDCBase>
: PolymorphicDerivedClasses<PolymorphicNDC1, PolymorphicNDC2>
{
};
}
}
struct PolymorphicPointers {
PolymorphicNDCBase* pp;
std::unique_ptr<PolymorphicNDCBase> up;
std::shared_ptr<PolymorphicNDCBase> sp;
std::weak_ptr<PolymorphicNDCBase> wp;
struct PolymorphicPointers
{
PolymorphicNDCBase* pp;
std::unique_ptr<PolymorphicNDCBase> up;
std::shared_ptr<PolymorphicNDCBase> sp;
std::weak_ptr<PolymorphicNDCBase> wp;
};
template <typename S>
void serialize(S& s, PolymorphicPointers& o) {
s.ext(o.pp, bitsery::ext::PointerOwner{});
s.ext(o.up, bitsery::ext::StdSmartPtr{});
s.ext(o.sp, bitsery::ext::StdSmartPtr{});
s.ext(o.wp, bitsery::ext::StdSmartPtr{});
template<typename S>
void
serialize(S& s, PolymorphicPointers& o)
{
s.ext(o.pp, bitsery::ext::PointerOwner{});
s.ext(o.up, bitsery::ext::StdSmartPtr{});
s.ext(o.sp, bitsery::ext::StdSmartPtr{});
s.ext(o.wp, bitsery::ext::StdSmartPtr{});
}
TEST(DeserializeNonDefaultConstructible, PolymorphicPointerAndSmartPointer) {
using TContext = std::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext<bitsery::ext::StandardRTTI>>;
using SerContext = BasicSerializationContext<TContext>;
SerContext ctx{};
PolymorphicPointers data{};
data.pp = new PolymorphicNDC1{-4};
data.up = std::unique_ptr<PolymorphicNDCBase>(new PolymorphicNDC2{54});
data.sp = std::shared_ptr<PolymorphicNDCBase>(new PolymorphicNDC1{15});
data.wp = data.sp;
TEST(DeserializeNonDefaultConstructible, PolymorphicPointerAndSmartPointer)
{
using TContext =
std::tuple<bitsery::ext::PointerLinkingContext,
bitsery::ext::PolymorphicContext<bitsery::ext::StandardRTTI>>;
using SerContext = BasicSerializationContext<TContext>;
SerContext ctx{};
PolymorphicPointers data{};
data.pp = new PolymorphicNDC1{ -4 };
data.up = std::unique_ptr<PolymorphicNDCBase>(new PolymorphicNDC2{ 54 });
data.sp = std::shared_ptr<PolymorphicNDCBase>(new PolymorphicNDC1{ 15 });
data.wp = data.sp;
PolymorphicPointers res{};
PolymorphicPointers res{};
TContext serCtx{};
TContext desCtx{};
TContext serCtx{};
TContext desCtx{};
std::get<1>(serCtx).registerBasesList<typename SerContext::TSerializer>(bitsery::ext::PolymorphicClassesList<PolymorphicNDCBase>{});
std::get<1>(desCtx).registerBasesList<typename SerContext::TDeserializer>(bitsery::ext::PolymorphicClassesList<PolymorphicNDCBase>{});
std::get<1>(serCtx).registerBasesList<typename SerContext::TSerializer>(
bitsery::ext::PolymorphicClassesList<PolymorphicNDCBase>{});
std::get<1>(desCtx).registerBasesList<typename SerContext::TDeserializer>(
bitsery::ext::PolymorphicClassesList<PolymorphicNDCBase>{});
ctx.createSerializer(serCtx).object(data);
ctx.createDeserializer(desCtx).object(res);
auto respp = dynamic_cast<PolymorphicNDC1*>(res.pp);
auto resup = dynamic_cast<PolymorphicNDC2*>(res.up.get());
auto ressp = dynamic_cast<PolymorphicNDC1*>(res.sp.get());
auto reswp = dynamic_cast<PolymorphicNDC1*>(res.wp.lock().get());
ctx.createSerializer(serCtx).object(data);
ctx.createDeserializer(desCtx).object(res);
auto respp = dynamic_cast<PolymorphicNDC1*>(res.pp);
auto resup = dynamic_cast<PolymorphicNDC2*>(res.up.get());
auto ressp = dynamic_cast<PolymorphicNDC1*>(res.sp.get());
auto reswp = dynamic_cast<PolymorphicNDC1*>(res.wp.lock().get());
auto datapp = dynamic_cast<PolymorphicNDC1*>(data.pp);
auto dataup = dynamic_cast<PolymorphicNDC2*>(data.up.get());
auto datasp = dynamic_cast<PolymorphicNDC1*>(data.sp.get());
auto datawp = dynamic_cast<PolymorphicNDC1*>(data.wp.lock().get());
auto datapp = dynamic_cast<PolymorphicNDC1*>(data.pp);
auto dataup = dynamic_cast<PolymorphicNDC2*>(data.up.get());
auto datasp = dynamic_cast<PolymorphicNDC1*>(data.sp.get());
auto datawp = dynamic_cast<PolymorphicNDC1*>(data.wp.lock().get());
EXPECT_THAT(respp, ::testing::Ne(nullptr));
EXPECT_THAT(resup, ::testing::Ne(nullptr));
EXPECT_THAT(ressp, ::testing::Ne(nullptr));
EXPECT_THAT(reswp, ::testing::Ne(nullptr));
EXPECT_THAT(respp, ::testing::Ne(nullptr));
EXPECT_THAT(resup, ::testing::Ne(nullptr));
EXPECT_THAT(ressp, ::testing::Ne(nullptr));
EXPECT_THAT(reswp, ::testing::Ne(nullptr));
EXPECT_THAT(*respp, Eq(*datapp));
delete res.pp;
delete data.pp;
EXPECT_THAT(*resup, Eq(*dataup));
EXPECT_THAT(*ressp, Eq(*datasp));
EXPECT_THAT(*reswp, Eq(*datawp));
std::get<0>(serCtx).clearSharedState();
std::get<0>(desCtx).clearSharedState();
EXPECT_THAT(*respp, Eq(*datapp));
delete res.pp;
delete data.pp;
EXPECT_THAT(*resup, Eq(*dataup));
EXPECT_THAT(*ressp, Eq(*datasp));
EXPECT_THAT(*reswp, Eq(*datawp));
std::get<0>(serCtx).clearSharedState();
std::get<0>(desCtx).clearSharedState();
}

View File

@@ -1,48 +1,48 @@
//MIT License
// MIT License
//
//Copyright (c) 2019 Mindaugas Vinkelis
// Copyright (c) 2019 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
TEST(Serialization, AdapterCanBeMovedInAndOut) {
Buffer buf{};
bitsery::Serializer<Writer> ser1{buf};
ser1.object(MyStruct1{1, 2});
auto writeAdapter = std::move(ser1).adapter();
bitsery::Serializer<Writer> ser2(std::move(writeAdapter));
ser2.object(MyStruct1{3, 4});
auto writtenBytesCount = ser2.adapter().writtenBytesCount();
EXPECT_THAT(writtenBytesCount, Eq(MyStruct1::SIZE + MyStruct1::SIZE));
TEST(Serialization, AdapterCanBeMovedInAndOut)
{
Buffer buf{};
bitsery::Serializer<Writer> ser1{ buf };
ser1.object(MyStruct1{ 1, 2 });
auto writeAdapter = std::move(ser1).adapter();
bitsery::Serializer<Writer> ser2(std::move(writeAdapter));
ser2.object(MyStruct1{ 3, 4 });
auto writtenBytesCount = ser2.adapter().writtenBytesCount();
EXPECT_THAT(writtenBytesCount, Eq(MyStruct1::SIZE + MyStruct1::SIZE));
MyStruct1 res{};
bitsery::Deserializer<Reader> des1{buf.begin(), writtenBytesCount};
des1.object(res);
EXPECT_THAT(res, Eq(MyStruct1{1, 2}));
auto readerAdapter = std::move(des1).adapter();
bitsery::Deserializer<Reader> des2(std::move(readerAdapter));
des2.object(res);
EXPECT_THAT(res, Eq(MyStruct1{3, 4}));
EXPECT_TRUE(des2.adapter().isCompletedSuccessfully());
MyStruct1 res{};
bitsery::Deserializer<Reader> des1{ buf.begin(), writtenBytesCount };
des1.object(res);
EXPECT_THAT(res, Eq(MyStruct1{ 1, 2 }));
auto readerAdapter = std::move(des1).adapter();
bitsery::Deserializer<Reader> des2(std::move(readerAdapter));
des2.object(res);
EXPECT_THAT(res, Eq(MyStruct1{ 3, 4 }));
EXPECT_TRUE(des2.adapter().isCompletedSuccessfully());
}

View File

@@ -1,83 +1,88 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
TEST(SerializeBooleans, BoolAsBit)
{
TEST(SerializeBooleans, BoolAsBit) {
SerializationContext ctx{};
bool t1{true};
bool t2{false};
bool res1;
bool res2;
auto& ser = ctx.createSerializer();
ser.enableBitPacking([&t1, &t2](SerializationContext::TSerializerBPEnabled& sbp) {
sbp.boolValue(t1);
sbp.boolValue(t2);
SerializationContext ctx{};
bool t1{ true };
bool t2{ false };
bool res1;
bool res2;
auto& ser = ctx.createSerializer();
ser.enableBitPacking(
[&t1, &t2](SerializationContext::TSerializerBPEnabled& sbp) {
sbp.boolValue(t1);
sbp.boolValue(t2);
});
auto& des = ctx.createDeserializer();
des.enableBitPacking([&res1, &res2](SerializationContext::TDeserializerBPEnabled& sbp) {
sbp.boolValue(res1);
sbp.boolValue(res2);
auto& des = ctx.createDeserializer();
des.enableBitPacking(
[&res1, &res2](SerializationContext::TDeserializerBPEnabled& sbp) {
sbp.boolValue(res1);
sbp.boolValue(res2);
});
EXPECT_THAT(res1, Eq(t1));
EXPECT_THAT(res2, Eq(t2));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
EXPECT_THAT(res2, Eq(t2));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}
TEST(SerializeBooleans, BoolAsByte) {
SerializationContext ctx;
bool t1{true};
bool t2{false};
bool res1;
bool res2;
auto& ser = ctx.createSerializer();
ser.boolValue(t1);
ser.boolValue(t2);
auto& des = ctx.createDeserializer();
des.boolValue(res1);
des.boolValue(res2);
TEST(SerializeBooleans, BoolAsByte)
{
SerializationContext ctx;
bool t1{ true };
bool t2{ false };
bool res1;
bool res2;
auto& ser = ctx.createSerializer();
ser.boolValue(t1);
ser.boolValue(t2);
auto& des = ctx.createDeserializer();
des.boolValue(res1);
des.boolValue(res2);
EXPECT_THAT(res1, Eq(t1));
EXPECT_THAT(res2, Eq(t2));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
EXPECT_THAT(res1, Eq(t1));
EXPECT_THAT(res2, Eq(t2));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
}
TEST(SerializeBooleans, WhenReadingBoolByteReadsMoreThanOneThenInvalidDataErrorAndResultIsFalse) {
SerializationContext ctx;
auto& ser = ctx.createSerializer();
ser.value1b(uint8_t{1});
ser.value1b(uint8_t{2});
bool res{};
auto& des = ctx.createDeserializer();
des.boolValue(res);
EXPECT_THAT(res, Eq(true));
des.boolValue(res);
EXPECT_THAT(res, Eq(false));
EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData));
TEST(SerializeBooleans,
WhenReadingBoolByteReadsMoreThanOneThenInvalidDataErrorAndResultIsFalse)
{
SerializationContext ctx;
auto& ser = ctx.createSerializer();
ser.value1b(uint8_t{ 1 });
ser.value1b(uint8_t{ 2 });
bool res{};
auto& des = ctx.createDeserializer();
des.boolValue(res);
EXPECT_THAT(res, Eq(true));
des.boolValue(res);
EXPECT_THAT(res, Eq(false));
EXPECT_THAT(ctx.des->adapter().error(),
Eq(bitsery::ReaderError::InvalidData));
}

View File

@@ -1,74 +1,68 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/traits/array.h>
#include <bitsery/traits/list.h>
#include <bitsery/traits/deque.h>
#include <bitsery/traits/forward_list.h>
#include <bitsery/traits/list.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::ContainerEq;
using testing::Eq;
/*
* overload to get container of types
*/
template<typename Container>
Container getFilledContainer() {
return {1, 2, 3, 4, 5, 78, 456, 8, 54};
Container
getFilledContainer()
{
return { 1, 2, 3, 4, 5, 78, 456, 8, 54 };
}
template<>
std::vector<MyStruct1> getFilledContainer<std::vector<MyStruct1>>() {
return {
{0, 1},
{2, 3},
{4, 5},
{6, 7},
{8, 9},
{11, 34},
{5134, 1532}
};
std::vector<MyStruct1>
getFilledContainer<std::vector<MyStruct1>>()
{
return { { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
{ 8, 9 }, { 11, 34 }, { 5134, 1532 } };
}
template<>
std::list<MyStruct2> getFilledContainer<std::list<MyStruct2>>() {
return {
{MyStruct2::V1, {0, 1}},
{MyStruct2::V3, {-45, 45}}
};
std::list<MyStruct2>
getFilledContainer<std::list<MyStruct2>>()
{
return { { MyStruct2::V1, { 0, 1 } }, { MyStruct2::V3, { -45, 45 } } };
}
struct EmptyFtor {
template <typename S, typename T>
void operator() (S& , T& ) {
}
struct EmptyFtor
{
template<typename S, typename T>
void operator()(S&, T&)
{
}
};
/*
@@ -76,197 +70,228 @@ struct EmptyFtor {
*/
template<typename T>
class SerializeContainerDynamicSizeArthmeticTypes : public testing::Test {
class SerializeContainerDynamicSizeArthmeticTypes : public testing::Test
{
public:
using TContainer = T;
using TValue = typename T::value_type;
using TContainer = T;
using TValue = typename T::value_type;
const TContainer src = getFilledContainer<TContainer>();
TContainer res{};
const TContainer src = getFilledContainer<TContainer>();
TContainer res{};
size_t getExpectedBufSize(const SerializationContext &ctx) const {
auto size = bitsery::traits::ContainerTraits<TContainer>::size(src);
return ctx.containerSizeSerializedBytesCount(size) + size * sizeof(TValue);
}
size_t getExpectedBufSize(const SerializationContext& ctx) const
{
auto size = bitsery::traits::ContainerTraits<TContainer>::size(src);
return ctx.containerSizeSerializedBytesCount(size) + size * sizeof(TValue);
}
};
//std::forward_list is not supported, because it doesn't have size() method
using SequenceContainersWithArthmeticTypes = ::testing::Types<
std::vector<int>,
std::list<float>,
std::forward_list<int>,
std::deque<unsigned short>>;
// std::forward_list is not supported, because it doesn't have size() method
using SequenceContainersWithArthmeticTypes =
::testing::Types<std::vector<int>,
std::list<float>,
std::forward_list<int>,
std::deque<unsigned short>>;
TYPED_TEST_SUITE(SerializeContainerDynamicSizeArthmeticTypes, SequenceContainersWithArthmeticTypes,);
TYPED_TEST_SUITE(SerializeContainerDynamicSizeArthmeticTypes,
SequenceContainersWithArthmeticTypes, );
TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, Values) {
SerializationContext ctx{};
using TValue = typename TestFixture::TValue;
TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, Values)
{
SerializationContext ctx{};
using TValue = typename TestFixture::TValue;
ctx.createSerializer().container<sizeof(TValue)>(this->src, 1000);
ctx.createDeserializer().container<sizeof(TValue)>(this->res, 1000);
ctx.createSerializer().container<sizeof(TValue)>(this->src, 1000);
ctx.createDeserializer().container<sizeof(TValue)>(this->res, 1000);
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
EXPECT_THAT(this->res, ContainerEq(this->src));
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
EXPECT_THAT(this->res, ContainerEq(this->src));
}
TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, CustomFunctionIncrements) {
SerializationContext ctx{};
using TValue = typename TestFixture::TValue;
TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes,
CustomFunctionIncrements)
{
SerializationContext ctx{};
using TValue = typename TestFixture::TValue;
auto& ser = ctx.createSerializer();
ser.container(this->src, 1000, [](decltype(ser)& ser, TValue& v) {
ser.template value<sizeof(v)>(v);
});
auto& des = ctx.createDeserializer();
des.container(this->res, 1000, [](decltype(des)& des, TValue &v) {
des.template value<sizeof(v)>(v);
//increment by 1 after reading
v++;
});
//decrement result by 1, before comparing for eq
for (auto &v:this->res)
v = static_cast<TValue>(v-1);
auto& ser = ctx.createSerializer();
ser.container(this->src, 1000, [](decltype(ser)& ser, TValue& v) {
ser.template value<sizeof(v)>(v);
});
auto& des = ctx.createDeserializer();
des.container(this->res, 1000, [](decltype(des)& des, TValue& v) {
des.template value<sizeof(v)>(v);
// increment by 1 after reading
v++;
});
// decrement result by 1, before comparing for eq
for (auto& v : this->res)
v = static_cast<TValue>(v - 1);
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
EXPECT_THAT(this->res, ContainerEq(this->src));
}
template<typename T>
class SerializeContainerDynamicSizeCompositeTypes : public testing::Test {
public:
using TContainer = T;
using TValue = typename T::value_type;
const TContainer src = getFilledContainer<TContainer>();
TContainer res{};
size_t getExpectedBufSize(const SerializationContext &ctx) const {
return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * TValue::SIZE;
}
};
using SerializeContainerDynamicSizeWithCompositeTypes = ::testing::Types<
std::vector<MyStruct1>,
std::list<MyStruct2>>;
TYPED_TEST_SUITE(SerializeContainerDynamicSizeCompositeTypes, SerializeContainerDynamicSizeWithCompositeTypes,);
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, DefaultSerializeFunction) {
SerializationContext ctx{};
ctx.createSerializer().container(this->src, 1000);
ctx.createDeserializer().container(this->res, 1000);
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
EXPECT_THAT(this->res, ContainerEq(this->src));
}
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, CustomFunctionThatDoNothing) {
SerializationContext ctx{};
ctx.createSerializer().container(this->src, 1000, EmptyFtor{});
ctx.createDeserializer().container(this->res, 1000, EmptyFtor{});
EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(this->src.size())));
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
EXPECT_THAT(this->res, ContainerEq(this->src));
}
template<typename T>
class SerializeContainerFixedSizeArithmeticTypes : public testing::Test {
class SerializeContainerDynamicSizeCompositeTypes : public testing::Test
{
public:
using TContainer = T;
using TContainer = T;
using TValue = typename T::value_type;
size_t getContainerSize() {
T tmp{};
return static_cast<size_t>(std::distance(std::begin(tmp), std::end(tmp)));
}
const TContainer src = getFilledContainer<TContainer>();
TContainer res{};
size_t getExpectedBufSize(const SerializationContext& ctx) const
{
return ctx.containerSizeSerializedBytesCount(src.size()) +
src.size() * TValue::SIZE;
}
};
using StaticContainersWithIntegralTypes = ::testing::Types<
std::array<int16_t, 4>,
int16_t[4]>;
using SerializeContainerDynamicSizeWithCompositeTypes =
::testing::Types<std::vector<MyStruct1>, std::list<MyStruct2>>;
TYPED_TEST_SUITE(SerializeContainerFixedSizeArithmeticTypes, StaticContainersWithIntegralTypes,);
TYPED_TEST_SUITE(SerializeContainerDynamicSizeCompositeTypes,
SerializeContainerDynamicSizeWithCompositeTypes, );
TYPED_TEST(SerializeContainerFixedSizeArithmeticTypes, ArithmeticValues) {
using Container = typename TestFixture::TContainer;
Container src{5, 9, 15, -459};
Container res{};
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes,
DefaultSerializeFunction)
{
SerializationContext ctx{};
SerializationContext ctx;
ctx.createSerializer().container<2>(src);
ctx.createDeserializer().container<2>(res);
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * 2));
EXPECT_THAT(res, ContainerEq(src));
ctx.createSerializer().container(this->src, 1000);
ctx.createDeserializer().container(this->res, 1000);
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
EXPECT_THAT(this->res, ContainerEq(this->src));
}
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes,
CustomFunctionThatDoNothing)
{
SerializationContext ctx{};
ctx.createSerializer().container(this->src, 1000, EmptyFtor{});
ctx.createDeserializer().container(this->res, 1000, EmptyFtor{});
EXPECT_THAT(ctx.getBufferSize(),
Eq(ctx.containerSizeSerializedBytesCount(this->src.size())));
}
template<typename T>
class SerializeContainerFixedSizeCompositeTypes : public SerializeContainerFixedSizeArithmeticTypes<T> {
class SerializeContainerFixedSizeArithmeticTypes : public testing::Test
{
public:
using TContainer = T;
size_t getContainerSize()
{
T tmp{};
return static_cast<size_t>(std::distance(std::begin(tmp), std::end(tmp)));
}
};
using StaticContainersWithCompositeTypes = ::testing::Types<
std::array<MyStruct1, 4>, MyStruct1[4]>;
using StaticContainersWithIntegralTypes =
::testing::Types<std::array<int16_t, 4>, int16_t[4]>;
TYPED_TEST_SUITE(SerializeContainerFixedSizeCompositeTypes, StaticContainersWithCompositeTypes,);
TYPED_TEST_SUITE(SerializeContainerFixedSizeArithmeticTypes,
StaticContainersWithIntegralTypes, );
TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, DefaultSerializationFunction) {
using Container = typename TestFixture::TContainer;
Container src{MyStruct1{0, 1}, MyStruct1{8, 9}, MyStruct1{11, 34}, MyStruct1{5134, 1532}};
Container res{};
TYPED_TEST(SerializeContainerFixedSizeArithmeticTypes, ArithmeticValues)
{
using Container = typename TestFixture::TContainer;
Container src{ 5, 9, 15, -459 };
Container res{};
SerializationContext ctx{};
ctx.createSerializer().container(src);
ctx.createDeserializer().container(res);
SerializationContext ctx;
ctx.createSerializer().container<2>(src);
ctx.createDeserializer().container<2>(res);
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * MyStruct1::SIZE));
EXPECT_THAT(res, ContainerEq(src));
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * 2));
EXPECT_THAT(res, ContainerEq(src));
}
TYPED_TEST(SerializeContainerFixedSizeCompositeTypes, CustomFunctionThatSerializesAnEmptyByteEveryElement) {
using Container = typename TestFixture::TContainer;
Container src{MyStruct1{0, 1}, MyStruct1{2, 3}, MyStruct1{4, 5}, MyStruct1{5134, 1532}};
Container res{};
using TValue = decltype(*std::begin(res));
SerializationContext ctx{};
auto& ser = ctx.createSerializer();
ser.container(src, [](decltype(ser)& ser, TValue &v) {
char tmp{};
ser.object(v);
ser.value1b(tmp);
});
auto& des = ctx.createDeserializer();
des.container(res, [](decltype(des)& des, TValue &v) {
char tmp{};
des.object(v);
des.value1b(tmp);
});
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * (MyStruct1::SIZE + sizeof(char))));
EXPECT_THAT(res, ContainerEq(src));
}
class SerializeContainer : public ::testing::TestWithParam<size_t> {
template<typename T>
class SerializeContainerFixedSizeCompositeTypes
: public SerializeContainerFixedSizeArithmeticTypes<T>
{
};
TEST_P(SerializeContainer, SizeHasVariableLength) {
SerializationContext ctx{};
using StaticContainersWithCompositeTypes =
::testing::Types<std::array<MyStruct1, 4>, MyStruct1[4]>;
std::vector<uint8_t > src(GetParam());
std::vector<uint8_t > res{};
ctx.createSerializer().container(src, std::numeric_limits<size_t>::max(), EmptyFtor{});
ctx.createDeserializer().container(res, std::numeric_limits<size_t>::max(), EmptyFtor{});
TYPED_TEST_SUITE(SerializeContainerFixedSizeCompositeTypes,
StaticContainersWithCompositeTypes, );
EXPECT_THAT(res.size(), Eq(src.size()));
EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(src.size())));
TYPED_TEST(SerializeContainerFixedSizeCompositeTypes,
DefaultSerializationFunction)
{
using Container = typename TestFixture::TContainer;
Container src{ MyStruct1{ 0, 1 },
MyStruct1{ 8, 9 },
MyStruct1{ 11, 34 },
MyStruct1{ 5134, 1532 } };
Container res{};
SerializationContext ctx{};
ctx.createSerializer().container(src);
ctx.createDeserializer().container(res);
EXPECT_THAT(ctx.getBufferSize(),
Eq(this->getContainerSize() * MyStruct1::SIZE));
EXPECT_THAT(res, ContainerEq(src));
}
INSTANTIATE_TEST_SUITE_P(LargeContainerSize, SerializeContainer, ::testing::Values(0x01, 0x80, 0x4000));
TYPED_TEST(SerializeContainerFixedSizeCompositeTypes,
CustomFunctionThatSerializesAnEmptyByteEveryElement)
{
using Container = typename TestFixture::TContainer;
Container src{ MyStruct1{ 0, 1 },
MyStruct1{ 2, 3 },
MyStruct1{ 4, 5 },
MyStruct1{ 5134, 1532 } };
Container res{};
using TValue = decltype(*std::begin(res));
SerializationContext ctx{};
auto& ser = ctx.createSerializer();
ser.container(src, [](decltype(ser)& ser, TValue& v) {
char tmp{};
ser.object(v);
ser.value1b(tmp);
});
auto& des = ctx.createDeserializer();
des.container(res, [](decltype(des)& des, TValue& v) {
char tmp{};
des.object(v);
des.value1b(tmp);
});
EXPECT_THAT(ctx.getBufferSize(),
Eq(this->getContainerSize() * (MyStruct1::SIZE + sizeof(char))));
EXPECT_THAT(res, ContainerEq(src));
}
class SerializeContainer : public ::testing::TestWithParam<size_t>
{};
TEST_P(SerializeContainer, SizeHasVariableLength)
{
SerializationContext ctx{};
std::vector<uint8_t> src(GetParam());
std::vector<uint8_t> res{};
ctx.createSerializer().container(
src, std::numeric_limits<size_t>::max(), EmptyFtor{});
ctx.createDeserializer().container(
res, std::numeric_limits<size_t>::max(), EmptyFtor{});
EXPECT_THAT(res.size(), Eq(src.size()));
EXPECT_THAT(ctx.getBufferSize(),
Eq(ctx.containerSizeSerializedBytesCount(src.size())));
}
INSTANTIATE_TEST_SUITE_P(LargeContainerSize,
SerializeContainer,
::testing::Values(0x01, 0x80, 0x4000));

View File

@@ -1,28 +1,27 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
@@ -31,78 +30,89 @@ using bitsery::DefaultConfig;
using SingleTypeContext = int;
using MultipleTypesContext = std::tuple<int, float, char>;
TEST(SerializationContext, WhenContextIsNotTupleThenReturnThisContext) {
SingleTypeContext ctx{54};
BasicSerializationContext<SingleTypeContext> c1;
auto& ser1 = c1.createSerializer(ctx);
TEST(SerializationContext, WhenContextIsNotTupleThenReturnThisContext)
{
SingleTypeContext ctx{ 54 };
BasicSerializationContext<SingleTypeContext> c1;
auto& ser1 = c1.createSerializer(ctx);
EXPECT_THAT(ser1.context<SingleTypeContext>(), Eq(ctx));
EXPECT_THAT(ser1.context<SingleTypeContext>(), Eq(ctx));
}
TEST(SerializationContext, WhenContextIsTupleThenReturnsTupleElements) {
TEST(SerializationContext, WhenContextIsTupleThenReturnsTupleElements)
{
MultipleTypesContext ctx{5, 798.654f, 'F'};
BasicSerializationContext<MultipleTypesContext> c1;
auto& ser1 = c1.createSerializer(ctx);
MultipleTypesContext ctx{ 5, 798.654f, 'F' };
BasicSerializationContext<MultipleTypesContext> c1;
auto& ser1 = c1.createSerializer(ctx);
EXPECT_THAT(ser1.context<int>(), std::get<0>(ctx));
EXPECT_THAT(ser1.context<float>(), std::get<1>(ctx));
EXPECT_THAT(ser1.context<char>(), std::get<2>(ctx));
EXPECT_THAT(ser1.context<int>(), std::get<0>(ctx));
EXPECT_THAT(ser1.context<float>(), std::get<1>(ctx));
EXPECT_THAT(ser1.context<char>(), std::get<2>(ctx));
}
TEST(SerializationContext, WhenContextDoesntExistsThenContextOrNullReturnsNull) {
SingleTypeContext ctx1= 32;
BasicSerializationContext<SingleTypeContext> c1;
TEST(SerializationContext, WhenContextDoesntExistsThenContextOrNullReturnsNull)
{
SingleTypeContext ctx1 = 32;
BasicSerializationContext<SingleTypeContext> c1;
auto& ser = c1.createSerializer(ctx1);
EXPECT_THAT(ser.contextOrNull<char>(), ::testing::IsNull());
EXPECT_THAT(ser.contextOrNull<int>(), ::testing::NotNull());
*ser.contextOrNull<int>() = 2;
EXPECT_THAT(ctx1, Eq(2));
MultipleTypesContext ctx2{ 5, 798.654f, 'F' };
BasicSerializationContext<MultipleTypesContext> c2;
auto& des = c2.createDeserializer(ctx2);
EXPECT_THAT(des.contextOrNull<double>(), ::testing::IsNull());
EXPECT_THAT(des.contextOrNull<int>(), ::testing::NotNull());
EXPECT_THAT(*des.contextOrNull<char>(), Eq('F'));
EXPECT_THAT(*des.contextOrNull<int>(), Eq(5));
}
struct Base
{
int value{};
};
struct Derived : Base
{};
TEST(SerializationContext, ContextWillTryToConvertIfTypeIsConvertible)
{
Derived ctx1{};
BasicSerializationContext<Derived> c1;
auto& ser = c1.createSerializer(ctx1);
EXPECT_THAT(ser.contextOrNull<Derived>(), ::testing::NotNull());
EXPECT_THAT(ser.contextOrNull<Base>(), ::testing::NotNull());
ser.context<Derived>();
ser.context<Base>();
}
TEST(SerializationContext,
WhenMultipleConvertibleTypesExistsThenFirstMatchIsTaken)
{
{
using CTX1 = std::tuple<Base, int, Derived>;
CTX1 ctx1{};
std::get<0>(ctx1).value = 1;
std::get<2>(ctx1).value = 2;
BasicSerializationContext<CTX1> c1;
auto& ser = c1.createSerializer(ctx1);
EXPECT_THAT(ser.contextOrNull<char>(), ::testing::IsNull());
EXPECT_THAT(ser.contextOrNull<int>(), ::testing::NotNull());
*ser.contextOrNull<int>() = 2;
EXPECT_THAT(ctx1, Eq(2));
EXPECT_THAT(ser.context<Derived>().value, Eq(std::get<2>(ctx1).value));
EXPECT_THAT(ser.context<Base>().value, Eq(std::get<0>(ctx1).value));
}
MultipleTypesContext ctx2{5, 798.654f, 'F'};
BasicSerializationContext<MultipleTypesContext> c2;
auto& des = c2.createDeserializer(ctx2);
EXPECT_THAT(des.contextOrNull<double>(), ::testing::IsNull());
EXPECT_THAT(des.contextOrNull<int>(), ::testing::NotNull());
EXPECT_THAT(*des.contextOrNull<char>(), Eq('F'));
EXPECT_THAT(*des.contextOrNull<int>(), Eq(5));
}
struct Base { int value{}; };
struct Derived: Base{};
TEST(SerializationContext, ContextWillTryToConvertIfTypeIsConvertible) {
Derived ctx1{};
BasicSerializationContext<Derived> c1;
auto& ser = c1.createSerializer(ctx1);
EXPECT_THAT(ser.contextOrNull<Derived>(), ::testing::NotNull());
EXPECT_THAT(ser.contextOrNull<Base>(), ::testing::NotNull());
ser.context<Derived>();
ser.context<Base>();
}
TEST(SerializationContext, WhenMultipleConvertibleTypesExistsThenFirstMatchIsTaken) {
{
using CTX1 = std::tuple<Base, int, Derived>;
CTX1 ctx1{};
std::get<0>(ctx1).value = 1;
std::get<2>(ctx1).value = 2;
BasicSerializationContext<CTX1> c1;
auto& ser = c1.createSerializer(ctx1);
EXPECT_THAT(ser.context<Derived>().value, Eq(std::get<2>(ctx1).value));
EXPECT_THAT(ser.context<Base>().value, Eq(std::get<0>(ctx1).value));
}
{
using CTX2 = std::tuple<float, Derived, Base>;
CTX2 ctx2{};
std::get<1>(ctx2).value = 1;
std::get<2>(ctx2).value = 2;
BasicSerializationContext<CTX2> c2;
auto& des = c2.createSerializer(ctx2);
EXPECT_THAT(des.context<Derived>().value, Eq(std::get<1>(ctx2).value));
//Base will not be accessable in this case, because Derived is first valid match
EXPECT_THAT(des.context<Base>().value, Eq(std::get<1>(ctx2).value));
}
{
using CTX2 = std::tuple<float, Derived, Base>;
CTX2 ctx2{};
std::get<1>(ctx2).value = 1;
std::get<2>(ctx2).value = 2;
BasicSerializationContext<CTX2> c2;
auto& des = c2.createSerializer(ctx2);
EXPECT_THAT(des.context<Derived>().value, Eq(std::get<1>(ctx2).value));
// Base will not be accessable in this case, because Derived is first valid
// match
EXPECT_THAT(des.context<Base>().value, Eq(std::get<1>(ctx2).value));
}
}

View File

@@ -1,244 +1,276 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/ext/compact_value.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <bitsery/traits/array.h>
#include <bitset>
#include <chrono>
using testing::Eq;
using bitsery::EndiannessType;
using bitsery::ext::CompactValue;
using bitsery::ext::CompactValueAsObject;
using bitsery::EndiannessType;
using testing::Eq;
// helper function, that gets value filled with specified number of bits
template <typename TValue>
TValue getValue(bool isPositive, size_t significantBits) {
TValue v = isPositive ? 0 : static_cast<TValue>(-1);
if (significantBits == 0)
return v;
template<typename TValue>
TValue
getValue(bool isPositive, size_t significantBits)
{
TValue v = isPositive ? 0 : static_cast<TValue>(-1);
if (significantBits == 0)
return v;
using TUnsigned = typename std::make_unsigned<TValue>::type;
TUnsigned mask = {};
mask = static_cast<TUnsigned>(~mask); // invert shiftByBits
auto shiftBy = bitsery::details::BitsSize<TValue>::value - significantBits;
mask = static_cast<TUnsigned>(mask >> shiftBy);
//cast to unsigned when applying mask
return v ^ static_cast<TValue>(mask);
using TUnsigned = typename std::make_unsigned<TValue>::type;
TUnsigned mask = {};
mask = static_cast<TUnsigned>(~mask); // invert shiftByBits
auto shiftBy = bitsery::details::BitsSize<TValue>::value - significantBits;
mask = static_cast<TUnsigned>(mask >> shiftBy);
// cast to unsigned when applying mask
return v ^ static_cast<TValue>(mask);
}
// helper function, that serialize and return deserialized value
template <typename TConfig, typename TValue>
std::pair<TValue, size_t> serializeAndGetDeserialized(TValue data) {
Buffer buf{};
bitsery::Serializer<bitsery::OutputBufferAdapter<Buffer, TConfig>> ser{buf};
ser.template ext<sizeof(TValue)>(data, CompactValue{});
template<typename TConfig, typename TValue>
std::pair<TValue, size_t>
serializeAndGetDeserialized(TValue data)
{
Buffer buf{};
bitsery::Serializer<bitsery::OutputBufferAdapter<Buffer, TConfig>> ser{ buf };
ser.template ext<sizeof(TValue)>(data, CompactValue{});
bitsery::Deserializer<bitsery::InputBufferAdapter<Buffer, TConfig>> des{buf.begin(), ser.adapter().writtenBytesCount()};
TValue res;
des.template ext<sizeof(TValue)>(res, CompactValue{});
return {res, ser.adapter().writtenBytesCount()};
bitsery::Deserializer<bitsery::InputBufferAdapter<Buffer, TConfig>> des{
buf.begin(), ser.adapter().writtenBytesCount()
};
TValue res;
des.template ext<sizeof(TValue)>(res, CompactValue{});
return { res, ser.adapter().writtenBytesCount() };
}
struct LittleEndianConfig {
static constexpr EndiannessType Endianness = EndiannessType::LittleEndian;
static constexpr bool CheckDataErrors = true;
static constexpr bool CheckAdapterErrors = true;
struct LittleEndianConfig
{
static constexpr EndiannessType Endianness = EndiannessType::LittleEndian;
static constexpr bool CheckDataErrors = true;
static constexpr bool CheckAdapterErrors = true;
};
struct BigEndianConfig {
static constexpr EndiannessType Endianness = EndiannessType::BigEndian;
static constexpr bool CheckDataErrors = true;
static constexpr bool CheckAdapterErrors = true;
struct BigEndianConfig
{
static constexpr EndiannessType Endianness = EndiannessType::BigEndian;
static constexpr bool CheckDataErrors = true;
static constexpr bool CheckAdapterErrors = true;
};
template <typename TValue, bool isPositiveNr, typename TConfig>
struct TC {
static_assert(isPositiveNr || std::is_signed<TValue>::value, "");
template<typename TValue, bool isPositiveNr, typename TConfig>
struct TC
{
static_assert(isPositiveNr || std::is_signed<TValue>::value, "");
using Value = TValue;
using Config = TConfig;
bool isPositive = isPositiveNr;
using Value = TValue;
using Config = TConfig;
bool isPositive = isPositiveNr;
};
template<typename T>
class SerializeExtensionCompactValueCorrectness : public testing::Test {
class SerializeExtensionCompactValueCorrectness : public testing::Test
{
public:
using TestCase = T;
using TestCase = T;
};
using AllValueSizesTestCases =
::testing::Types<TC<uint8_t, true, LittleEndianConfig>,
TC<uint16_t, true, LittleEndianConfig>,
TC<uint32_t, true, LittleEndianConfig>,
TC<uint64_t, true, LittleEndianConfig>,
TC<int8_t, true, LittleEndianConfig>,
TC<int16_t, true, LittleEndianConfig>,
TC<int32_t, true, LittleEndianConfig>,
TC<int64_t, true, LittleEndianConfig>,
TC<int8_t, false, LittleEndianConfig>,
TC<int16_t, false, LittleEndianConfig>,
TC<int32_t, false, LittleEndianConfig>,
TC<int64_t, false, LittleEndianConfig>,
TC<uint8_t, true, BigEndianConfig>,
TC<uint16_t, true, BigEndianConfig>,
TC<uint32_t, true, BigEndianConfig>,
TC<uint64_t, true, BigEndianConfig>,
TC<int8_t, true, BigEndianConfig>,
TC<int16_t, true, BigEndianConfig>,
TC<int32_t, true, BigEndianConfig>,
TC<int64_t, true, BigEndianConfig>,
TC<int8_t, false, BigEndianConfig>,
TC<int16_t, false, BigEndianConfig>,
TC<int32_t, false, BigEndianConfig>,
TC<int64_t, false, BigEndianConfig>>;
using AllValueSizesTestCases = ::testing::Types<
TC<uint8_t, true, LittleEndianConfig>,
TC<uint16_t, true, LittleEndianConfig>,
TC<uint32_t, true, LittleEndianConfig>,
TC<uint64_t, true, LittleEndianConfig>,
TC<int8_t, true, LittleEndianConfig>,
TC<int16_t, true, LittleEndianConfig>,
TC<int32_t, true, LittleEndianConfig>,
TC<int64_t, true, LittleEndianConfig>,
TC<int8_t, false, LittleEndianConfig>,
TC<int16_t, false, LittleEndianConfig>,
TC<int32_t, false, LittleEndianConfig>,
TC<int64_t, false, LittleEndianConfig>,
TC<uint8_t, true, BigEndianConfig>,
TC<uint16_t, true, BigEndianConfig>,
TC<uint32_t, true, BigEndianConfig>,
TC<uint64_t, true, BigEndianConfig>,
TC<int8_t, true, BigEndianConfig>,
TC<int16_t, true, BigEndianConfig>,
TC<int32_t, true, BigEndianConfig>,
TC<int64_t, true, BigEndianConfig>,
TC<int8_t, false, BigEndianConfig>,
TC<int16_t, false, BigEndianConfig>,
TC<int32_t, false, BigEndianConfig>,
TC<int64_t, false, BigEndianConfig>
>;
TYPED_TEST_SUITE(SerializeExtensionCompactValueCorrectness,
AllValueSizesTestCases, );
TYPED_TEST_SUITE(SerializeExtensionCompactValueCorrectness, AllValueSizesTestCases,);
TYPED_TEST(SerializeExtensionCompactValueCorrectness, TestDifferentSizeValues)
{
using TCase = typename TestFixture::TestCase;
using TValue = typename TCase::Value;
TCase tc{};
TYPED_TEST(SerializeExtensionCompactValueCorrectness, TestDifferentSizeValues) {
using TCase = typename TestFixture::TestCase;
using TValue = typename TCase::Value;
TCase tc{};
for (auto i = 0u; i < bitsery::details::BitsSize<TValue>::value + 1; ++i) {
auto data = getValue<TValue>(tc.isPositive, i);
auto res = serializeAndGetDeserialized<typename TCase::Config>(data);
EXPECT_THAT(res.first, Eq(data));
}
for (auto i = 0u; i < bitsery::details::BitsSize<TValue>::value + 1; ++i) {
auto data = getValue<TValue>(tc.isPositive, i);
auto res = serializeAndGetDeserialized<typename TCase::Config>(data);
EXPECT_THAT(res.first, Eq(data));
}
}
// this stucture will contain test data and result, as type paramters
template <typename TValue, bool isPositiveNr, size_t significantBits, size_t resultBytes>
struct SizeTC {
static_assert(isPositiveNr || std::is_signed<TValue>::value, "");
static_assert(bitsery::details::BitsSize<TValue>::value >= significantBits, "");
template<typename TValue,
bool isPositiveNr,
size_t significantBits,
size_t resultBytes>
struct SizeTC
{
static_assert(isPositiveNr || std::is_signed<TValue>::value, "");
static_assert(bitsery::details::BitsSize<TValue>::value >= significantBits,
"");
using Value = TValue;
bool isPositive = isPositiveNr;
size_t fillBits = significantBits;
size_t bytesCount = resultBytes;
using Value = TValue;
bool isPositive = isPositiveNr;
size_t fillBits = significantBits;
size_t bytesCount = resultBytes;
};
template<typename T>
class SerializeExtensionCompactValueRequiredBytes : public testing::Test {
class SerializeExtensionCompactValueRequiredBytes : public testing::Test
{
public:
using TestCase = T;
using TestCase = T;
};
using RequiredBytesTestCases = ::testing::Types<
//1 byte always writes to 1 byte
SizeTC<uint8_t, true, 0,1>,
SizeTC<uint8_t, true, 8,1>,
SizeTC<int8_t, false, 0,1>,
SizeTC<int8_t, true, 8,1>,
// 1 byte always writes to 1 byte
SizeTC<uint8_t, true, 0, 1>,
SizeTC<uint8_t, true, 8, 1>,
SizeTC<int8_t, false, 0, 1>,
SizeTC<int8_t, true, 8, 1>,
//2 byte, +1 byte after 15 significant bits
SizeTC<uint16_t, true, 7,1>,
SizeTC<uint16_t, true, 8,2>,
SizeTC<uint16_t, true, 14,2>,
SizeTC<uint16_t, true, 15,3>,
//2 byte, +1 byte after 15-1 significant bits (1 bit for sign)
SizeTC<int16_t, true, 6,1>,
SizeTC<int16_t, false, 7,2>,
SizeTC<int16_t, true, 13,2>,
SizeTC<int16_t, false, 14,3>,
// 2 byte, +1 byte after 15 significant bits
SizeTC<uint16_t, true, 7, 1>,
SizeTC<uint16_t, true, 8, 2>,
SizeTC<uint16_t, true, 14, 2>,
SizeTC<uint16_t, true, 15, 3>,
// 2 byte, +1 byte after 15-1 significant bits (1 bit for sign)
SizeTC<int16_t, true, 6, 1>,
SizeTC<int16_t, false, 7, 2>,
SizeTC<int16_t, true, 13, 2>,
SizeTC<int16_t, false, 14, 3>,
//4 byte, +1 byte after 29 significant bits
SizeTC<uint32_t, true, 14,2>,
SizeTC<uint32_t, true, 21,3>,
SizeTC<uint32_t, true, 28,4>,
SizeTC<uint32_t, true, 29,5>,
SizeTC<uint32_t, true, 32,5>,
//4 byte
SizeTC<int32_t, true, 13,2>,
SizeTC<int32_t, false, 20,3>,
SizeTC<int32_t, true, 27,4>,
SizeTC<int32_t, false, 28,5>,
SizeTC<int32_t, true, 31,5>,
// 4 byte, +1 byte after 29 significant bits
SizeTC<uint32_t, true, 14, 2>,
SizeTC<uint32_t, true, 21, 3>,
SizeTC<uint32_t, true, 28, 4>,
SizeTC<uint32_t, true, 29, 5>,
SizeTC<uint32_t, true, 32, 5>,
// 4 byte
SizeTC<int32_t, true, 13, 2>,
SizeTC<int32_t, false, 20, 3>,
SizeTC<int32_t, true, 27, 4>,
SizeTC<int32_t, false, 28, 5>,
SizeTC<int32_t, true, 31, 5>,
//8 byte, +1 byte after 57 significant bits, or +2 byte when all bits are significant
SizeTC<uint64_t, true, 28,4>,
SizeTC<uint64_t, true, 35,5>,
SizeTC<uint64_t, true, 42,6>,
SizeTC<uint64_t, true, 49,7>,
SizeTC<uint64_t, true, 56,8>,
SizeTC<uint64_t, true, 57,9>,
SizeTC<uint64_t, true, 63,9>,
SizeTC<uint64_t, true, 64,10>,
//8 byte,
SizeTC<int64_t, true, 27,4>,
SizeTC<int64_t, false, 34,5>,
SizeTC<int64_t, true, 41,6>,
SizeTC<int64_t, false, 48,7>,
SizeTC<int64_t, true, 55,8>,
SizeTC<int64_t, false, 56,9>,
SizeTC<int64_t, true, 62,9>,
SizeTC<int64_t, false, 63,10>
>;
// 8 byte, +1 byte after 57 significant bits, or +2 byte when all bits are
// significant
SizeTC<uint64_t, true, 28, 4>,
SizeTC<uint64_t, true, 35, 5>,
SizeTC<uint64_t, true, 42, 6>,
SizeTC<uint64_t, true, 49, 7>,
SizeTC<uint64_t, true, 56, 8>,
SizeTC<uint64_t, true, 57, 9>,
SizeTC<uint64_t, true, 63, 9>,
SizeTC<uint64_t, true, 64, 10>,
// 8 byte,
SizeTC<int64_t, true, 27, 4>,
SizeTC<int64_t, false, 34, 5>,
SizeTC<int64_t, true, 41, 6>,
SizeTC<int64_t, false, 48, 7>,
SizeTC<int64_t, true, 55, 8>,
SizeTC<int64_t, false, 56, 9>,
SizeTC<int64_t, true, 62, 9>,
SizeTC<int64_t, false, 63, 10>>;
TYPED_TEST_SUITE(SerializeExtensionCompactValueRequiredBytes, RequiredBytesTestCases,);
TYPED_TEST_SUITE(SerializeExtensionCompactValueRequiredBytes,
RequiredBytesTestCases, );
TYPED_TEST(SerializeExtensionCompactValueRequiredBytes, Test) {
using TCase = typename TestFixture::TestCase;
using TValue = typename TCase::Value;
TCase tc{};
TValue data = getValue<TValue>(tc.isPositive, tc.fillBits);
auto res = serializeAndGetDeserialized<bitsery::DefaultConfig>(data);
EXPECT_THAT(res.first, Eq(data));
EXPECT_THAT(res.second, tc.bytesCount);
TYPED_TEST(SerializeExtensionCompactValueRequiredBytes, Test)
{
using TCase = typename TestFixture::TestCase;
using TValue = typename TCase::Value;
TCase tc{};
TValue data = getValue<TValue>(tc.isPositive, tc.fillBits);
auto res = serializeAndGetDeserialized<bitsery::DefaultConfig>(data);
EXPECT_THAT(res.first, Eq(data));
EXPECT_THAT(res.second, tc.bytesCount);
}
enum b1En: uint8_t {
A,B,C,D=54,E
enum b1En : uint8_t
{
A,
B,
C,
D = 54,
E
};
enum class b8En: int64_t {
A=-874987489,B,C=0,D,E=489748978, F,G
enum class b8En : int64_t
{
A = -874987489,
B,
C = 0,
D,
E = 489748978,
F,
G
};
TEST(SerializeExtensionCompactValueEnum, TestEnums) {
auto d1 = b1En::E;
auto d2 = b8En::B;
auto d3 = b8En::F;
EXPECT_THAT(serializeAndGetDeserialized<bitsery::DefaultConfig>(d1).first, Eq(d1));
EXPECT_THAT(serializeAndGetDeserialized<bitsery::DefaultConfig>(d2).first, Eq(d2));
EXPECT_THAT(serializeAndGetDeserialized<bitsery::DefaultConfig>(d3).first, Eq(d3));
TEST(SerializeExtensionCompactValueEnum, TestEnums)
{
auto d1 = b1En::E;
auto d2 = b8En::B;
auto d3 = b8En::F;
EXPECT_THAT(serializeAndGetDeserialized<bitsery::DefaultConfig>(d1).first,
Eq(d1));
EXPECT_THAT(serializeAndGetDeserialized<bitsery::DefaultConfig>(d2).first,
Eq(d2));
EXPECT_THAT(serializeAndGetDeserialized<bitsery::DefaultConfig>(d3).first,
Eq(d3));
}
TEST(SerializeExtensionCompactValueAsObjectDeserializeOverflow, TestEnums) {
SerializationContext ctx;
auto data = getValue<uint32_t >(true, 17);
uint16_t res{};
ctx.createSerializer().ext(data, CompactValueAsObject{});
ctx.createDeserializer().ext(res, CompactValueAsObject{});
EXPECT_THAT(data, ::testing::Ne(res));
EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData));
TEST(SerializeExtensionCompactValueAsObjectDeserializeOverflow, TestEnums)
{
SerializationContext ctx;
auto data = getValue<uint32_t>(true, 17);
uint16_t res{};
ctx.createSerializer().ext(data, CompactValueAsObject{});
ctx.createDeserializer().ext(res, CompactValueAsObject{});
EXPECT_THAT(data, ::testing::Ne(res));
EXPECT_THAT(ctx.des->adapter().error(),
Eq(bitsery::ReaderError::InvalidData));
}

View File

@@ -1,31 +1,30 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/entropy.h>
#include <bitsery/traits/list.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using namespace testing;
@@ -34,167 +33,195 @@ using bitsery::ext::Entropy;
using BPSer = SerializationContext::TSerializerBPEnabled;
using BPDes = SerializationContext::TDeserializerBPEnabled;
TEST(SerializeExtensionEntropy,
WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits)
{
int32_t v = 4849;
int32_t res;
int32_t values[3] = { 485, 4849, 89 };
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking(
[&v, &values](BPSer& ser) { ser.ext4b(v, Entropy<int32_t[3]>{ values }); });
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext4b(res, Entropy<int32_t[3]>{ values });
});
TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits) {
int32_t v = 4849;
int32_t res;
int32_t values[3] = {485,4849,89};
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext4b(v, Entropy<int32_t[3]>{values});
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext4b(res, Entropy<int32_t[3]>{values});
});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
SerializationContext ctx1{};
ctx1.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext4b(v, Entropy<int32_t[3]>{values});
});
ctx1.createDeserializer().enableBitPacking([&res](BPDes& des) {
des.ext(res, bitsery::ext::ValueRange<int32_t>{0, static_cast<int32_t>(3 + 1)});
});
EXPECT_THAT(res, Eq(2));
SerializationContext ctx1{};
ctx1.createSerializer().enableBitPacking(
[&v, &values](BPSer& ser) { ser.ext4b(v, Entropy<int32_t[3]>{ values }); });
ctx1.createDeserializer().enableBitPacking([&res](BPDes& des) {
des.ext(
res, bitsery::ext::ValueRange<int32_t>{ 0, static_cast<int32_t>(3 + 1) });
});
EXPECT_THAT(res, Eq(2));
}
TEST(SerializeExtensionEntropy, WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrObject) {
int16_t v = 8945;
int16_t res;
std::initializer_list<int> values{485,4849,89};
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext2b(v, Entropy<std::initializer_list<int>>{values});
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext2b(res, Entropy<std::initializer_list<int>>{values});
});
TEST(SerializeExtensionEntropy,
WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrObject)
{
int16_t v = 8945;
int16_t res;
std::initializer_list<int> values{ 485, 4849, 89 };
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext2b(v, Entropy<std::initializer_list<int>>{ values });
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext2b(res, Entropy<std::initializer_list<int>>{ values });
});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int16_t)+1));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int16_t) + 1));
}
TEST(SerializeExtensionEntropy, CustomTypeEntropyEncoded) {
MyStruct1 v = {12,10};
MyStruct1 res;
constexpr size_t N = 4;
TEST(SerializeExtensionEntropy, CustomTypeEntropyEncoded)
{
MyStruct1 v = { 12, 10 };
MyStruct1 res;
constexpr size_t N = 4;
MyStruct1 values[N]{
MyStruct1{12, 10}, MyStruct1{485, 454},
MyStruct1{4849, 89}, MyStruct1{0, 1}};
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext(v, Entropy<MyStruct1[4]>{values});
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext(res, Entropy<MyStruct1[4]>{values});
});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
MyStruct1 values[N]{ MyStruct1{ 12, 10 },
MyStruct1{ 485, 454 },
MyStruct1{ 4849, 89 },
MyStruct1{ 0, 1 } };
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking(
[&v, &values](BPSer& ser) { ser.ext(v, Entropy<MyStruct1[4]>{ values }); });
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext(res, Entropy<MyStruct1[4]>{ values });
});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}
TEST(SerializeExtensionEntropy, CustomTypeNotEntropyEncoded) {
MyStruct1 v = {8945,4456};
MyStruct1 res;
TEST(SerializeExtensionEntropy, CustomTypeNotEntropyEncoded)
{
MyStruct1 v = { 8945, 4456 };
MyStruct1 res;
std::initializer_list<MyStruct1> values {
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext(v, Entropy<std::initializer_list<MyStruct1>>{values});
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext(res, Entropy<std::initializer_list<MyStruct1>>{values});
});
std::initializer_list<MyStruct1> values{ MyStruct1{ 12, 10 },
MyStruct1{ 485, 454 },
MyStruct1{ 4849, 89 },
MyStruct1{ 0, 1 } };
SerializationContext ctx{};
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext(v, Entropy<std::initializer_list<MyStruct1>>{ values });
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext(res, Entropy<std::initializer_list<MyStruct1>>{ values });
});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1));
}
TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncodedWithNoAlignBeforeData) {
MyStruct1 v = {8945,4456};
MyStruct1 res;
constexpr size_t N = 4;
TEST(SerializeExtensionEntropy,
CustomFunctionNotEntropyEncodedWithNoAlignBeforeData)
{
MyStruct1 v = { 8945, 4456 };
MyStruct1 res;
constexpr size_t N = 4;
std::vector<MyStruct1> values{
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
std::vector<MyStruct1> values{ MyStruct1{ 12, 10 },
MyStruct1{ 485, 454 },
MyStruct1{ 4849, 89 },
MyStruct1{ 0, 1 } };
auto rangeForValue = bitsery::ext::ValueRange<int>{0, 10000};
auto rangeForValue = bitsery::ext::ValueRange<int>{ 0, 10000 };
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&v, &values, &rangeForValue](BPSer& ser){
//lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind...
auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) {
ser.ext(data.i1, rangeForValue);
ser.ext(data.i2, rangeForValue);
};
ser.ext(v, Entropy<std::vector<MyStruct1>>(values, false), serLambda);
SerializationContext ctx;
ctx.createSerializer().enableBitPacking(
[&v, &values, &rangeForValue](BPSer& ser) {
// lambdas differ only in capture clauses, it would make sense to use
// std::bind, but debugger crashes when it sees std::bind...
auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) {
ser.ext(data.i1, rangeForValue);
ser.ext(data.i2, rangeForValue);
};
ser.ext(v, Entropy<std::vector<MyStruct1>>(values, false), serLambda);
});
ctx.createDeserializer().enableBitPacking([&res, &values, &rangeForValue](BPDes& des) {
auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) {
des.ext(data.i1, rangeForValue);
des.ext(data.i2, rangeForValue);
};
des.ext(res, Entropy<std::vector<MyStruct1>>(values, false), desLambda);
ctx.createDeserializer().enableBitPacking(
[&res, &values, &rangeForValue](BPDes& des) {
auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) {
des.ext(data.i1, rangeForValue);
des.ext(data.i2, rangeForValue);
};
des.ext(res, Entropy<std::vector<MyStruct1>>(values, false), desLambda);
});
EXPECT_THAT(res, Eq(v));
auto rangeForIndex = bitsery::ext::ValueRange<size_t>{0u, N+1};
EXPECT_THAT(ctx.getBufferSize(), Eq((rangeForIndex.getRequiredBits() + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 ));
EXPECT_THAT(res, Eq(v));
auto rangeForIndex = bitsery::ext::ValueRange<size_t>{ 0u, N + 1 };
EXPECT_THAT(ctx.getBufferSize(),
Eq((rangeForIndex.getRequiredBits() +
rangeForValue.getRequiredBits() * 2 - 1) /
8 +
1));
}
TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncodedWithAlignBeforeData) {
MyStruct1 v = {8945,4456};
MyStruct1 res;
TEST(SerializeExtensionEntropy,
CustomFunctionNotEntropyEncodedWithAlignBeforeData)
{
MyStruct1 v = { 8945, 4456 };
MyStruct1 res;
std::vector<MyStruct1> values{
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
std::vector<MyStruct1> values{ MyStruct1{ 12, 10 },
MyStruct1{ 485, 454 },
MyStruct1{ 4849, 89 },
MyStruct1{ 0, 1 } };
auto rangeForValue = bitsery::ext::ValueRange<int>{0, 10000};
auto rangeForValue = bitsery::ext::ValueRange<int>{ 0, 10000 };
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&v, &values, &rangeForValue](BPSer& ser){
//lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind...
auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) {
ser.ext(data.i1, rangeForValue);
ser.ext(data.i2, rangeForValue);
};
ser.ext(v, Entropy<std::vector<MyStruct1>>(values, true), serLambda);
SerializationContext ctx;
ctx.createSerializer().enableBitPacking(
[&v, &values, &rangeForValue](BPSer& ser) {
// lambdas differ only in capture clauses, it would make sense to use
// std::bind, but debugger crashes when it sees std::bind...
auto serLambda = [&rangeForValue](BPSer& ser, MyStruct1& data) {
ser.ext(data.i1, rangeForValue);
ser.ext(data.i2, rangeForValue);
};
ser.ext(v, Entropy<std::vector<MyStruct1>>(values, true), serLambda);
});
ctx.createDeserializer().enableBitPacking([&res, &values, &rangeForValue](BPDes& des) {
auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) {
des.ext(data.i1, rangeForValue);
des.ext(data.i2, rangeForValue);
};
des.ext(res, Entropy<std::vector<MyStruct1>>(values, true), desLambda);
ctx.createDeserializer().enableBitPacking(
[&res, &values, &rangeForValue](BPDes& des) {
auto desLambda = [&rangeForValue](BPDes& des, MyStruct1& data) {
des.ext(data.i1, rangeForValue);
des.ext(data.i2, rangeForValue);
};
des.ext(res, Entropy<std::vector<MyStruct1>>(values, true), desLambda);
});
EXPECT_THAT(res, Eq(v));
auto bitsForIndex = 8u; //because aligned
EXPECT_THAT(ctx.getBufferSize(), Eq((bitsForIndex + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 ));
EXPECT_THAT(res, Eq(v));
auto bitsForIndex = 8u; // because aligned
EXPECT_THAT(
ctx.getBufferSize(),
Eq((bitsForIndex + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1));
}
TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenCustomFunctionNotInvoked) {
MyStruct1 v = {4849,89};
MyStruct1 res;
TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenCustomFunctionNotInvoked)
{
MyStruct1 v = { 4849, 89 };
MyStruct1 res;
std::list<MyStruct1> values {MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
std::list<MyStruct1> values{ MyStruct1{ 12, 10 },
MyStruct1{ 485, 454 },
MyStruct1{ 4849, 89 },
MyStruct1{ 0, 1 } };
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext(v, Entropy<std::list<MyStruct1>>{values}, [](BPSer& ,MyStruct1& ) {});
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext(res, Entropy<std::list<MyStruct1>>{values}, [](BPDes& , MyStruct1& ) {});
});
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&v, &values](BPSer& ser) {
ser.ext(
v, Entropy<std::list<MyStruct1>>{ values }, [](BPSer&, MyStruct1&) {});
});
ctx.createDeserializer().enableBitPacking([&res, &values](BPDes& des) {
des.ext(
res, Entropy<std::list<MyStruct1>>{ values }, [](BPDes&, MyStruct1&) {});
});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}

View File

@@ -1,238 +1,253 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/ext/growable.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using namespace testing;
using bitsery::ext::Growable;
struct DataV1 {
int32_t v1;
struct DataV1
{
int32_t v1;
};
template <typename S>
void serialize(S& s, DataV1& o) {
s.value4b(o.v1);
template<typename S>
void
serialize(S& s, DataV1& o)
{
s.value4b(o.v1);
}
struct DataV2 {
int32_t v1;
int32_t v2;
struct DataV2
{
int32_t v1;
int32_t v2;
};
template <typename S>
void serialize(S& s, DataV2& o) {
s.value4b(o.v1);
s.value4b(o.v2);
template<typename S>
void
serialize(S& s, DataV2& o)
{
s.value4b(o.v1);
s.value4b(o.v2);
}
struct DataV3 {
int32_t v1;
int32_t v2;
int32_t v3;
template <typename S>
void serialize(S& s) {
s.value4b(v1);
s.value4b(v2);
s.value4b(v3);
}
struct DataV3
{
int32_t v1;
int32_t v2;
int32_t v3;
template<typename S>
void serialize(S& s)
{
s.value4b(v1);
s.value4b(v2);
s.value4b(v3);
}
};
TEST(SerializeExtensionGrowable, SessionsLengthIsStoredWith4BytesBeforeSessionDataStarts) {
SerializationContext ctx;
auto& ser = ctx.createSerializer();
//session cannot be empty
ser.value2b(int16_t{1});
ser.ext(int8_t{2}, Growable{}, [] (decltype(ser)& ser, int8_t& v) {
ser.value1b(v);
TEST(SerializeExtensionGrowable,
SessionsLengthIsStoredWith4BytesBeforeSessionDataStarts)
{
SerializationContext ctx;
auto& ser = ctx.createSerializer();
// session cannot be empty
ser.value2b(int16_t{ 1 });
ser.ext(int8_t{ 2 }, Growable{}, [](decltype(ser)& ser, int8_t& v) {
ser.value1b(v);
});
ser.value1b(int8_t{ 3 });
auto& des = ctx.createDeserializer();
uint8_t res1b{};
uint16_t res2b{};
uint32_t res4b{};
des.value2b(res2b);
EXPECT_THAT(res2b, Eq(1));
des.value4b(res4b);
EXPECT_THAT(res4b, Eq(1 + 4)); // size + 4bytes
des.value1b(res1b);
EXPECT_THAT(res1b, Eq(2));
des.value1b(res1b);
EXPECT_THAT(res1b, Eq(3));
EXPECT_THAT(ctx.ser->adapter().writtenBytesCount(), Eq(8));
}
TEST(SerializeExtensionGrowable, MultipleSessionsReadSameVersionData)
{
SerializationContext ctx;
DataV2 data{ 8454, 987451 };
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{});
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleSessionsReadNewerVersionData)
{
SerializationContext ctx;
DataV3 data{ 8454, 987451, 45612 };
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{});
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleSessionsReadOlderVersionData)
{
SerializationContext ctx;
DataV2 data{ 8454, 987451 };
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{});
}
ctx.createDeserializer();
DataV3 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
EXPECT_THAT(res.v3, Eq(0));
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadSameVersionData)
{
SerializationContext ctx;
DataV2 data{ 8454, 987451 };
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) {
ser.value4b(o.v1);
ser.value4b(o.v2);
ser.ext(o, Growable{});
});
ser.value1b(int8_t{3});
auto& des = ctx.createDeserializer();
uint8_t res1b{};
uint16_t res2b{};
uint32_t res4b{};
des.value2b(res2b);
EXPECT_THAT(res2b, Eq(1));
des.value4b(res4b);
EXPECT_THAT(res4b, Eq(1+4));//size + 4bytes
des.value1b(res1b);
EXPECT_THAT(res1b, Eq(2));
des.value1b(res1b);
EXPECT_THAT(res1b, Eq(3));
EXPECT_THAT(ctx.ser->adapter().writtenBytesCount(), Eq(8));
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) {
des.value4b(o.v1);
des.value4b(o.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
des.ext(o, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
});
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleSessionsReadSameVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
auto& ser = ctx.createSerializer();
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadNewerVersionData)
{
SerializationContext ctx;
DataV3 data{ 8454, 987451, 54124 };
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{});
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV3& o) {
ser.value4b(o.v1);
ser.value4b(o.v2);
ser.ext(o, Growable{});
// new fields can only be added at the end
ser.value4b(o.v3);
});
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) {
des.value4b(o.v1);
des.value4b(o.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
des.ext(o, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
});
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleSessionsReadNewerVersionData) {
SerializationContext ctx;
DataV3 data{8454,987451, 45612};
auto& ser = ctx.createSerializer();
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadOlderVersionData)
{
SerializationContext ctx;
DataV2 data{ 8454, 987451 };
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{});
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleSessionsReadOlderVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{});
}
ctx.createDeserializer();
DataV3 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
EXPECT_THAT(res.v3, Eq(0));
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadSameVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) {
ser.value4b(o.v1);
ser.value4b(o.v2);
ser.ext(o, Growable{});
});
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) {
des.value4b(o.v1);
des.value4b(o.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
des.ext(o, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
});
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadNewerVersionData) {
SerializationContext ctx;
DataV3 data{8454,987451, 54124};
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV3& o) {
ser.value4b(o.v1);
ser.value4b(o.v2);
ser.ext(o, Growable{});
//new fields can only be added at the end
ser.value4b(o.v3);
});
}
ctx.createDeserializer();
DataV2 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV2& o) {
des.value4b(o.v1);
des.value4b(o.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
des.ext(o, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
});
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadOlderVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
auto& ser = ctx.createSerializer();
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) {
ser.value4b(o.v1);
ser.value4b(o.v2);
ser.ext(o, Growable{});
});
}
ctx.createDeserializer();
DataV3 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV3& o) {
des.value4b(o.v1);
des.value4b(o.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
des.ext(o, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
EXPECT_THAT(res.v3, Eq(0));
//new fields can only be added at the end
des.value4b(o.v3);
EXPECT_THAT(res.v3, Eq(0));
});
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
for (auto i = 0; i < 10; ++i) {
ser.ext(data, Growable{}, [](decltype(ser)& ser, DataV2& o) {
ser.value4b(o.v1);
ser.value4b(o.v2);
ser.ext(o, Growable{});
});
}
ctx.createDeserializer();
DataV3 res{};
auto& des = ctx.createDeserializer();
for (auto i = 0; i < 10; ++i) {
des.ext(res, Growable{}, [&res, &data](decltype(des)& des, DataV3& o) {
des.value4b(o.v1);
des.value4b(o.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
des.ext(o, Growable{});
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
EXPECT_THAT(res.v3, Eq(0));
// new fields can only be added at the end
des.value4b(o.v3);
EXPECT_THAT(res.v3, Eq(0));
});
}
EXPECT_THAT(ctx.des->adapter().isCompletedSuccessfully(), Eq(true));
}

View File

@@ -1,28 +1,28 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/ext/inheritance.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using bitsery::ext::BaseClass;
using bitsery::ext::VirtualBaseClass;
@@ -34,332 +34,400 @@ using testing::Eq;
/*
* base class
*/
struct Base {
uint8_t x{};
virtual ~Base() = default;
struct Base
{
uint8_t x{};
virtual ~Base() = default;
};
template <typename S>
void serialize(S& s, Base& o) {
s.value1b(o.x);
template<typename S>
void
serialize(S& s, Base& o)
{
s.value1b(o.x);
}
/*
* non virtual inheritance from base
*/
struct Derive1NonVirtually:Base {
uint8_t y1{};
struct Derive1NonVirtually : Base
{
uint8_t y1{};
};
template <typename S>
void serialize(S& s, Derive1NonVirtually& o) {
s.ext(o, BaseClass<Base>{});
s.value1b(o.y1);
template<typename S>
void
serialize(S& s, Derive1NonVirtually& o)
{
s.ext(o, BaseClass<Base>{});
s.value1b(o.y1);
}
struct Derive2NonVirtually:Base {
uint8_t y2{};
struct Derive2NonVirtually : Base
{
uint8_t y2{};
};
template <typename S>
void serialize(S& s, Derive2NonVirtually& o) {
//use lambda to serialize base
s.ext(o, BaseClass<Base>{}, [](S& s, Base& b) {
s.object(b);
});
s.value1b(o.y2);
template<typename S>
void
serialize(S& s, Derive2NonVirtually& o)
{
// use lambda to serialize base
s.ext(o, BaseClass<Base>{}, [](S& s, Base& b) { s.object(b); });
s.value1b(o.y2);
}
struct MultipleInheritanceNonVirtualBase: Derive1NonVirtually, Derive2NonVirtually {
uint8_t z{};
struct MultipleInheritanceNonVirtualBase
: Derive1NonVirtually
, Derive2NonVirtually
{
uint8_t z{};
};
template <typename S>
void serialize(S& s, MultipleInheritanceNonVirtualBase& o) {
s.ext(o, BaseClass<Derive1NonVirtually>{});
s.ext(o, BaseClass<Derive2NonVirtually>{});
s.value1b(o.z);
template<typename S>
void
serialize(S& s, MultipleInheritanceNonVirtualBase& o)
{
s.ext(o, BaseClass<Derive1NonVirtually>{});
s.ext(o, BaseClass<Derive2NonVirtually>{});
s.value1b(o.z);
}
/*
* virtual inheritance from base
*/
struct Derive1Virtually:virtual Base {
uint8_t y1{};
struct Derive1Virtually : virtual Base
{
uint8_t y1{};
};
template <typename S>
void serialize(S& s, Derive1Virtually& o) {
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y1);
template<typename S>
void
serialize(S& s, Derive1Virtually& o)
{
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y1);
}
struct Derive2Virtually:virtual Base {
uint8_t y2{};
struct Derive2Virtually : virtual Base
{
uint8_t y2{};
};
template <typename S>
void serialize(S& s, Derive2Virtually& o) {
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y2);
template<typename S>
void
serialize(S& s, Derive2Virtually& o)
{
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y2);
}
struct MultipleInheritanceVirtualBase: Derive1Virtually, Derive2Virtually {
uint8_t z{};
MultipleInheritanceVirtualBase() = default;
struct MultipleInheritanceVirtualBase
: Derive1Virtually
, Derive2Virtually
{
uint8_t z{};
MultipleInheritanceVirtualBase() = default;
MultipleInheritanceVirtualBase(uint8_t x_, uint8_t y1_, uint8_t y2_, uint8_t z_) {
x = x_;
y1 = y1_;
y2 = y2_;
z = z_;
}
template <typename S>
void serialize(S& s) {
s.ext(*this, BaseClass<Derive1Virtually>{});
s.ext(*this, BaseClass<Derive2Virtually>{});
s.value1b(z);
}
MultipleInheritanceVirtualBase(uint8_t x_,
uint8_t y1_,
uint8_t y2_,
uint8_t z_)
{
x = x_;
y1 = y1_;
y2 = y2_;
z = z_;
}
template<typename S>
void serialize(S& s)
{
s.ext(*this, BaseClass<Derive1Virtually>{});
s.ext(*this, BaseClass<Derive2Virtually>{});
s.value1b(z);
}
};
bool operator == (const MultipleInheritanceVirtualBase& lhs, const MultipleInheritanceVirtualBase& rhs) {
return std::tie(lhs.x, lhs.y1, lhs.y2, lhs.z) == std::tie(rhs.x, rhs.y1, rhs.y2, rhs.z);
bool
operator==(const MultipleInheritanceVirtualBase& lhs,
const MultipleInheritanceVirtualBase& rhs)
{
return std::tie(lhs.x, lhs.y1, lhs.y2, lhs.z) ==
std::tie(rhs.x, rhs.y1, rhs.y2, rhs.z);
}
TEST(SerializeExtensionInheritance, BaseClass) {
TEST(SerializeExtensionInheritance, BaseClass)
{
Derive1NonVirtually d1{};
d1.x = 187;
d1.y1 = 74;
Derive1NonVirtually rd1{};
Derive1NonVirtually d1{};
d1.x = 187;
d1.y1 = 74;
Derive1NonVirtually rd1{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(d1);
ctx.createDeserializer(inherCtxDes).object(rd1);
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(d1);
ctx.createDeserializer(inherCtxDes).object(rd1);
EXPECT_THAT(rd1.x, Eq(d1.x));
EXPECT_THAT(rd1.y1, Eq(d1.y1));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
EXPECT_THAT(rd1.x, Eq(d1.x));
EXPECT_THAT(rd1.y1, Eq(d1.y1));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
}
TEST(SerializeExtensionInheritance, VirtualBaseClass) {
Derive1Virtually d1{};
d1.x = 15;
d1.y1 = 87;
Derive1Virtually rd1{};
TEST(SerializeExtensionInheritance, VirtualBaseClass)
{
Derive1Virtually d1{};
d1.x = 15;
d1.y1 = 87;
Derive1Virtually rd1{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(d1);
ctx.createDeserializer(inherCtxDes).object(rd1);
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(d1);
ctx.createDeserializer(inherCtxDes).object(rd1);
EXPECT_THAT(rd1.x, Eq(d1.x));
EXPECT_THAT(rd1.y1, Eq(d1.y1));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
EXPECT_THAT(rd1.x, Eq(d1.x));
EXPECT_THAT(rd1.y1, Eq(d1.y1));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
}
TEST(SerializeExtensionInheritance, MultipleBasesWithoutVirtualInheritance) {
MultipleInheritanceNonVirtualBase md{};
//x is ambiguous because we don't derive virtually
static_cast<Derive1NonVirtually&>(md).x = 1;
static_cast<Derive2NonVirtually&>(md).x = 2;
md.y1 = 4;
md.z = 5;
md.y2 = 6;
MultipleInheritanceNonVirtualBase res{};
TEST(SerializeExtensionInheritance, MultipleBasesWithoutVirtualInheritance)
{
MultipleInheritanceNonVirtualBase md{};
// x is ambiguous because we don't derive virtually
static_cast<Derive1NonVirtually&>(md).x = 1;
static_cast<Derive2NonVirtually&>(md).x = 2;
md.y1 = 4;
md.z = 5;
md.y2 = 6;
MultipleInheritanceNonVirtualBase res{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(md);
ctx.createDeserializer(inherCtxDes).object(res);
EXPECT_THAT(static_cast<Derive1NonVirtually&>(res).x, Eq(static_cast<Derive1NonVirtually&>(md).x));
EXPECT_THAT(static_cast<Derive2NonVirtually&>(res).x, Eq(static_cast<Derive2NonVirtually&>(md).x));
EXPECT_THAT(res.y1, Eq(md.y1));
EXPECT_THAT(res.y2, Eq(md.y2));
EXPECT_THAT(res.z, Eq(md.z));
EXPECT_THAT(ctx.getBufferSize(), Eq(5)); //5 because two bases
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(md);
ctx.createDeserializer(inherCtxDes).object(res);
EXPECT_THAT(static_cast<Derive1NonVirtually&>(res).x,
Eq(static_cast<Derive1NonVirtually&>(md).x));
EXPECT_THAT(static_cast<Derive2NonVirtually&>(res).x,
Eq(static_cast<Derive2NonVirtually&>(md).x));
EXPECT_THAT(res.y1, Eq(md.y1));
EXPECT_THAT(res.y2, Eq(md.y2));
EXPECT_THAT(res.z, Eq(md.z));
EXPECT_THAT(ctx.getBufferSize(), Eq(5)); // 5 because two bases
}
TEST(SerializeExtensionInheritance, WhenNoVirtualInheritanceExistsThenInheritanceContextIsNotRequired) {
MultipleInheritanceNonVirtualBase md{};
//x is ambiguous because we don't derive virtually
static_cast<Derive1NonVirtually&>(md).x = 1;
static_cast<Derive2NonVirtually&>(md).x = 2;
md.y1 = 4;
md.z = 5;
md.y2 = 6;
MultipleInheritanceNonVirtualBase res{};
TEST(SerializeExtensionInheritance,
WhenNoVirtualInheritanceExistsThenInheritanceContextIsNotRequired)
{
MultipleInheritanceNonVirtualBase md{};
// x is ambiguous because we don't derive virtually
static_cast<Derive1NonVirtually&>(md).x = 1;
static_cast<Derive2NonVirtually&>(md).x = 2;
md.y1 = 4;
md.z = 5;
md.y2 = 6;
MultipleInheritanceNonVirtualBase res{};
//without InheritanceContext
SerializationContext ctx{};
ctx.createSerializer().object(md);
ctx.createDeserializer().object(res);
EXPECT_THAT(static_cast<Derive1NonVirtually&>(res).x, Eq(static_cast<Derive1NonVirtually&>(md).x));
EXPECT_THAT(static_cast<Derive2NonVirtually&>(res).x, Eq(static_cast<Derive2NonVirtually&>(md).x));
EXPECT_THAT(res.y1, Eq(md.y1));
EXPECT_THAT(res.y2, Eq(md.y2));
EXPECT_THAT(res.z, Eq(md.z));
EXPECT_THAT(ctx.getBufferSize(), Eq(5)); //5 because two bases
// without InheritanceContext
SerializationContext ctx{};
ctx.createSerializer().object(md);
ctx.createDeserializer().object(res);
EXPECT_THAT(static_cast<Derive1NonVirtually&>(res).x,
Eq(static_cast<Derive1NonVirtually&>(md).x));
EXPECT_THAT(static_cast<Derive2NonVirtually&>(res).x,
Eq(static_cast<Derive2NonVirtually&>(md).x));
EXPECT_THAT(res.y1, Eq(md.y1));
EXPECT_THAT(res.y2, Eq(md.y2));
EXPECT_THAT(res.z, Eq(md.z));
EXPECT_THAT(ctx.getBufferSize(), Eq(5)); // 5 because two bases
}
TEST(SerializeExtensionInheritance, MultipleBasesWithVirtualInheritance)
{
MultipleInheritanceVirtualBase md{ 3, 7, 5, 15 };
MultipleInheritanceVirtualBase res{};
TEST(SerializeExtensionInheritance, MultipleBasesWithVirtualInheritance) {
MultipleInheritanceVirtualBase md{3,7,5,15};
MultipleInheritanceVirtualBase res{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(md);
ctx.createDeserializer(inherCtxDes).object(res);
EXPECT_THAT(res, Eq(md));
EXPECT_THAT(ctx.getBufferSize(), Eq(4)); //4 because virtual base
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(md);
ctx.createDeserializer(inherCtxDes).object(res);
EXPECT_THAT(res, Eq(md));
EXPECT_THAT(ctx.getBufferSize(), Eq(4)); // 4 because virtual base
}
TEST(SerializeExtensionInheritance, MultipleBasesWithVirtualInheritanceMultipleObjects) {
std::vector<MultipleInheritanceVirtualBase> data;
data.emplace_back(4,8,7,9);
data.emplace_back(1,2,3,4);
data.emplace_back(8,7,15,97);
data.emplace_back(54,132,45,84);
data.emplace_back(27,85,41,2);
std::vector<MultipleInheritanceVirtualBase> res{};
TEST(SerializeExtensionInheritance,
MultipleBasesWithVirtualInheritanceMultipleObjects)
{
std::vector<MultipleInheritanceVirtualBase> data;
data.emplace_back(4, 8, 7, 9);
data.emplace_back(1, 2, 3, 4);
data.emplace_back(8, 7, 15, 97);
data.emplace_back(54, 132, 45, 84);
data.emplace_back(27, 85, 41, 2);
std::vector<MultipleInheritanceVirtualBase> res{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).container(data, 10);
ctx.createDeserializer(inherCtxDes).container(res, 10);
EXPECT_THAT(res, ::testing::ContainerEq(data));
EXPECT_THAT(ctx.getBufferSize(), Eq(1 + 4 * data.size())); //1 container size + 4 because virtual base * elements
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).container(data, 10);
ctx.createDeserializer(inherCtxDes).container(res, 10);
EXPECT_THAT(res, ::testing::ContainerEq(data));
EXPECT_THAT(
ctx.getBufferSize(),
Eq(1 +
4 *
data.size())); // 1 container size + 4 because virtual base * elements
}
//
class BasePrivateSerialize {
class BasePrivateSerialize
{
public:
explicit BasePrivateSerialize(uint8_t v):_v{v} {}
uint8_t getX() const { return _v; }
explicit BasePrivateSerialize(uint8_t v)
: _v{ v }
{
}
uint8_t getX() const { return _v; }
private:
uint8_t _v;
friend bitsery::Access;
template <typename S>
void serialize(S& s) {
s.value1b(_v);
}
uint8_t _v;
friend bitsery::Access;
template<typename S>
void serialize(S& s)
{
s.value1b(_v);
}
};
class DerivedPrivateBase: public BasePrivateSerialize {
class DerivedPrivateBase : public BasePrivateSerialize
{
public:
explicit DerivedPrivateBase(uint8_t v) : BasePrivateSerialize(v) {}
uint8_t z{};
explicit DerivedPrivateBase(uint8_t v)
: BasePrivateSerialize(v)
{
}
uint8_t z{};
};
template <typename S>
void serialize(S& s, DerivedPrivateBase& o) {
//use lambda for base serialization
s.ext(o, BaseClass<BasePrivateSerialize>{}, [](S& s, BasePrivateSerialize& b) {
s.object(b);
});
s.value1b(o.z);
template<typename S>
void
serialize(S& s, DerivedPrivateBase& o)
{
// use lambda for base serialization
s.ext(o,
BaseClass<BasePrivateSerialize>{},
[](S& s, BasePrivateSerialize& b) { s.object(b); });
s.value1b(o.z);
}
struct BaseNonMemberSerialize {
uint8_t x{};
struct BaseNonMemberSerialize
{
uint8_t x{};
};
template <typename S>
void serialize(S& s, BaseNonMemberSerialize& o) {
s.value1b(o.x);
template<typename S>
void
serialize(S& s, BaseNonMemberSerialize& o)
{
s.value1b(o.x);
}
struct DerivedMemberSerialize: public BaseNonMemberSerialize {
uint8_t z{};
template <typename S>
void serialize(S& s) {
s.ext(*this, BaseClass<BaseNonMemberSerialize>{});
s.value1b(z);
}
struct DerivedMemberSerialize : public BaseNonMemberSerialize
{
uint8_t z{};
template<typename S>
void serialize(S& s)
{
s.ext(*this, BaseClass<BaseNonMemberSerialize>{});
s.value1b(z);
}
};
//explicitly select serialize functions, for types that has ambiguous serialize functions
// explicitly select serialize functions, for types that has ambiguous serialize
// functions
namespace bitsery {
template <>
struct SelectSerializeFnc<DerivedPrivateBase>:UseNonMemberFnc {};
template <>
struct SelectSerializeFnc<DerivedMemberSerialize>:UseMemberFnc {};
}
TEST(SerializeExtensionInheritance, WhenDerivedClassHasAmbiguousSerializeFunctionThenExplicitlySelectSpecialization) {
DerivedPrivateBase data1{43};
data1.z = 87;
DerivedMemberSerialize data2{};
data2.x = 71;
data2.z = 22;
DerivedPrivateBase res1{0};
DerivedMemberSerialize res2{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(data1);
ctx.createSerializer(inherCtxSer).object(data2);
ctx.createDeserializer(inherCtxDes).object(res1);
ctx.createDeserializer(inherCtxDes).object(res2);
EXPECT_THAT(res1.getX(), Eq(data1.getX()));
EXPECT_THAT(res1.z, Eq(data1.z));
EXPECT_THAT(res2.x, Eq(data2.x));
EXPECT_THAT(res2.z, Eq(data2.z));
}
struct AbstractBase {
uint8_t x{};
virtual void exec() = 0;
virtual ~AbstractBase() = default;
template <typename S>
void serialize(S& s) {
s.value1b(x);
}
template<>
struct SelectSerializeFnc<DerivedPrivateBase> : UseNonMemberFnc
{
};
struct ImplementedBase:AbstractBase {
uint8_t y{};
void exec() override {}
template<>
struct SelectSerializeFnc<DerivedMemberSerialize> : UseMemberFnc
{
};
}
template <typename S>
void serialize(S& s) {
s.ext(*this, BaseClass<AbstractBase>{});
s.value1b(y);
}
TEST(
SerializeExtensionInheritance,
WhenDerivedClassHasAmbiguousSerializeFunctionThenExplicitlySelectSpecialization)
{
DerivedPrivateBase data1{ 43 };
data1.z = 87;
DerivedMemberSerialize data2{};
data2.x = 71;
data2.z = 22;
DerivedPrivateBase res1{ 0 };
DerivedMemberSerialize res2{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(data1);
ctx.createSerializer(inherCtxSer).object(data2);
ctx.createDeserializer(inherCtxDes).object(res1);
ctx.createDeserializer(inherCtxDes).object(res2);
EXPECT_THAT(res1.getX(), Eq(data1.getX()));
EXPECT_THAT(res1.z, Eq(data1.z));
EXPECT_THAT(res2.x, Eq(data2.x));
EXPECT_THAT(res2.z, Eq(data2.z));
}
struct AbstractBase
{
uint8_t x{};
virtual void exec() = 0;
virtual ~AbstractBase() = default;
template<typename S>
void serialize(S& s)
{
s.value1b(x);
}
};
TEST(SerializeExtensionInheritance, CanSerializeAbstractClass) {
ImplementedBase data{};
data.x = 4;
data.y = 2;
data.exec();
ImplementedBase res{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(data);
ctx.createDeserializer(inherCtxDes).object(res);
EXPECT_THAT(res.x, Eq(data.x));
EXPECT_THAT(res.y, Eq(data.y));
struct ImplementedBase : AbstractBase
{
uint8_t y{};
void exec() override {}
template<typename S>
void serialize(S& s)
{
s.ext(*this, BaseClass<AbstractBase>{});
s.value1b(y);
}
};
TEST(SerializeExtensionInheritance, CanSerializeAbstractClass)
{
ImplementedBase data{};
data.x = 4;
data.y = 2;
data.exec();
ImplementedBase res{};
SerContext ctx{};
bitsery::ext::InheritanceContext inherCtxSer{};
bitsery::ext::InheritanceContext inherCtxDes{};
ctx.createSerializer(inherCtxSer).object(data);
ctx.createDeserializer(inherCtxDes).object(res);
EXPECT_THAT(res.x, Eq(data.x));
EXPECT_THAT(res.y, Eq(data.y));
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,30 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/inheritance.h>
#include <bitsery/ext/pointer.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using bitsery::ext::BaseClass;
using bitsery::ext::VirtualBaseClass;
@@ -35,294 +34,342 @@ using bitsery::ext::PointerLinkingContext;
using bitsery::ext::PolymorphicContext;
using bitsery::ext::StandardRTTI;
using bitsery::ext::PointerOwner;
using bitsery::ext::PointerObserver;
using bitsery::ext::PointerOwner;
using bitsery::ext::ReferencedByPointer;
using testing::Eq;
using TContext = std::tuple<PointerLinkingContext, InheritanceContext, PolymorphicContext<StandardRTTI>>;
using TContext = std::tuple<PointerLinkingContext,
InheritanceContext,
PolymorphicContext<StandardRTTI>>;
using SerContext = BasicSerializationContext<TContext>;
//this is useful for PolymorphicContext to bind classes to serializer/deserializer
// this is useful for PolymorphicContext to bind classes to
// serializer/deserializer
using TSerializer = typename SerContext::TSerializer;
using TDeserializer = typename SerContext::TDeserializer;
/*
* base class
*/
struct Base {
uint8_t x{};
struct Base
{
uint8_t x{};
virtual ~Base() = default;
virtual ~Base() = default;
};
template<typename S>
void serialize(S &s, Base &o) {
s.value1b(o.x);
void
serialize(S& s, Base& o)
{
s.value1b(o.x);
}
struct Derived1 : virtual Base {
uint8_t y1{};
struct Derived1 : virtual Base
{
uint8_t y1{};
};
template<typename S>
void serialize(S &s, Derived1 &o) {
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y1);
void
serialize(S& s, Derived1& o)
{
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y1);
}
struct Derived2 : virtual Base {
uint8_t y2{};
struct Derived2 : virtual Base
{
uint8_t y2{};
};
template<typename S>
void serialize(S &s, Derived2 &o) {
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y2);
void
serialize(S& s, Derived2& o)
{
s.ext(o, VirtualBaseClass<Base>{});
s.value1b(o.y2);
}
struct MultipleVirtualInheritance : Derived1, Derived2 {
int8_t z{};
struct MultipleVirtualInheritance
: Derived1
, Derived2
{
int8_t z{};
MultipleVirtualInheritance() = default;
MultipleVirtualInheritance() = default;
MultipleVirtualInheritance(uint8_t x_, uint8_t y1_, uint8_t y2_, int8_t z_) {
x = x_;
y1 = y1_;
y2 = y2_;
z = z_;
}
template<typename S>
void serialize(S &s) {
s.ext(*this, BaseClass<Derived1>{});
s.ext(*this, BaseClass<Derived2>{});
s.value1b(z);
}
MultipleVirtualInheritance(uint8_t x_, uint8_t y1_, uint8_t y2_, int8_t z_)
{
x = x_;
y1 = y1_;
y2 = y2_;
z = z_;
}
template<typename S>
void serialize(S& s)
{
s.ext(*this, BaseClass<Derived1>{});
s.ext(*this, BaseClass<Derived2>{});
s.value1b(z);
}
};
//this class has no relationships specified via PolymorphicBaseClass
struct NoRelationshipSpecifiedDerived : Base {
};
// this class has no relationships specified via PolymorphicBaseClass
struct NoRelationshipSpecifiedDerived : Base
{};
//these classes will be used to "cheat" a little bit when testing deserialization flows
struct BaseClone {
uint8_t x{};
// these classes will be used to "cheat" a little bit when testing
// deserialization flows
struct BaseClone
{
uint8_t x{};
virtual ~BaseClone() = default;
virtual ~BaseClone() = default;
};
template<typename S>
void serialize(S &s, BaseClone &o) {
s.value1b(o.x);
void
serialize(S& s, BaseClone& o)
{
s.value1b(o.x);
}
//define relationships between base class and derived classes for runtime polymorphism
// define relationships between base class and derived classes for runtime
// polymorphism
namespace bitsery {
namespace ext {
namespace ext {
template<>
struct PolymorphicBaseClass<Base> : PolymorphicDerivedClasses<Derived1, Derived2> {
};
// this is commented on purpose, to test scenario when base class is registered (Base)
// but using instance of Derived1 which is not registered as base
// template<>
// struct PolymorphicBaseClass<Derived1> : PolymorphicDerivedClasses<MultipleVirtualInheritance> {
// };
template<>
struct PolymorphicBaseClass<Derived2> : PolymorphicDerivedClasses<MultipleVirtualInheritance> {
};
}
}
class SerializeExtensionPointerPolymorphicTypes : public testing::Test {
public:
TContext plctx{};
SerContext sctx{};
typename SerContext::TSerializer& createSerializer() {
auto& res = sctx.createSerializer(plctx);
std::get<2>(plctx).clear();
//bind serializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TSerializer>(bitsery::ext::PolymorphicClassesList<Base>{});
return res;
}
typename SerContext::TDeserializer& createDeserializer() {
auto& res = sctx.createDeserializer(plctx);
std::get<2>(plctx).clear();
//bind deserializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TDeserializer>(bitsery::ext::PolymorphicClassesList<Base>{});
return res;
}
bool isPointerContextValid() {
return std::get<0>(plctx).isValid();
}
virtual void TearDown() override {
EXPECT_TRUE(isPointerContextValid());
}
template<>
struct PolymorphicBaseClass<Base>
: PolymorphicDerivedClasses<Derived1, Derived2>
{
};
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result0) {
Base *baseData = nullptr;
createSerializer().ext(baseData, PointerOwner{});
Base *baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
// this is commented on purpose, to test scenario when base class is registered
// (Base) but using instance of Derived1 which is not registered as base
// template<>
// struct PolymorphicBaseClass<Derived1> :
// PolymorphicDerivedClasses<MultipleVirtualInheritance> {
// };
EXPECT_THAT(baseRes, ::testing::IsNull());
EXPECT_THAT(baseData, ::testing::IsNull());
template<>
struct PolymorphicBaseClass<Derived2>
: PolymorphicDerivedClasses<MultipleVirtualInheritance>
{
};
}
}
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result1) {
Base *baseData = nullptr;
createSerializer().ext(baseData, PointerOwner{});
class SerializeExtensionPointerPolymorphicTypes : public testing::Test
{
public:
TContext plctx{};
SerContext sctx{};
Base *baseRes = new Derived1{};
createDeserializer().ext(baseRes, PointerOwner{});
typename SerContext::TSerializer& createSerializer()
{
auto& res = sctx.createSerializer(plctx);
std::get<2>(plctx).clear();
// bind serializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TSerializer>(
bitsery::ext::PolymorphicClassesList<Base>{});
return res;
}
EXPECT_THAT(baseRes, ::testing::IsNull());
EXPECT_THAT(baseData, ::testing::IsNull());
typename SerContext::TDeserializer& createDeserializer()
{
auto& res = sctx.createDeserializer(plctx);
std::get<2>(plctx).clear();
// bind deserializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TDeserializer>(
bitsery::ext::PolymorphicClassesList<Base>{});
return res;
}
bool isPointerContextValid() { return std::get<0>(plctx).isValid(); }
virtual void TearDown() override { EXPECT_TRUE(isPointerContextValid()); }
};
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result0)
{
Base* baseData = nullptr;
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
EXPECT_THAT(baseRes, ::testing::IsNull());
EXPECT_THAT(baseData, ::testing::IsNull());
}
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result0) {
Derived1 d1{};
d1.x = 3;
d1.y1 = 78;
Base *baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
Base *baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data0Result1)
{
Base* baseData = nullptr;
createSerializer().ext(baseData, PointerOwner{});
auto *data = dynamic_cast<Derived1 *>(baseData);
auto *res = dynamic_cast<Derived1 *>(baseRes);
Base* baseRes = new Derived1{};
createDeserializer().ext(baseRes, PointerOwner{});
EXPECT_THAT(baseRes, ::testing::NotNull());
EXPECT_THAT(data, ::testing::NotNull());
EXPECT_THAT(res, ::testing::NotNull());
EXPECT_THAT(res->x, Eq(data->x));
EXPECT_THAT(res->y1, Eq(data->y1));
delete baseRes;
EXPECT_THAT(baseRes, ::testing::IsNull());
EXPECT_THAT(baseData, ::testing::IsNull());
}
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result1) {
Derived1 d1{};
d1.x = 3;
d1.y1 = 78;
Base *baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
Base *baseRes = &d1;
createDeserializer().ext(baseRes, PointerOwner{});
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result0)
{
Derived1 d1{};
d1.x = 3;
d1.y1 = 78;
Base* baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
auto *data = dynamic_cast<Derived1 *>(baseData);
auto *res = dynamic_cast<Derived1 *>(baseRes);
auto* data = dynamic_cast<Derived1*>(baseData);
auto* res = dynamic_cast<Derived1*>(baseRes);
EXPECT_THAT(baseRes, ::testing::NotNull());
EXPECT_THAT(data, ::testing::NotNull());
EXPECT_THAT(res, ::testing::NotNull());
EXPECT_THAT(res->x, Eq(data->x));
EXPECT_THAT(res->y1, Eq(data->y1));
EXPECT_THAT(baseRes, ::testing::NotNull());
EXPECT_THAT(data, ::testing::NotNull());
EXPECT_THAT(res, ::testing::NotNull());
EXPECT_THAT(res->x, Eq(data->x));
EXPECT_THAT(res->y1, Eq(data->y1));
delete baseRes;
}
TEST_F(SerializeExtensionPointerPolymorphicTypes, ComplexTypeWithVirtualInheritanceData1Result0) {
MultipleVirtualInheritance md1{};
md1.x = 3;
md1.y1 = 78;
md1.y2 = 14;
md1.z = -33;
Base *baseData = &md1;
createSerializer().ext(baseData, PointerOwner{});
Base *baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
TEST_F(SerializeExtensionPointerPolymorphicTypes, Data1Result1)
{
Derived1 d1{};
d1.x = 3;
d1.y1 = 78;
Base* baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = &d1;
createDeserializer().ext(baseRes, PointerOwner{});
auto *data = dynamic_cast<MultipleVirtualInheritance *>(baseData);
auto *res = dynamic_cast<MultipleVirtualInheritance *>(baseRes);
auto* data = dynamic_cast<Derived1*>(baseData);
auto* res = dynamic_cast<Derived1*>(baseRes);
EXPECT_THAT(baseRes, ::testing::NotNull());
EXPECT_THAT(data, ::testing::NotNull());
EXPECT_THAT(res, ::testing::NotNull());
EXPECT_THAT(res->x, Eq(data->x));
EXPECT_THAT(res->y1, Eq(data->y1));
EXPECT_THAT(res->y2, Eq(data->y2));
EXPECT_THAT(res->z, Eq(data->z));
delete baseRes;
EXPECT_THAT(baseRes, ::testing::NotNull());
EXPECT_THAT(data, ::testing::NotNull());
EXPECT_THAT(res, ::testing::NotNull());
EXPECT_THAT(res->x, Eq(data->x));
EXPECT_THAT(res->y1, Eq(data->y1));
}
TEST_F(SerializeExtensionPointerPolymorphicTypes, WhenResultIsDifferentTypeThenRecreate) {
MultipleVirtualInheritance md1{};
md1.x = 3;
md1.y1 = 78;
md1.y2 = 14;
md1.z = -33;
Base *baseData = &md1;
createSerializer().ext(baseData, PointerOwner{});
Base *baseRes = new Derived1{};
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance *>(baseRes), ::testing::IsNull());
createDeserializer().ext(baseRes, PointerOwner{});
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance *>(baseRes), ::testing::NotNull());
delete baseRes;
TEST_F(SerializeExtensionPointerPolymorphicTypes,
ComplexTypeWithVirtualInheritanceData1Result0)
{
MultipleVirtualInheritance md1{};
md1.x = 3;
md1.y1 = 78;
md1.y2 = 14;
md1.z = -33;
Base* baseData = &md1;
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
auto* data = dynamic_cast<MultipleVirtualInheritance*>(baseData);
auto* res = dynamic_cast<MultipleVirtualInheritance*>(baseRes);
EXPECT_THAT(baseRes, ::testing::NotNull());
EXPECT_THAT(data, ::testing::NotNull());
EXPECT_THAT(res, ::testing::NotNull());
EXPECT_THAT(res->x, Eq(data->x));
EXPECT_THAT(res->y1, Eq(data->y1));
EXPECT_THAT(res->y2, Eq(data->y2));
EXPECT_THAT(res->z, Eq(data->z));
delete baseRes;
}
TEST_F(SerializeExtensionPointerPolymorphicTypes,
WhenResultIsDifferentTypeThenRecreate)
{
MultipleVirtualInheritance md1{};
md1.x = 3;
md1.y1 = 78;
md1.y2 = 14;
md1.z = -33;
Base* baseData = &md1;
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = new Derived1{};
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance*>(baseRes),
::testing::IsNull());
createDeserializer().ext(baseRes, PointerOwner{});
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance*>(baseRes),
::testing::NotNull());
delete baseRes;
}
#ifndef NDEBUG
TEST_F(SerializeExtensionPointerPolymorphicTypes,
WhenSerializingDerivedTypeWithoutSpecifiedRelationshipsWithBaseThenAssert) {
TEST_F(
SerializeExtensionPointerPolymorphicTypes,
WhenSerializingDerivedTypeWithoutSpecifiedRelationshipsWithBaseThenAssert)
{
NoRelationshipSpecifiedDerived md1;//this class has no relationships specified via PolymorphicBaseClass
Base *baseData = &md1;
EXPECT_DEATH(createSerializer().ext(baseData, PointerOwner{}), "");
NoRelationshipSpecifiedDerived
md1; // this class has no relationships specified via PolymorphicBaseClass
Base* baseData = &md1;
EXPECT_DEATH(createSerializer().ext(baseData, PointerOwner{}), "");
}
TEST_F(SerializeExtensionPointerPolymorphicTypes,
WhenDeserializingDerivedTypeNotRegisteredWithPolymorphicContextThenAssert) {
TEST_F(
SerializeExtensionPointerPolymorphicTypes,
WhenDeserializingDerivedTypeNotRegisteredWithPolymorphicContextThenAssert)
{
Derived1 d1{};
Base *baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
Derived1 d1{};
Base* baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
BaseClone *baseRes = nullptr; //this class is not registered
EXPECT_DEATH(createDeserializer().ext(baseRes, PointerOwner{}), "");
BaseClone* baseRes = nullptr; // this class is not registered
EXPECT_DEATH(createDeserializer().ext(baseRes, PointerOwner{}), "");
}
#endif
TEST_F(SerializeExtensionPointerPolymorphicTypes,
CompileTimeTypeIsDerivedAndReachableFromBaseRegisteredWithPolymorphicContext) {
TEST_F(
SerializeExtensionPointerPolymorphicTypes,
CompileTimeTypeIsDerivedAndReachableFromBaseRegisteredWithPolymorphicContext)
{
MultipleVirtualInheritance md;
Derived2 *derivedData = &md;//this class is not registered via PolymorphicContext
createSerializer().ext(derivedData, PointerOwner{});
Derived2 *derivedRes = new Derived2{};
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance *>(derivedRes), ::testing::IsNull());
createDeserializer().ext(derivedRes, PointerOwner{});
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance *>(derivedRes), ::testing::NotNull());
delete derivedRes;
MultipleVirtualInheritance md;
Derived2* derivedData =
&md; // this class is not registered via PolymorphicContext
createSerializer().ext(derivedData, PointerOwner{});
Derived2* derivedRes = new Derived2{};
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance*>(derivedRes),
::testing::IsNull());
createDeserializer().ext(derivedRes, PointerOwner{});
EXPECT_THAT(dynamic_cast<MultipleVirtualInheritance*>(derivedRes),
::testing::NotNull());
delete derivedRes;
}
TEST_F(SerializeExtensionPointerPolymorphicTypes,
WhenPolymorphicTypeNotFoundDuringDeserializionThenInvalidPointerError) {
WhenPolymorphicTypeNotFoundDuringDeserializionThenInvalidPointerError)
{
Derived1 d1{};
Base *baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
Derived1 d1{};
Base* baseData = &d1;
createSerializer().ext(baseData, PointerOwner{});
BaseClone *baseRes = nullptr; //this class will be registered, but it doesn't have relationships specified via PolymorphicBaseClass
auto& des = sctx.createDeserializer(plctx);
auto &pc = std::get<2>(plctx);
pc.clear();
pc.registerBasesList<SerContext::TDeserializer>(bitsery::ext::PolymorphicClassesList<BaseClone>{});
des.ext(baseRes, PointerOwner{});
EXPECT_THAT(sctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidPointer));
BaseClone* baseRes =
nullptr; // this class will be registered, but it doesn't have relationships
// specified via PolymorphicBaseClass
auto& des = sctx.createDeserializer(plctx);
auto& pc = std::get<2>(plctx);
pc.clear();
pc.registerBasesList<SerContext::TDeserializer>(
bitsery::ext::PolymorphicClassesList<BaseClone>{});
des.ext(baseRes, PointerOwner{});
EXPECT_THAT(sctx.des->adapter().error(),
Eq(bitsery::ReaderError::InvalidPointer));
}

View File

@@ -1,32 +1,31 @@
//MIT License
// MIT License
//
//Copyright (c) 2019 Mindaugas Vinkelis
// Copyright (c) 2019 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/inheritance.h>
#include <bitsery/ext/pointer.h>
#include <bitsery/ext/std_smart_ptr.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using bitsery::ext::BaseClass;
using bitsery::ext::VirtualBaseClass;
@@ -36,332 +35,396 @@ using bitsery::ext::PointerLinkingContext;
using bitsery::ext::PolymorphicContext;
using bitsery::ext::StandardRTTI;
using bitsery::ext::PointerOwner;
using bitsery::ext::PointerObserver;
using bitsery::ext::PointerOwner;
using bitsery::ext::ReferencedByPointer;
using bitsery::ext::StdSmartPtr;
using testing::Eq;
using TContext = std::tuple<PointerLinkingContext, InheritanceContext, PolymorphicContext<StandardRTTI>>;
using TContext = std::tuple<PointerLinkingContext,
InheritanceContext,
PolymorphicContext<StandardRTTI>>;
using SerContext = BasicSerializationContext<TContext>;
//this is useful for PolymorphicContext to bind classes to serializer/deserializer
// this is useful for PolymorphicContext to bind classes to
// serializer/deserializer
using TSerializer = typename SerContext::TSerializer;
using TDeserializer = typename SerContext::TDeserializer;
/*
* base class
*/
struct Base {
Base() = default;
struct Base
{
Base() = default;
explicit Base(uint64_t v) : x{v} {}
explicit Base(uint64_t v)
: x{ v }
{
}
uint64_t x{};
uint64_t x{};
virtual ~Base() = default;
virtual ~Base() = default;
};
template<typename S>
void serialize(S& s, Base& o) {
s.value8b(o.x);
void
serialize(S& s, Base& o)
{
s.value8b(o.x);
}
struct Derived1 : Base {
Derived1() = default;
struct Derived1 : Base
{
Derived1() = default;
Derived1(uint64_t x_, uint64_t y_) : Base{x_}, y1{y_} {}
Derived1(uint64_t x_, uint64_t y_)
: Base{ x_ }
, y1{ y_ }
{
}
friend bool operator==(const Derived1& lhs, const Derived1& rhs) {
return lhs.x == rhs.x && lhs.y1 == rhs.y1;
}
friend bool operator==(const Derived1& lhs, const Derived1& rhs)
{
return lhs.x == rhs.x && lhs.y1 == rhs.y1;
}
uint64_t y1{};
uint64_t y1{};
};
template<typename S>
void serialize(S& s, Derived1& o) {
s.ext(o, BaseClass<Base>{});
s.value8b(o.y1);
void
serialize(S& s, Derived1& o)
{
s.ext(o, BaseClass<Base>{});
s.value8b(o.y1);
}
struct Derived2 : Base {
uint64_t y1{};
uint64_t y2{};
struct Derived2 : Base
{
uint64_t y1{};
uint64_t y2{};
};
template<typename S>
void serialize(S& s, Derived2& o) {
s.ext(o, BaseClass<Base>{});
s.value8b(o.y1);
s.value8b(o.y2);
void
serialize(S& s, Derived2& o)
{
s.ext(o, BaseClass<Base>{});
s.value8b(o.y1);
s.value8b(o.y2);
}
// polymorphic structure that contains polymorphic pointer, to test memory resource propagation
struct PolyPtrWithPolyPtrBase {
std::unique_ptr<Base> ptr{};
// polymorphic structure that contains polymorphic pointer, to test memory
// resource propagation
struct PolyPtrWithPolyPtrBase
{
std::unique_ptr<Base> ptr{};
virtual ~PolyPtrWithPolyPtrBase() = default;
virtual ~PolyPtrWithPolyPtrBase() = default;
};
template<typename S>
void serialize(S& s, PolyPtrWithPolyPtrBase& o) {
s.ext(o.ptr, StdSmartPtr{});
void
serialize(S& s, PolyPtrWithPolyPtrBase& o)
{
s.ext(o.ptr, StdSmartPtr{});
}
struct DerivedPolyPtrWithPolyPtr : PolyPtrWithPolyPtrBase {
};
struct DerivedPolyPtrWithPolyPtr : PolyPtrWithPolyPtrBase
{};
template<typename S>
void serialize(S& s, DerivedPolyPtrWithPolyPtr& o) {
s.ext(o.ptr, StdSmartPtr{});
void
serialize(S& s, DerivedPolyPtrWithPolyPtr& o)
{
s.ext(o.ptr, StdSmartPtr{});
}
//define relationships between base class and derived classes for runtime polymorphism
// define relationships between base class and derived classes for runtime
// polymorphism
namespace bitsery {
namespace ext {
namespace ext {
template<>
struct PolymorphicBaseClass<Base> : PolymorphicDerivedClasses<Derived1, Derived2> {
};
template<>
struct PolymorphicBaseClass<Base>
: PolymorphicDerivedClasses<Derived1, Derived2>
{
};
template<>
struct PolymorphicBaseClass<PolyPtrWithPolyPtrBase> : PolymorphicDerivedClasses<DerivedPolyPtrWithPolyPtr> {
};
template<>
struct PolymorphicBaseClass<PolyPtrWithPolyPtrBase>
: PolymorphicDerivedClasses<DerivedPolyPtrWithPolyPtr>
{
};
}
}
}
// this class is for testing
struct TestAllocInfo {
void* ptr;
size_t bytes;
size_t alignment;
size_t typeId;
struct TestAllocInfo
{
void* ptr;
size_t bytes;
size_t alignment;
size_t typeId;
friend bool operator==(const TestAllocInfo& lhs, const TestAllocInfo& rhs) {
return std::tie(lhs.ptr, lhs.bytes, lhs.alignment, lhs.typeId) ==
std::tie(rhs.ptr, rhs.bytes, rhs.alignment, rhs.typeId);
}
friend bool operator==(const TestAllocInfo& lhs, const TestAllocInfo& rhs)
{
return std::tie(lhs.ptr, lhs.bytes, lhs.alignment, lhs.typeId) ==
std::tie(rhs.ptr, rhs.bytes, rhs.alignment, rhs.typeId);
}
};
struct MemResourceForTest : public bitsery::ext::MemResourceBase {
struct MemResourceForTest : public bitsery::ext::MemResourceBase
{
void* allocate(size_t bytes, size_t alignment, size_t typeId) override {
const auto res = bitsery::ext::MemResourceNewDelete{}.allocate(bytes, alignment, typeId);
allocs.push_back({res, bytes, alignment, typeId});
return res;
}
void* allocate(size_t bytes, size_t alignment, size_t typeId) override
{
const auto res =
bitsery::ext::MemResourceNewDelete{}.allocate(bytes, alignment, typeId);
allocs.push_back({ res, bytes, alignment, typeId });
return res;
}
void deallocate(void* ptr, size_t bytes, size_t alignment, size_t typeId) noexcept override {
deallocs.push_back({ptr, bytes, alignment, typeId});
bitsery::ext::MemResourceNewDelete{}.deallocate(ptr, bytes, alignment, typeId);
}
void deallocate(void* ptr,
size_t bytes,
size_t alignment,
size_t typeId) noexcept override
{
deallocs.push_back({ ptr, bytes, alignment, typeId });
bitsery::ext::MemResourceNewDelete{}.deallocate(
ptr, bytes, alignment, typeId);
}
std::vector<TestAllocInfo> allocs{};
std::vector<TestAllocInfo> deallocs{};
std::vector<TestAllocInfo> allocs{};
std::vector<TestAllocInfo> deallocs{};
};
class SerializeExtensionPointerWithAllocator : public testing::Test {
class SerializeExtensionPointerWithAllocator : public testing::Test
{
public:
TContext plctx{};
SerContext sctx{};
TContext plctx{};
SerContext sctx{};
typename SerContext::TSerializer& createSerializer()
{
auto& res = sctx.createSerializer(plctx);
std::get<2>(plctx).clear();
// bind serializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TSerializer>(
bitsery::ext::PolymorphicClassesList<Base, PolyPtrWithPolyPtrBase>{});
return res;
}
typename SerContext::TSerializer& createSerializer() {
auto& res = sctx.createSerializer(plctx);
std::get<2>(plctx).clear();
//bind serializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TSerializer>(
bitsery::ext::PolymorphicClassesList<Base, PolyPtrWithPolyPtrBase>{});
return res;
}
typename SerContext::TDeserializer& createDeserializer()
{
auto& res = sctx.createDeserializer(plctx);
std::get<2>(plctx).clear();
// bind deserializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TDeserializer>(
bitsery::ext::PolymorphicClassesList<Base, PolyPtrWithPolyPtrBase>{});
return res;
}
typename SerContext::TDeserializer& createDeserializer() {
auto& res = sctx.createDeserializer(plctx);
std::get<2>(plctx).clear();
//bind deserializer with classes
std::get<2>(plctx).registerBasesList<SerContext::TDeserializer>(
bitsery::ext::PolymorphicClassesList<Base, PolyPtrWithPolyPtrBase>{});
return res;
}
bool isPointerContextValid() { return std::get<0>(plctx).isValid(); }
bool isPointerContextValid() {
return std::get<0>(plctx).isValid();
}
virtual void TearDown() override {
EXPECT_TRUE(isPointerContextValid());
}
virtual void TearDown() override { EXPECT_TRUE(isPointerContextValid()); }
};
TEST_F(SerializeExtensionPointerWithAllocator, CanSetDefaultMemoryResourceInPointerLinkingContext) {
TEST_F(SerializeExtensionPointerWithAllocator,
CanSetDefaultMemoryResourceInPointerLinkingContext)
{
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
Base* baseData = new Derived1{2, 1};
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
Base* baseData = new Derived1{ 2, 1 };
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = nullptr;
createDeserializer().ext(baseRes, PointerOwner{});
auto dData = dynamic_cast<Derived1*>(baseData);
auto dRes = dynamic_cast<Derived1*>(baseRes);
auto dData = dynamic_cast<Derived1*>(baseData);
auto dRes = dynamic_cast<Derived1*>(baseRes);
EXPECT_THAT(dRes, ::testing::NotNull());
EXPECT_THAT(*dData, *dRes);
EXPECT_THAT(memRes.allocs.size(), Eq(1u));
EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.allocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes.deallocs.size(), Eq(0u));
delete dData;
delete dRes;
EXPECT_THAT(dRes, ::testing::NotNull());
EXPECT_THAT(*dData, *dRes);
EXPECT_THAT(memRes.allocs.size(), Eq(1u));
EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.allocs[0].typeId,
Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes.deallocs.size(), Eq(0u));
delete dData;
delete dRes;
}
TEST_F(SerializeExtensionPointerWithAllocator, CorrectlyDeallocatesPreviousInstance) {
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
TEST_F(SerializeExtensionPointerWithAllocator,
CorrectlyDeallocatesPreviousInstance)
{
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
Base* baseData = new Derived1{2, 1};
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = new Derived2;
createDeserializer().ext(baseRes, PointerOwner{});
Base* baseData = new Derived1{ 2, 1 };
createSerializer().ext(baseData, PointerOwner{});
Base* baseRes = new Derived2;
createDeserializer().ext(baseRes, PointerOwner{});
auto dData = dynamic_cast<Derived1*>(baseData);
auto dRes = dynamic_cast<Derived1*>(baseRes);
auto dData = dynamic_cast<Derived1*>(baseData);
auto dRes = dynamic_cast<Derived1*>(baseRes);
EXPECT_THAT(dRes, ::testing::NotNull());
EXPECT_THAT(*dData, *dRes);
EXPECT_THAT(memRes.allocs.size(), Eq(1u));
EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.allocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived2)));
EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived2)));
EXPECT_THAT(memRes.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get<Derived2>()));
EXPECT_THAT(dRes, ::testing::NotNull());
EXPECT_THAT(*dData, *dRes);
EXPECT_THAT(memRes.allocs.size(), Eq(1u));
EXPECT_THAT(memRes.allocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.allocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.allocs[0].typeId,
Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived2)));
EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived2)));
EXPECT_THAT(memRes.deallocs[0].typeId,
Eq(bitsery::ext::StandardRTTI::get<Derived2>()));
delete dData;
delete dRes;
delete dData;
delete dRes;
}
TEST_F(SerializeExtensionPointerWithAllocator, DefaultDeleterIsNotUsedForStdUniquePtr) {
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
TEST_F(SerializeExtensionPointerWithAllocator,
DefaultDeleterIsNotUsedForStdUniquePtr)
{
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
std::unique_ptr<Base> baseData{};
createSerializer().ext(baseData, StdSmartPtr{});
auto baseRes = std::unique_ptr<Base>(new Derived1{45, 64});
createDeserializer().ext(baseRes, StdSmartPtr{});
std::unique_ptr<Base> baseData{};
createSerializer().ext(baseData, StdSmartPtr{});
auto baseRes = std::unique_ptr<Base>(new Derived1{ 45, 64 });
createDeserializer().ext(baseRes, StdSmartPtr{});
EXPECT_THAT(memRes.allocs.size(), Eq(0u));
EXPECT_THAT(memRes.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes.allocs.size(), Eq(0u));
EXPECT_THAT(memRes.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].typeId,
Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
}
struct CustomBaseDeleter {
void operator()(Base* obj) {
delete obj;
}
struct CustomBaseDeleter
{
void operator()(Base* obj) { delete obj; }
};
TEST_F(SerializeExtensionPointerWithAllocator, CustomDeleterIsNotUsedForStdUniquePtr) {
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
TEST_F(SerializeExtensionPointerWithAllocator,
CustomDeleterIsNotUsedForStdUniquePtr)
{
MemResourceForTest memRes{};
std::get<0>(plctx).setMemResource(&memRes);
std::unique_ptr<Base, CustomBaseDeleter> baseData{};
createSerializer().ext(baseData, StdSmartPtr{});
auto baseRes = std::unique_ptr<Base, CustomBaseDeleter>(new Derived1{45, 64});
createDeserializer().ext(baseRes, StdSmartPtr{});
std::unique_ptr<Base, CustomBaseDeleter> baseData{};
createSerializer().ext(baseData, StdSmartPtr{});
auto baseRes =
std::unique_ptr<Base, CustomBaseDeleter>(new Derived1{ 45, 64 });
createDeserializer().ext(baseRes, StdSmartPtr{});
EXPECT_THAT(memRes.allocs.size(), Eq(0u));
EXPECT_THAT(memRes.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes.allocs.size(), Eq(0u));
EXPECT_THAT(memRes.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes.deallocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes.deallocs[0].typeId,
Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
}
TEST_F(SerializeExtensionPointerWithAllocator, CanSetMemResourcePerPointer)
{
MemResourceForTest memRes1{};
MemResourceForTest memRes2{};
std::get<0>(plctx).setMemResource(&memRes1);
TEST_F(SerializeExtensionPointerWithAllocator, CanSetMemResourcePerPointer) {
MemResourceForTest memRes1{};
MemResourceForTest memRes2{};
std::get<0>(plctx).setMemResource(&memRes1);
Base* baseData = new Derived1{ 2, 1 };
createSerializer().ext(
baseData, PointerOwner{ bitsery::ext::PointerType::Nullable, &memRes2 });
Base* baseRes = new Derived2;
createDeserializer().ext(
baseRes, PointerOwner{ bitsery::ext::PointerType::Nullable, &memRes2 });
Base* baseData = new Derived1{2, 1};
createSerializer().ext(baseData, PointerOwner{bitsery::ext::PointerType::Nullable, &memRes2});
Base* baseRes = new Derived2;
createDeserializer().ext(baseRes, PointerOwner{bitsery::ext::PointerType::Nullable, &memRes2});
auto dData = dynamic_cast<Derived1*>(baseData);
auto dRes = dynamic_cast<Derived1*>(baseRes);
auto dData = dynamic_cast<Derived1*>(baseData);
auto dRes = dynamic_cast<Derived1*>(baseRes);
EXPECT_THAT(dRes, ::testing::NotNull());
EXPECT_THAT(*dData, *dRes);
EXPECT_THAT(memRes1.allocs.size(), Eq(0u));
EXPECT_THAT(memRes1.deallocs.size(), Eq(0u));
EXPECT_THAT(memRes2.allocs.size(), Eq(1u));
EXPECT_THAT(memRes2.allocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes2.allocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes2.allocs[0].typeId,
Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes2.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes2.deallocs[0].bytes, Eq(sizeof(Derived2)));
EXPECT_THAT(memRes2.deallocs[0].alignment, Eq(alignof(Derived2)));
EXPECT_THAT(memRes2.deallocs[0].typeId,
Eq(bitsery::ext::StandardRTTI::get<Derived2>()));
EXPECT_THAT(dRes, ::testing::NotNull());
EXPECT_THAT(*dData, *dRes);
EXPECT_THAT(memRes1.allocs.size(), Eq(0u));
EXPECT_THAT(memRes1.deallocs.size(), Eq(0u));
EXPECT_THAT(memRes2.allocs.size(), Eq(1u));
EXPECT_THAT(memRes2.allocs[0].bytes, Eq(sizeof(Derived1)));
EXPECT_THAT(memRes2.allocs[0].alignment, Eq(alignof(Derived1)));
EXPECT_THAT(memRes2.allocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get<Derived1>()));
EXPECT_THAT(memRes2.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes2.deallocs[0].bytes, Eq(sizeof(Derived2)));
EXPECT_THAT(memRes2.deallocs[0].alignment, Eq(alignof(Derived2)));
EXPECT_THAT(memRes2.deallocs[0].typeId, Eq(bitsery::ext::StandardRTTI::get<Derived2>()));
delete dData;
delete dRes;
delete dData;
delete dRes;
}
TEST_F(SerializeExtensionPointerWithAllocator,
MemResourceSetPerPointerByDefaultDoNotPropagate)
{
MemResourceForTest memRes1{};
MemResourceForTest memRes2{};
std::get<0>(plctx).setMemResource(&memRes1);
TEST_F(SerializeExtensionPointerWithAllocator, MemResourceSetPerPointerByDefaultDoNotPropagate) {
MemResourceForTest memRes1{};
MemResourceForTest memRes2{};
std::get<0>(plctx).setMemResource(&memRes1);
auto data =
std::unique_ptr<PolyPtrWithPolyPtrBase>(new PolyPtrWithPolyPtrBase{});
data->ptr = std::unique_ptr<Base>(new Derived1{ 5, 6 });
createSerializer().ext(
data, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2 });
auto data = std::unique_ptr<PolyPtrWithPolyPtrBase>(new PolyPtrWithPolyPtrBase{});
data->ptr = std::unique_ptr<Base>(new Derived1{5, 6});
createSerializer().ext(data, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2});
auto res =
std::unique_ptr<PolyPtrWithPolyPtrBase>(new DerivedPolyPtrWithPolyPtr{});
res->ptr = std::unique_ptr<Base>(new Derived2{});
createDeserializer().ext(
res, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2 });
auto res = std::unique_ptr<PolyPtrWithPolyPtrBase>(new DerivedPolyPtrWithPolyPtr{});
res->ptr = std::unique_ptr<Base>(new Derived2{});
createDeserializer().ext(res, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2});
EXPECT_THAT(memRes1.allocs.size(), Eq(1u));
// Base* was destroyed by unique_ptr on PolyPtrWithPolyPtrBase destructor, hence == 0
EXPECT_THAT(memRes1.deallocs.size(), Eq(0u));
EXPECT_THAT(memRes2.allocs.size(), Eq(1u));
EXPECT_THAT(memRes2.deallocs.size(), Eq(1u));
EXPECT_THAT(memRes1.allocs.size(), Eq(1u));
// Base* was destroyed by unique_ptr on PolyPtrWithPolyPtrBase destructor,
// hence == 0
EXPECT_THAT(memRes1.deallocs.size(), Eq(0u));
EXPECT_THAT(memRes2.allocs.size(), Eq(1u));
EXPECT_THAT(memRes2.deallocs.size(), Eq(1u));
}
TEST_F(SerializeExtensionPointerWithAllocator, MemResourceSetPerPointerCanPropagate) {
MemResourceForTest memRes1{};
MemResourceForTest memRes2{};
std::get<0>(plctx).setMemResource(&memRes1);
TEST_F(SerializeExtensionPointerWithAllocator,
MemResourceSetPerPointerCanPropagate)
{
MemResourceForTest memRes1{};
MemResourceForTest memRes2{};
std::get<0>(plctx).setMemResource(&memRes1);
auto data = std::unique_ptr<PolyPtrWithPolyPtrBase>(new PolyPtrWithPolyPtrBase{});
data->ptr = std::unique_ptr<Base>(new Derived1{5, 6});
createSerializer().ext(data, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2, true});
auto data =
std::unique_ptr<PolyPtrWithPolyPtrBase>(new PolyPtrWithPolyPtrBase{});
data->ptr = std::unique_ptr<Base>(new Derived1{ 5, 6 });
createSerializer().ext(
data, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2, true });
auto res = std::unique_ptr<PolyPtrWithPolyPtrBase>(new DerivedPolyPtrWithPolyPtr{});
res->ptr = std::unique_ptr<Base>(new Derived2{});
createDeserializer().ext(res, StdSmartPtr{bitsery::ext::PointerType::Nullable, &memRes2, true});
EXPECT_THAT(memRes1.allocs.size(), Eq(0u));
EXPECT_THAT(memRes1.deallocs.size(), Eq(0u));
EXPECT_THAT(memRes2.allocs.size(), Eq(2u));
// deallocates are actually == 1, because when we destroy PolyPtrWithPolyPtrBase
// it also destroys Base because it is managed by unique_ptr.
// in order to do it correctly we should always use custom deleter for structures with nested pointers
EXPECT_THAT(memRes2.deallocs.size(), Eq(1u));
auto res =
std::unique_ptr<PolyPtrWithPolyPtrBase>(new DerivedPolyPtrWithPolyPtr{});
res->ptr = std::unique_ptr<Base>(new Derived2{});
createDeserializer().ext(
res, StdSmartPtr{ bitsery::ext::PointerType::Nullable, &memRes2, true });
EXPECT_THAT(memRes1.allocs.size(), Eq(0u));
EXPECT_THAT(memRes1.deallocs.size(), Eq(0u));
EXPECT_THAT(memRes2.allocs.size(), Eq(2u));
// deallocates are actually == 1, because when we destroy
// PolyPtrWithPolyPtrBase it also destroys Base because it is managed by
// unique_ptr. in order to do it correctly we should always use custom deleter
// for structures with nested pointers
EXPECT_THAT(memRes2.deallocs.size(), Eq(1u));
}

View File

@@ -1,124 +1,132 @@
//MIT License
// MIT License
//
//Copyright (c) 2020 Mindaugas Vinkelis
// Copyright (c) 2020 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/std_bitset.h>
#include <bitsery/ext/value_range.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using StdBitset = bitsery::ext::StdBitset;
using ValueRange = bitsery::ext::ValueRange<int>;
using testing::Eq;
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong) {
SerializationContext ctx;
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong)
{
SerializationContext ctx;
std::bitset<31> data;
data[2] = true;
data[8] = true;
data[15] = true;
data[25] = true;
data[30] = true;
std::bitset<31> res;
std::bitset<31> data;
data[2] = true;
data[8] = true;
data[15] = true;
data[25] = true;
data[30] = true;
std::bitset<31> res;
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
}
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong2) {
SerializationContext ctx;
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLong2)
{
SerializationContext ctx;
std::bitset<9> data;
data.set();
std::bitset<9> res;
std::bitset<9> data;
data.set();
std::bitset<9> res;
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
}
TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLong)
{
SerializationContext ctx;
TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLong) {
SerializationContext ctx;
std::bitset<200> data;
data[1] = true;
data[31] = true;
data[63] = true;
data[100] = true;
data[191] = true;
std::bitset<200> res;
std::bitset<200> data;
data[1] = true;
data[31] = true;
data[63] = true;
data[100] = true;
data[191] = true;
std::bitset<200> res;
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
ctx.createSerializer().ext(data, StdBitset{});
ctx.createDeserializer().ext(res, StdBitset{});
EXPECT_THAT(res, Eq(data));
}
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLongBitPackingEnabled) {
SerializationContext ctx;
TEST(SerializeExtensionStdBitset, BitsetSmallerThanULongLongBitPackingEnabled)
{
SerializationContext ctx;
std::bitset<12> data;
int other_data = 1001;
data[2] = true;
data[9] = true;
std::bitset<12> res{};
int other_res{};
std::bitset<12> data;
int other_data = 1001;
data[2] = true;
data[9] = true;
std::bitset<12> res{};
int other_res{};
ctx.createSerializer().enableBitPacking([&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) {
sbp.ext(data, StdBitset{});
sbp.ext(other_data, ValueRange{1000,1015});
ctx.createSerializer().enableBitPacking(
[&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) {
sbp.ext(data, StdBitset{});
sbp.ext(other_data, ValueRange{ 1000, 1015 });
});
ctx.createDeserializer().enableBitPacking([&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) {
dbp.ext(res, StdBitset{});
dbp.ext(other_res, ValueRange{1000,1015});
ctx.createDeserializer().enableBitPacking(
[&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) {
dbp.ext(res, StdBitset{});
dbp.ext(other_res, ValueRange{ 1000, 1015 });
});
EXPECT_THAT(res, Eq(data));
EXPECT_THAT(other_res, Eq(other_data));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
EXPECT_THAT(res, Eq(data));
EXPECT_THAT(other_res, Eq(other_data));
EXPECT_THAT(ctx.getBufferSize(), Eq(2));
}
TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLongBitPackingEnabled) {
SerializationContext ctx;
TEST(SerializeExtensionStdBitset, BitsetLargerThanULongLongBitPackingEnabled)
{
SerializationContext ctx;
std::bitset<204> data;
int other_data = 1001;
data[1] = true;
data[100] = true;
data[191] = true;
std::bitset<204> res{};
int other_res{};
std::bitset<204> data;
int other_data = 1001;
data[1] = true;
data[100] = true;
data[191] = true;
std::bitset<204> res{};
int other_res{};
ctx.createSerializer().enableBitPacking([&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) {
sbp.ext(data, StdBitset{});
sbp.ext(other_data, ValueRange{1000,1015});
ctx.createSerializer().enableBitPacking(
[&data, &other_data](SerializationContext::TSerializerBPEnabled& sbp) {
sbp.ext(data, StdBitset{});
sbp.ext(other_data, ValueRange{ 1000, 1015 });
});
ctx.createDeserializer().enableBitPacking([&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) {
dbp.ext(res, StdBitset{});
dbp.ext(other_res, ValueRange{1000,1015});
ctx.createDeserializer().enableBitPacking(
[&res, &other_res](SerializationContext::TDeserializerBPEnabled& dbp) {
dbp.ext(res, StdBitset{});
dbp.ext(other_res, ValueRange{ 1000, 1015 });
});
EXPECT_THAT(res, Eq(data));
EXPECT_THAT(other_res, Eq(other_data));
EXPECT_THAT(ctx.getBufferSize(), Eq(26));
EXPECT_THAT(res, Eq(data));
EXPECT_THAT(other_res, Eq(other_data));
EXPECT_THAT(ctx.getBufferSize(), Eq(26));
}

View File

@@ -1,81 +1,85 @@
//MIT License
// MIT License
//
//Copyright (c) 2019 Mindaugas Vinkelis
// Copyright (c) 2019 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/std_chrono.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using StdDuration = bitsery::ext::StdDuration;
using StdTimePoint = bitsery::ext::StdTimePoint;
using testing::Eq;
TEST(SerializeExtensionStdChrono, IntegralDuration) {
SerializationContext ctx1;
using Hours = std::chrono::duration<int32_t, std::ratio<60>>;
TEST(SerializeExtensionStdChrono, IntegralDuration)
{
SerializationContext ctx1;
using Hours = std::chrono::duration<int32_t, std::ratio<60>>;
Hours data{43};
Hours res{};
Hours data{ 43 };
Hours res{};
ctx1.createSerializer().ext4b(data, StdDuration{});
ctx1.createDeserializer().ext4b(res, StdDuration{});
EXPECT_THAT(res, Eq(data));
ctx1.createSerializer().ext4b(data, StdDuration{});
ctx1.createDeserializer().ext4b(res, StdDuration{});
EXPECT_THAT(res, Eq(data));
}
TEST(SerializeExtensionStdChrono, IntegralTimePoint) {
SerializationContext ctx1;
using Duration = std::chrono::duration<int64_t, std::milli>;
using TP = std::chrono::time_point<std::chrono::system_clock, Duration>;
TEST(SerializeExtensionStdChrono, IntegralTimePoint)
{
SerializationContext ctx1;
using Duration = std::chrono::duration<int64_t, std::milli>;
using TP = std::chrono::time_point<std::chrono::system_clock, Duration>;
TP data{Duration{243}};
TP res{};
TP data{ Duration{ 243 } };
TP res{};
ctx1.createSerializer().ext8b(data, StdTimePoint{});
ctx1.createDeserializer().ext8b(res, StdTimePoint{});
EXPECT_THAT(res, Eq(data));
ctx1.createSerializer().ext8b(data, StdTimePoint{});
ctx1.createDeserializer().ext8b(res, StdTimePoint{});
EXPECT_THAT(res, Eq(data));
}
TEST(SerializeExtensionStdChrono, FloatDuration) {
SerializationContext ctx1;
using Hours = std::chrono::duration<float, std::ratio<60>>;
TEST(SerializeExtensionStdChrono, FloatDuration)
{
SerializationContext ctx1;
using Hours = std::chrono::duration<float, std::ratio<60>>;
Hours data{43.5f};
Hours res{};
Hours data{ 43.5f };
Hours res{};
ctx1.createSerializer().ext4b(data, StdDuration{});
ctx1.createDeserializer().ext4b(res, StdDuration{});
EXPECT_THAT(res, Eq(data));
ctx1.createSerializer().ext4b(data, StdDuration{});
ctx1.createDeserializer().ext4b(res, StdDuration{});
EXPECT_THAT(res, Eq(data));
}
TEST(SerializeExtensionStdChrono, FloatTimePoint) {
SerializationContext ctx1;
using Duration = std::chrono::duration<double, std::milli>;
using TP = std::chrono::time_point<std::chrono::system_clock, Duration>;
TEST(SerializeExtensionStdChrono, FloatTimePoint)
{
SerializationContext ctx1;
using Duration = std::chrono::duration<double, std::milli>;
using TP = std::chrono::time_point<std::chrono::system_clock, Duration>;
TP data{Duration{243457.4}};
TP res{};
TP data{ Duration{ 243457.4 } };
TP res{};
ctx1.createSerializer().ext8b(data, StdTimePoint{});
ctx1.createDeserializer().ext8b(res, StdTimePoint{});
EXPECT_THAT(res, Eq(data));
ctx1.createSerializer().ext8b(data, StdTimePoint{});
ctx1.createDeserializer().ext8b(res, StdTimePoint{});
EXPECT_THAT(res, Eq(data));
}

View File

@@ -1,139 +1,151 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/std_map.h>
#include <bitsery/ext/entropy.h>
#include <unordered_map>
#include <bitsery/ext/std_map.h>
#include <bitsery/traits/string.h>
#include <unordered_map>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using StdMap = bitsery::ext::StdMap;
using testing::Eq;
template<typename Container>
Container createData() {
return {};
Container
createData()
{
return {};
}
template<>
std::unordered_map<std::string, MyStruct1> createData<std::unordered_map<std::string, MyStruct1>>() {
return {
std::make_pair("some key", MyStruct1{874,456}),
std::make_pair("other key", MyStruct1{-34,8645}),
std::make_pair("secret key", MyStruct1{-4878,3468975})
};
std::unordered_map<std::string, MyStruct1>
createData<std::unordered_map<std::string, MyStruct1>>()
{
return { std::make_pair("some key", MyStruct1{ 874, 456 }),
std::make_pair("other key", MyStruct1{ -34, 8645 }),
std::make_pair("secret key", MyStruct1{ -4878, 3468975 }) };
}
template<>
std::unordered_multimap<int32_t, float> createData<std::unordered_multimap<int32_t, float>>() {
return {
std::pair<int32_t , float>(545, 45.485f),
std::pair<int32_t , float>(6748, -7891.5f),
std::pair<int32_t , float>(845, -457.0f)
};
std::unordered_multimap<int32_t, float>
createData<std::unordered_multimap<int32_t, float>>()
{
return { std::pair<int32_t, float>(545, 45.485f),
std::pair<int32_t, float>(6748, -7891.5f),
std::pair<int32_t, float>(845, -457.0f) };
}
template<>
std::map<MyEnumClass, MyStruct1> createData<std::map<MyEnumClass, MyStruct1>>() {
return {
std::make_pair(MyEnumClass::E3, MyStruct1{874,456}),
std::make_pair(MyEnumClass::E6, MyStruct1{-34,8645}),
std::make_pair(MyEnumClass::E2, MyStruct1{-4878,3468975})
};
std::map<MyEnumClass, MyStruct1>
createData<std::map<MyEnumClass, MyStruct1>>()
{
return { std::make_pair(MyEnumClass::E3, MyStruct1{ 874, 456 }),
std::make_pair(MyEnumClass::E6, MyStruct1{ -34, 8645 }),
std::make_pair(MyEnumClass::E2, MyStruct1{ -4878, 3468975 }) };
}
template<>
std::multimap<int32_t ,int64_t> createData<std::multimap<int32_t ,int64_t>>() {
return {//these are optimized with range and entropy
std::pair<int32_t, int64_t>(-45, -984196845ll),
std::pair<int32_t, int64_t>(54, 1ll),
std::pair<int32_t, int64_t>(98, 3ll)
};
std::multimap<int32_t, int64_t>
createData<std::multimap<int32_t, int64_t>>()
{
return { // these are optimized with range and entropy
std::pair<int32_t, int64_t>(-45, -984196845ll),
std::pair<int32_t, int64_t>(54, 1ll),
std::pair<int32_t, int64_t>(98, 3ll)
};
}
template<typename T>
class SerializeExtensionStdMap : public testing::Test {
class SerializeExtensionStdMap : public testing::Test
{
public:
using TContainer = T;
using TContainer = T;
const TContainer src = createData<TContainer>();
TContainer res{};
const TContainer src = createData<TContainer>();
TContainer res{};
};
using SerializeExtensionStdMapTypes = ::testing::Types<
std::unordered_map<std::string, MyStruct1>,
std::unordered_multimap<int32_t, float>,
std::map<MyEnumClass , MyStruct1>,
std::multimap<int32_t ,int64_t>
>;
using SerializeExtensionStdMapTypes =
::testing::Types<std::unordered_map<std::string, MyStruct1>,
std::unordered_multimap<int32_t, float>,
std::map<MyEnumClass, MyStruct1>,
std::multimap<int32_t, int64_t>>;
TYPED_TEST_SUITE(SerializeExtensionStdMap, SerializeExtensionStdMapTypes,);
TYPED_TEST_SUITE(SerializeExtensionStdMap, SerializeExtensionStdMapTypes, );
namespace bitsery {
template <typename S>
void serialize(S& s, std::unordered_map<std::string, MyStruct1>& o) {
s.ext(o, StdMap{10}, [](S& s, std::string& key, MyStruct1& value) {
s.text1b(key, 100);
s.object(value);
});
}
template<typename S>
void
serialize(S& s, std::unordered_map<std::string, MyStruct1>& o)
{
s.ext(o, StdMap{ 10 }, [](S& s, std::string& key, MyStruct1& value) {
s.text1b(key, 100);
s.object(value);
});
}
template <typename S>
void serialize(S& s, std::unordered_multimap<int32_t, float>& o) {
s.ext(o, StdMap{10}, [](S& s, int32_t& key, float& value) {
s.value4b(key);
s.value4b(value);
});
}
template<typename S>
void
serialize(S& s, std::unordered_multimap<int32_t, float>& o)
{
s.ext(o, StdMap{ 10 }, [](S& s, int32_t& key, float& value) {
s.value4b(key);
s.value4b(value);
});
}
template <typename S>
void serialize(S& s, std::map<MyEnumClass , MyStruct1>& o) {
s.ext(o, StdMap{10}, [](S& s, MyEnumClass& key, MyStruct1& value) {
s.value4b(key);
s.object(value);
});
}
template <typename S>
void serialize(S& s, std::multimap<int32_t ,int64_t>& o) {
s.ext(o, StdMap{10}, [](S& s, int32_t& key, int64_t& value) {
s.enableBitPacking([&key, &value](typename S::BPEnabledType& sbp) {
int64_t values[3]{1ll, 2ll, 3ll};
sbp.ext(key, bitsery::ext::ValueRange<int32_t>{-100,100});
sbp.ext8b(value, bitsery::ext::Entropy<int64_t[3]>{values});
});
});
}
template<typename S>
void
serialize(S& s, std::map<MyEnumClass, MyStruct1>& o)
{
s.ext(o, StdMap{ 10 }, [](S& s, MyEnumClass& key, MyStruct1& value) {
s.value4b(key);
s.object(value);
});
}
template<typename S>
void
serialize(S& s, std::multimap<int32_t, int64_t>& o)
{
s.ext(o, StdMap{ 10 }, [](S& s, int32_t& key, int64_t& value) {
s.enableBitPacking([&key, &value](typename S::BPEnabledType& sbp) {
int64_t values[3]{ 1ll, 2ll, 3ll };
sbp.ext(key, bitsery::ext::ValueRange<int32_t>{ -100, 100 });
sbp.ext8b(value, bitsery::ext::Entropy<int64_t[3]>{ values });
});
});
}
}
TYPED_TEST(SerializeExtensionStdMap, SerializeAndDeserializeEquals) {
SerializationContext ctx1;
ctx1.createSerializer().object(this->src);
ctx1.createDeserializer().object(this->res);
EXPECT_THAT(this->res, Eq(this->src));
TYPED_TEST(SerializeExtensionStdMap, SerializeAndDeserializeEquals)
{
SerializationContext ctx1;
ctx1.createSerializer().object(this->src);
ctx1.createDeserializer().object(this->res);
EXPECT_THAT(this->res, Eq(this->src));
}

View File

@@ -1,28 +1,27 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
#if __cplusplus > 201402L
@@ -36,92 +35,96 @@ using BPDes = SerializationContext::TDeserializer::BPEnabledType;
using testing::Eq;
template <typename T>
void test(SerializationContext& ctx, const T& v, T& r) {
ctx.createSerializer().ext4b(v, StdOptional{});
ctx.createDeserializer().ext4b(r, StdOptional{});
template<typename T>
void
test(SerializationContext& ctx, const T& v, T& r)
{
ctx.createSerializer().ext4b(v, StdOptional{});
ctx.createDeserializer().ext4b(r, StdOptional{});
}
TEST(SerializeExtensionStdOptional, EmptyOptional) {
std::optional<int32_t> t1{};
std::optional<int32_t> r1{};
TEST(SerializeExtensionStdOptional, EmptyOptional)
{
std::optional<int32_t> t1{};
std::optional<int32_t> r1{};
SerializationContext ctx1;
test(ctx1,t1, r1);
EXPECT_THAT(ctx1.getBufferSize(), Eq(1));
EXPECT_THAT(t1, Eq(r1));
SerializationContext ctx1;
test(ctx1, t1, r1);
EXPECT_THAT(ctx1.getBufferSize(), Eq(1));
EXPECT_THAT(t1, Eq(r1));
r1 = 3;
SerializationContext ctx2;
test(ctx2,t1, r1);
EXPECT_THAT(ctx2.getBufferSize(), Eq(1));
EXPECT_THAT(t1, Eq(r1));
r1 = 3;
SerializationContext ctx2;
test(ctx2, t1, r1);
EXPECT_THAT(ctx2.getBufferSize(), Eq(1));
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdOptional, OptionalHasValue) {
std::optional<int32_t> t1{43};
std::optional<int32_t> r1{52};
TEST(SerializeExtensionStdOptional, OptionalHasValue)
{
std::optional<int32_t> t1{ 43 };
std::optional<int32_t> r1{ 52 };
SerializationContext ctx1;
test(ctx1,t1, r1);
EXPECT_THAT(ctx1.getBufferSize(), Eq(1 + sizeof(int)));
EXPECT_THAT(t1.value(), Eq(r1.value()));
r1 = std::optional<int>{};
SerializationContext ctx2;
test(ctx2,t1, r1);
EXPECT_THAT(ctx2.getBufferSize(), Eq(1 + sizeof(int)));
EXPECT_THAT(t1.value(), Eq(r1.value()));
SerializationContext ctx1;
test(ctx1, t1, r1);
EXPECT_THAT(ctx1.getBufferSize(), Eq(1 + sizeof(int)));
EXPECT_THAT(t1.value(), Eq(r1.value()));
r1 = std::optional<int>{};
SerializationContext ctx2;
test(ctx2, t1, r1);
EXPECT_THAT(ctx2.getBufferSize(), Eq(1 + sizeof(int)));
EXPECT_THAT(t1.value(), Eq(r1.value()));
}
TEST(SerializeExtensionStdOptional, AlignAfterStateWriteRead) {
std::optional<int32_t> t1{43};
std::optional<int32_t> r1{52};
auto range = bitsery::ext::ValueRange<int>{40,60};
TEST(SerializeExtensionStdOptional, AlignAfterStateWriteRead)
{
std::optional<int32_t> t1{ 43 };
std::optional<int32_t> r1{ 52 };
auto range = bitsery::ext::ValueRange<int>{ 40, 60 };
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) {
ser.ext(t1, StdOptional(true), [&range](BPSer& ser, int32_t& v) {
ser.ext(v, range);
});
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) {
ser.ext(t1, StdOptional(true), [&range](BPSer& ser, int32_t& v) {
ser.ext(v, range);
});
ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) {
des.ext(r1, StdOptional(true), [&range](BPDes& des, int32_t& v) {
des.ext(v, range);
});
});
ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) {
des.ext(r1, StdOptional(true), [&range](BPDes& des, int32_t& v) {
des.ext(v, range);
});
});
EXPECT_THAT(ctx.getBufferSize(), Eq(2));//1byte for index + 1byte for value
EXPECT_THAT(t1.value(), Eq(r1.value()));
EXPECT_THAT(ctx.getBufferSize(), Eq(2)); // 1byte for index + 1byte for value
EXPECT_THAT(t1.value(), Eq(r1.value()));
}
TEST(SerializeExtensionStdOptional, NoAlignAfterStateWriteRead) {
std::optional<int32_t> t1{43};
std::optional<int32_t> r1{52};
auto range = bitsery::ext::ValueRange<int>{40,60};
TEST(SerializeExtensionStdOptional, NoAlignAfterStateWriteRead)
{
std::optional<int32_t> t1{ 43 };
std::optional<int32_t> r1{ 52 };
auto range = bitsery::ext::ValueRange<int>{ 40, 60 };
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) {
ser.ext(t1, StdOptional(false), [&range](BPSer& ser, int32_t& v) {
ser.ext(v, range);
});
SerializationContext ctx;
ctx.createSerializer().enableBitPacking([&t1, &range](BPSer& ser) {
ser.ext(t1, StdOptional(false), [&range](BPSer& ser, int32_t& v) {
ser.ext(v, range);
});
ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) {
des.ext(r1, StdOptional(false), [&range](BPDes& des, int32_t& v) {
des.ext(v, range);
});
});
ctx.createDeserializer().enableBitPacking([&r1, &range](BPDes& des) {
des.ext(r1, StdOptional(false), [&range](BPDes& des, int32_t& v) {
des.ext(v, range);
});
});
EXPECT_THAT(range.getRequiredBits() + 1, ::testing::Lt(8));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(t1.value(), Eq(r1.value()));
EXPECT_THAT(range.getRequiredBits() + 1, ::testing::Lt(8));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(t1.value(), Eq(r1.value()));
}
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::optional tests")
#pragma message( \
"C++17 and /Zc:__cplusplus option is required to enable std::optional tests")
#else
#pragma message("C++17 is required to enable std::optional tests")
#endif

View File

@@ -1,100 +1,107 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/std_queue.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using StdQueue = bitsery::ext::StdQueue;
using testing::Eq;
//inherit from queue so we could take underlying container, because priority queue doesn't have equal operator defined
template <typename T, typename C>
// inherit from queue so we could take underlying container, because priority
// queue doesn't have equal operator defined
template<typename T, typename C>
struct PriorityQueueCnt : public std::priority_queue<T, C>
{
static const C& getContainer(const std::priority_queue<T, C>& s )
{
//get address of underlying container
return s.*(&PriorityQueueCnt::c);
}
static C& getContainer(std::priority_queue<T, C>& s )
{
//get address of underlying container
return s.*(&PriorityQueueCnt::c);
}
static const C& getContainer(const std::priority_queue<T, C>& s)
{
// get address of underlying container
return s.*(&PriorityQueueCnt::c);
}
static C& getContainer(std::priority_queue<T, C>& s)
{
// get address of underlying container
return s.*(&PriorityQueueCnt::c);
}
};
template <typename T>
void test(SerializationContext& ctx, const T& v, T& r) {
ctx.createSerializer().ext4b(v, StdQueue{10});
ctx.createDeserializer().ext4b(r, StdQueue{10});
template<typename T>
void
test(SerializationContext& ctx, const T& v, T& r)
{
ctx.createSerializer().ext4b(v, StdQueue{ 10 });
ctx.createDeserializer().ext4b(r, StdQueue{ 10 });
}
TEST(SerializeExtensionStdQueue, QueueDefaultContainer) {
std::queue<int32_t> t1{};
t1.push(3);
t1.push(-4854);
std::queue<int32_t> r1{};
TEST(SerializeExtensionStdQueue, QueueDefaultContainer)
{
std::queue<int32_t> t1{};
t1.push(3);
t1.push(-4854);
std::queue<int32_t> r1{};
SerializationContext ctx1{};
test(ctx1,t1, r1);
EXPECT_THAT(t1, Eq(r1));
SerializationContext ctx1{};
test(ctx1, t1, r1);
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdQueue, QueueVectorContainer) {
std::queue<int32_t, std::vector<int32_t>> t1{};
t1.push(3);
t1.push(-4854);
std::queue<int32_t, std::vector<int32_t>> r1{};
TEST(SerializeExtensionStdQueue, QueueVectorContainer)
{
std::queue<int32_t, std::vector<int32_t>> t1{};
t1.push(3);
t1.push(-4854);
std::queue<int32_t, std::vector<int32_t>> r1{};
SerializationContext ctx1{};
test(ctx1,t1, r1);
EXPECT_THAT(t1, Eq(r1));
SerializationContext ctx1{};
test(ctx1, t1, r1);
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdQueue, PriorityQueueDefaultContainer) {
std::priority_queue<int32_t> t1{};
t1.push(3);
t1.push(-4854);
std::priority_queue<int32_t> r1{};
TEST(SerializeExtensionStdQueue, PriorityQueueDefaultContainer)
{
std::priority_queue<int32_t> t1{};
t1.push(3);
t1.push(-4854);
std::priority_queue<int32_t> r1{};
SerializationContext ctx1{};
test(ctx1,t1, r1);
auto & ct1 = PriorityQueueCnt<int32_t, std::vector<int32_t>>::getContainer(t1);
auto & cr1 = PriorityQueueCnt<int32_t, std::vector<int32_t>>::getContainer(r1);
EXPECT_THAT(ct1, Eq(cr1));
SerializationContext ctx1{};
test(ctx1, t1, r1);
auto& ct1 = PriorityQueueCnt<int32_t, std::vector<int32_t>>::getContainer(t1);
auto& cr1 = PriorityQueueCnt<int32_t, std::vector<int32_t>>::getContainer(r1);
EXPECT_THAT(ct1, Eq(cr1));
}
TEST(SerializeExtensionStdQueue, PriorityQueueDequeContainer) {
std::priority_queue<int32_t, std::deque<int32_t>> t1{};
t1.push(678);
t1.push(-44);
std::priority_queue<int32_t, std::deque<int32_t>> r1{};
TEST(SerializeExtensionStdQueue, PriorityQueueDequeContainer)
{
std::priority_queue<int32_t, std::deque<int32_t>> t1{};
t1.push(678);
t1.push(-44);
std::priority_queue<int32_t, std::deque<int32_t>> r1{};
SerializationContext ctx1{};
test(ctx1,t1, r1);
auto & ct1 = PriorityQueueCnt<int32_t, std::deque<int32_t>>::getContainer(t1);
auto & cr1 = PriorityQueueCnt<int32_t, std::deque<int32_t>>::getContainer(r1);
EXPECT_THAT(ct1, Eq(cr1));
SerializationContext ctx1{};
test(ctx1, t1, r1);
auto& ct1 = PriorityQueueCnt<int32_t, std::deque<int32_t>>::getContainer(t1);
auto& cr1 = PriorityQueueCnt<int32_t, std::deque<int32_t>>::getContainer(r1);
EXPECT_THAT(ct1, Eq(cr1));
}

View File

@@ -1,78 +1,82 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/ext/std_set.h>
#include <set>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using StdSet = bitsery::ext::StdSet;
using testing::Eq;
template<typename T>
class SerializeExtensionStdSet : public testing::Test {
class SerializeExtensionStdSet : public testing::Test
{
public:
using TContainer = T;
const TContainer src = {4, 8, 48, 4, 9845, 64, 8};
TContainer res{78,74,154,8};
using TContainer = T;
const TContainer src = { 4, 8, 48, 4, 9845, 64, 8 };
TContainer res{ 78, 74, 154, 8 };
};
using SerializeExtensionStdSetTypes = ::testing::Types<
std::unordered_set<int32_t>,
std::unordered_multiset<int32_t>,
std::set<int32_t>,
std::multiset<int32_t>>;
using SerializeExtensionStdSetTypes =
::testing::Types<std::unordered_set<int32_t>,
std::unordered_multiset<int32_t>,
std::set<int32_t>,
std::multiset<int32_t>>;
TYPED_TEST_SUITE(SerializeExtensionStdSet, SerializeExtensionStdSetTypes,);
TYPED_TEST_SUITE(SerializeExtensionStdSet, SerializeExtensionStdSetTypes, );
TYPED_TEST(SerializeExtensionStdSet, ValuesSyntaxDifferentSetTypes) {
SerializationContext ctx1;
ctx1.createSerializer().ext4b(this->src, StdSet{10});
ctx1.createDeserializer().ext4b(this->res, StdSet{10});
EXPECT_THAT(this->res, Eq(this->src));
TYPED_TEST(SerializeExtensionStdSet, ValuesSyntaxDifferentSetTypes)
{
SerializationContext ctx1;
ctx1.createSerializer().ext4b(this->src, StdSet{ 10 });
ctx1.createDeserializer().ext4b(this->res, StdSet{ 10 });
EXPECT_THAT(this->res, Eq(this->src));
}
TEST(SerializeExtensionStdSet, ObjectSyntax) {
SerializationContext ctx1;
std::set<MyStruct1> t1{MyStruct1{874 ,456}, MyStruct1{-874, -456}, MyStruct1{4894,0}};
std::set<MyStruct1> r1{};
ctx1.createSerializer().ext(t1, StdSet{10});
ctx1.createDeserializer().ext(r1, StdSet{10});
EXPECT_THAT(r1, Eq(t1));
TEST(SerializeExtensionStdSet, ObjectSyntax)
{
SerializationContext ctx1;
std::set<MyStruct1> t1{ MyStruct1{ 874, 456 },
MyStruct1{ -874, -456 },
MyStruct1{ 4894, 0 } };
std::set<MyStruct1> r1{};
ctx1.createSerializer().ext(t1, StdSet{ 10 });
ctx1.createDeserializer().ext(r1, StdSet{ 10 });
EXPECT_THAT(r1, Eq(t1));
}
TEST(SerializeExtensionStdSet, FunctionSyntax) {
SerializationContext ctx1;
std::unordered_multiset<int32_t> t1{54,-484,841,79};
std::unordered_multiset<int32_t> r1{74,878,15,16,-7,5,-4,8,7};
auto& ser = ctx1.createSerializer();
ser.ext(t1, StdSet{10}, [](decltype(ser)& ser, int32_t& v) {
ser.value4b(v);
});
auto& des = ctx1.createDeserializer();
des.ext(r1, StdSet{10}, [](decltype(des)& des, int32_t& v) {
des.value4b(v);
});
EXPECT_THAT(r1, Eq(t1));
TEST(SerializeExtensionStdSet, FunctionSyntax)
{
SerializationContext ctx1;
std::unordered_multiset<int32_t> t1{ 54, -484, 841, 79 };
std::unordered_multiset<int32_t> r1{ 74, 878, 15, 16, -7, 5, -4, 8, 7 };
auto& ser = ctx1.createSerializer();
ser.ext(
t1, StdSet{ 10 }, [](decltype(ser)& ser, int32_t& v) { ser.value4b(v); });
auto& des = ctx1.createDeserializer();
des.ext(
r1, StdSet{ 10 }, [](decltype(des)& des, int32_t& v) { des.value4b(v); });
EXPECT_THAT(r1, Eq(t1));
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +1,61 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/ext/std_stack.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using StdStack = bitsery::ext::StdStack;
using testing::Eq;
template <typename T>
void test(SerializationContext& ctx, const T& v, T& r) {
ctx.createSerializer().ext4b(v, StdStack{10});
ctx.createDeserializer().ext4b(r, StdStack{10});
template<typename T>
void
test(SerializationContext& ctx, const T& v, T& r)
{
ctx.createSerializer().ext4b(v, StdStack{ 10 });
ctx.createDeserializer().ext4b(r, StdStack{ 10 });
}
TEST(SerializeExtensionStdStack, DefaultContainer) {
std::stack<int32_t> t1{};
t1.push(3);
t1.push(-4854);
std::stack<int32_t> r1{};
TEST(SerializeExtensionStdStack, DefaultContainer)
{
std::stack<int32_t> t1{};
t1.push(3);
t1.push(-4854);
std::stack<int32_t> r1{};
SerializationContext ctx1;
test(ctx1,t1, r1);
EXPECT_THAT(t1, Eq(r1));
SerializationContext ctx1;
test(ctx1, t1, r1);
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdStack, VectorContainer) {
std::stack<int32_t, std::vector<int32_t>> t1{};
t1.push(3);
t1.push(-4854);
std::stack<int32_t, std::vector<int32_t>> r1{};
TEST(SerializeExtensionStdStack, VectorContainer)
{
std::stack<int32_t, std::vector<int32_t>> t1{};
t1.push(3);
t1.push(-4854);
std::stack<int32_t, std::vector<int32_t>> r1{};
SerializationContext ctx1;
test(ctx1,t1, r1);
EXPECT_THAT(t1, Eq(r1));
SerializationContext ctx1;
test(ctx1, t1, r1);
EXPECT_THAT(t1, Eq(r1));
}

View File

@@ -1,27 +1,27 @@
//MIT License
// MIT License
//
//Copyright (c) 2019 Mindaugas Vinkelis
// Copyright (c) 2019 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
@@ -32,94 +32,109 @@ using testing::Eq;
template<typename T, size_t N>
using OverloadValue = bitsery::ext::OverloadValue<T, N>;
TEST(SerializeExtensionStdTuple, UseDefaultSerializeFunction) {
std::tuple<MyStruct1, MyStruct2> t1{MyStruct1{-789, 45}, MyStruct2{MyStruct2::MyEnum::V3, MyStruct1{}}};
std::tuple<MyStruct1, MyStruct2> r1{};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{});
EXPECT_THAT(t1, Eq(r1));
TEST(SerializeExtensionStdTuple, UseDefaultSerializeFunction)
{
std::tuple<MyStruct1, MyStruct2> t1{
MyStruct1{ -789, 45 }, MyStruct2{ MyStruct2::MyEnum::V3, MyStruct1{} }
};
std::tuple<MyStruct1, MyStruct2> r1{};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{});
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdTuple, ValueTypesCanBeSerializedWithLambdaAndOrCallableObject) {
std::tuple<float, int32_t> t1{123.456f, -898754656};
std::tuple<float, int32_t> r1{};
SerializationContext ctx;
auto exec = [](auto& s, auto& o) {
s.ext(o, bitsery::ext::StdTuple{
[](auto& s1, float& o1) {
s1.value4b(o1);
},
OverloadValue<int32_t, 4>{}
});
};
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(t1, Eq(r1));
TEST(SerializeExtensionStdTuple,
ValueTypesCanBeSerializedWithLambdaAndOrCallableObject)
{
std::tuple<float, int32_t> t1{ 123.456f, -898754656 };
std::tuple<float, int32_t> r1{};
SerializationContext ctx;
auto exec = [](auto& s, auto& o) {
s.ext(o,
bitsery::ext::StdTuple{ [](auto& s1, float& o1) { s1.value4b(o1); },
OverloadValue<int32_t, 4>{} });
};
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdTuple, CanOverloadDefaultSerializeFunction) {
std::tuple<MyStruct1, MyStruct2> t1{MyStruct1{-789, 45}, MyStruct2{MyStruct2::MyEnum::V3, MyStruct1{}}};
std::tuple<MyStruct1, MyStruct2> r1{};
SerializationContext ctx;
auto exec = [](auto& s, auto& o) {
s.ext(o, bitsery::ext::StdTuple{
TEST(SerializeExtensionStdTuple, CanOverloadDefaultSerializeFunction)
{
std::tuple<MyStruct1, MyStruct2> t1{
MyStruct1{ -789, 45 }, MyStruct2{ MyStruct2::MyEnum::V3, MyStruct1{} }
};
std::tuple<MyStruct1, MyStruct2> r1{};
SerializationContext ctx;
auto exec = [](auto& s, auto& o) {
s.ext(o,
bitsery::ext::StdTuple{
[](auto& s1, MyStruct1& o1) {
s1.value4b(o1.i1);
//do not serialize other element, it should be 0 (default)
s1.value4b(o1.i1);
// do not serialize other element, it should be 0 (default)
},
});
};
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(std::get<1>(t1), Eq(std::get<1>(r1)));
EXPECT_THAT(std::get<0>(t1).i1, Eq(std::get<0>(r1).i1));
EXPECT_THAT(std::get<0>(t1).i2, ::testing::Ne(std::get<0>(r1).i2));
});
};
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(std::get<1>(t1), Eq(std::get<1>(r1)));
EXPECT_THAT(std::get<0>(t1).i1, Eq(std::get<0>(r1).i1));
EXPECT_THAT(std::get<0>(t1).i2, ::testing::Ne(std::get<0>(r1).i2));
}
TEST(SerializeExtensionStdTuple, EmptyTuple) {
std::tuple<> t1{};
std::tuple<> r1{};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{});
EXPECT_THAT(t1, Eq(r1));
TEST(SerializeExtensionStdTuple, EmptyTuple)
{
std::tuple<> t1{};
std::tuple<> r1{};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{});
EXPECT_THAT(t1, Eq(r1));
}
struct NonDefaultConstructable {
explicit NonDefaultConstructable(float x) : _x{x} {}
struct NonDefaultConstructable
{
explicit NonDefaultConstructable(float x)
: _x{ x }
{
}
float _x;
float _x;
bool operator==(const NonDefaultConstructable& rhs) const {
return _x == rhs._x;
}
bool operator==(const NonDefaultConstructable& rhs) const
{
return _x == rhs._x;
}
private:
friend class bitsery::Access;
friend class bitsery::Access;
NonDefaultConstructable() : _x{0.0f} {};
NonDefaultConstructable()
: _x{ 0.0f } {};
};
TEST(SerializeExtensionStdTuple, NonDefaultConstructable) {
std::tuple<NonDefaultConstructable> t1{34.0f};
std::tuple<NonDefaultConstructable> r1{8.0f};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdTuple{
[](auto& s, NonDefaultConstructable& v) {
s.value4b(v._x);
},
TEST(SerializeExtensionStdTuple, NonDefaultConstructable)
{
std::tuple<NonDefaultConstructable> t1{ 34.0f };
std::tuple<NonDefaultConstructable> r1{ 8.0f };
SerializationContext ctx;
ctx.createSerializer().ext(
t1,
bitsery::ext::StdTuple{
[](auto& s, NonDefaultConstructable& v) { s.value4b(v._x); },
});
ctx.createDeserializer().ext(r1, bitsery::ext::StdTuple{
[](auto& s, NonDefaultConstructable& v) {
s.value4b(v._x);
},
ctx.createDeserializer().ext(
r1,
bitsery::ext::StdTuple{
[](auto& s, NonDefaultConstructable& v) { s.value4b(v._x); },
});
EXPECT_THAT(t1, Eq(r1));
EXPECT_THAT(t1, Eq(r1));
}
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::tuple tests")
#pragma message( \
"C++17 and /Zc:__cplusplus option is required to enable std::tuple tests")
#else
#pragma message("C++17 is required to enable std::tuple tests")
#endif

View File

@@ -1,28 +1,27 @@
//MIT License
// MIT License
//
//Copyright (c) 2019 Mindaugas Vinkelis
// Copyright (c) 2019 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
#if __cplusplus > 201402L
@@ -33,142 +32,153 @@ using testing::Eq;
template<typename T, size_t N>
using OverloadValue = bitsery::ext::OverloadValue<T, N>;
TEST(SerializeExtensionStdVariant, UseSerializeFunction) {
TEST(SerializeExtensionStdVariant, UseSerializeFunction)
{
std::variant<MyStruct1, MyStruct2> t1{MyStruct1{978, 15}};
std::variant<MyStruct1, MyStruct2> r1{MyStruct2{}};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{});
EXPECT_THAT(t1, Eq(r1));
std::variant<MyStruct1, MyStruct2> t1{ MyStruct1{ 978, 15 } };
std::variant<MyStruct1, MyStruct2> r1{ MyStruct2{} };
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{});
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdVariant, WhenTwoIndicesWithSameTypeThenDeserializeCorrectIndex) {
TEST(SerializeExtensionStdVariant,
WhenTwoIndicesWithSameTypeThenDeserializeCorrectIndex)
{
std::variant<MyStruct1, MyStruct2, MyStruct1> t1{std::in_place_index_t<2>{}, MyStruct1{978, 15}};
std::variant<MyStruct1, MyStruct2, MyStruct1> r1{MyStruct2{}};
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{});
EXPECT_THAT(t1, Eq(r1));
std::variant<MyStruct1, MyStruct2, MyStruct1> t1{ std::in_place_index_t<2>{},
MyStruct1{ 978, 15 } };
std::variant<MyStruct1, MyStruct2, MyStruct1> r1{ MyStruct2{} };
SerializationContext ctx;
ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{});
ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{});
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdVariant, ValueTypesCanBeSerializedWithLambda) {
TEST(SerializeExtensionStdVariant, ValueTypesCanBeSerializedWithLambda)
{
std::variant<float, char, MyStruct1> t1{5.6f};
std::variant<float, char, MyStruct1> r1{MyStruct1{}};
SerializationContext ctx;
auto fncFloat = [](auto& s, float& v) {
s.value4b(v);
};
auto fncChar = [](auto& s, char& v) {
s.value1b(v);
};
ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{fncFloat, fncChar});
ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{fncFloat, fncChar});
EXPECT_THAT(t1, Eq(r1));
std::variant<float, char, MyStruct1> t1{ 5.6f };
std::variant<float, char, MyStruct1> r1{ MyStruct1{} };
SerializationContext ctx;
auto fncFloat = [](auto& s, float& v) { s.value4b(v); };
auto fncChar = [](auto& s, char& v) { s.value1b(v); };
ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{ fncFloat, fncChar });
ctx.createDeserializer().ext(r1,
bitsery::ext::StdVariant{ fncFloat, fncChar });
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdVariant, ValueTypesCanBeSerializedWithLambdaAndOrCallableObject) {
std::variant<float, char, MyStruct1> t1{'Z'};
std::variant<float, char, MyStruct1> r1{MyStruct1{}};
SerializationContext ctx;
auto fncFloat = [](auto& s, float& v) {
s.value4b(v);
};
TEST(SerializeExtensionStdVariant,
ValueTypesCanBeSerializedWithLambdaAndOrCallableObject)
{
std::variant<float, char, MyStruct1> t1{ 'Z' };
std::variant<float, char, MyStruct1> r1{ MyStruct1{} };
SerializationContext ctx;
auto fncFloat = [](auto& s, float& v) { s.value4b(v); };
ctx.createSerializer().ext(t1, bitsery::ext::StdVariant{fncFloat, OverloadValue<char, 1>{}});
ctx.createDeserializer().ext(r1, bitsery::ext::StdVariant{fncFloat, OverloadValue<char, 1>{}});
EXPECT_THAT(t1, Eq(r1));
ctx.createSerializer().ext(
t1, bitsery::ext::StdVariant{ fncFloat, OverloadValue<char, 1>{} });
ctx.createDeserializer().ext(
r1, bitsery::ext::StdVariant{ fncFloat, OverloadValue<char, 1>{} });
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdVariant, CanOverloadDefaultSerializationFunction) {
std::variant<MyStruct2, MyStruct1, int32_t> t1{MyStruct1{5, 9}};
std::variant<MyStruct2, MyStruct1, int32_t> r1{MyStruct1{}};
SerializationContext ctx;
auto exec = [](auto& s, std::variant<MyStruct2, MyStruct1, int32_t>& o) {
using S = decltype(s);
s.ext(o, bitsery::ext::StdVariant{
[](S& s, MyStruct1& v) {
s.value4b(v.i1);
//do not serialize other element, it should be 0 (default)
},
OverloadValue<int32_t, 4>{}
});
};
TEST(SerializeExtensionStdVariant, CanOverloadDefaultSerializationFunction)
{
std::variant<MyStruct2, MyStruct1, int32_t> t1{ MyStruct1{ 5, 9 } };
std::variant<MyStruct2, MyStruct1, int32_t> r1{ MyStruct1{} };
SerializationContext ctx;
auto exec = [](auto& s, std::variant<MyStruct2, MyStruct1, int32_t>& o) {
using S = decltype(s);
s.ext(o,
bitsery::ext::StdVariant{ [](S& s, MyStruct1& v) {
s.value4b(v.i1);
// do not serialize other element, it
// should be 0 (default)
},
OverloadValue<int32_t, 4>{} });
};
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(std::get<1>(r1).i2, Eq(0));
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(std::get<1>(r1).i2, Eq(0));
}
struct NonDefaultConstructable
{
explicit NonDefaultConstructable(float x)
: _x{ x }
{
}
struct NonDefaultConstructable {
explicit NonDefaultConstructable(float x) : _x{x} {}
float _x;
float _x;
bool operator==(const NonDefaultConstructable& rhs) const {
return _x == rhs._x;
}
bool operator==(const NonDefaultConstructable& rhs) const
{
return _x == rhs._x;
}
private:
friend class bitsery::Access;
friend class bitsery::Access;
NonDefaultConstructable() : _x{0.0f} {};
NonDefaultConstructable()
: _x{ 0.0f } {};
};
TEST(SerializeExtensionStdVariant, CanUseNonDefaultConstructableTypes) {
std::variant<NonDefaultConstructable, MyStruct1, int32_t> t1{NonDefaultConstructable{123.456f}};
std::variant<NonDefaultConstructable, MyStruct1, int32_t> r1{MyStruct1{}};
SerializationContext ctx;
TEST(SerializeExtensionStdVariant, CanUseNonDefaultConstructableTypes)
{
std::variant<NonDefaultConstructable, MyStruct1, int32_t> t1{
NonDefaultConstructable{ 123.456f }
};
std::variant<NonDefaultConstructable, MyStruct1, int32_t> r1{ MyStruct1{} };
SerializationContext ctx;
auto exec = [](auto& s, std::variant<NonDefaultConstructable, MyStruct1, int32_t>& o) {
using S = decltype(s);
s.ext(o, bitsery::ext::StdVariant{
[](S& s, NonDefaultConstructable& v) {
s.value4b(v._x);
},
OverloadValue<int32_t, 4>{}
});
};
auto exec = [](auto& s,
std::variant<NonDefaultConstructable, MyStruct1, int32_t>& o) {
using S = decltype(s);
s.ext(o,
bitsery::ext::StdVariant{
[](S& s, NonDefaultConstructable& v) { s.value4b(v._x); },
OverloadValue<int32_t, 4>{} });
};
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(t1, Eq(r1));
EXPECT_THAT(t1, Eq(r1));
}
TEST(SerializeExtensionStdVariant, CorrectlyHandleMonoState)
{
std::variant<std::monostate, NonDefaultConstructable, MyStruct1> t1{};
std::variant<std::monostate, NonDefaultConstructable, MyStruct1> r1{};
SerializationContext ctx;
TEST(SerializeExtensionStdVariant, CorrectlyHandleMonoState) {
std::variant<std::monostate, NonDefaultConstructable, MyStruct1> t1{};
std::variant<std::monostate, NonDefaultConstructable, MyStruct1> r1{};
SerializationContext ctx;
auto exec = [](auto& s, auto& o) {
using S = decltype(s);
s.ext(o,
bitsery::ext::StdVariant{
[](S& s, NonDefaultConstructable& v) { s.value4b(v._x); },
});
};
auto exec = [](auto& s, auto& o) {
using S = decltype(s);
s.ext(o, bitsery::ext::StdVariant{
[](S& s, NonDefaultConstructable& v) {
s.value4b(v._x);
},
});
};
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(t1, Eq(r1));
std::variant<std::monostate> t2{};
std::variant<std::monostate> r2{};
SerializationContext ctx1;
ctx1.createSerializer().ext(t2, bitsery::ext::StdVariant{});
ctx1.createDeserializer().ext(r2, bitsery::ext::StdVariant{});
EXPECT_THAT(t2, Eq(r2));
ctx.createSerializer().object(t1, exec);
ctx.createDeserializer().object(r1, exec);
EXPECT_THAT(t1, Eq(r1));
std::variant<std::monostate> t2{};
std::variant<std::monostate> r2{};
SerializationContext ctx1;
ctx1.createSerializer().ext(t2, bitsery::ext::StdVariant{});
ctx1.createDeserializer().ext(r2, bitsery::ext::StdVariant{});
EXPECT_THAT(t2, Eq(r2));
}
#elif defined(_MSC_VER)
#pragma message("C++17 and /Zc:__cplusplus option is required to enable std::variant tests")
#pragma message( \
"C++17 and /Zc:__cplusplus option is required to enable std::variant tests")
#else
#pragma message("C++17 is required to enable std::variant tests")
#endif

View File

@@ -1,29 +1,28 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/ext/value_range.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using namespace testing;
using bitsery::details::RangeSpec;
@@ -32,20 +31,20 @@ using bitsery::ext::ValueRange;
#if __cplusplus > 201103L
TEST(SerializeExtensionValueRange, RequiredBitsIsConstexpr) {
constexpr RangeSpec<int> r1{0, 31};
static_assert(r1.bitsRequired == 5, "r1.bitsRequired == 5");
TEST(SerializeExtensionValueRange, RequiredBitsIsConstexpr)
{
constexpr RangeSpec<int> r1{ 0, 31 };
static_assert(r1.bitsRequired == 5, "r1.bitsRequired == 5");
constexpr RangeSpec<MyEnumClass> r2{MyEnumClass::E1, MyEnumClass::E4};
static_assert(r2.bitsRequired == 2, "r2.bitsRequired == 2");
constexpr RangeSpec<MyEnumClass> r2{ MyEnumClass::E1, MyEnumClass::E4 };
static_assert(r2.bitsRequired == 2, "r2.bitsRequired == 2");
constexpr RangeSpec<double> r3{-1.0,1.0, BitsConstraint{5u}};
//EXPECT_THAT(r1.bitsRequired, Eq(5));
static_assert(r3.bitsRequired == 5, "r3.bitsRequired == 5");
constexpr RangeSpec<float> r4{-1.0f,1.0f, 0.01f};
static_assert(r4.bitsRequired == 8, "r4.bitsRequired == 8");
constexpr RangeSpec<double> r3{ -1.0, 1.0, BitsConstraint{ 5u } };
// EXPECT_THAT(r1.bitsRequired, Eq(5));
static_assert(r3.bitsRequired == 5, "r3.bitsRequired == 5");
constexpr RangeSpec<float> r4{ -1.0f, 1.0f, 0.01f };
static_assert(r4.bitsRequired == 8, "r4.bitsRequired == 8");
}
#endif
@@ -53,158 +52,157 @@ TEST(SerializeExtensionValueRange, RequiredBitsIsConstexpr) {
using BPSer = SerializationContext::TSerializerBPEnabled;
using BPDes = SerializationContext::TDeserializerBPEnabled;
TEST(SerializeExtensionValueRange, IntegerNegative)
{
SerializationContext ctx;
ValueRange<int> r1{ -50, 50 };
int t1{ -8 };
int res1;
ctx.createSerializer().enableBitPacking(
[&t1, &r1](BPSer& ser) { ser.ext(t1, r1); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
TEST(SerializeExtensionValueRange, IntegerNegative) {
SerializationContext ctx;
ValueRange<int> r1{-50, 50};
int t1{-8};
int res1;
ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) {
ser.ext(t1, r1);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
}
TEST(SerializeExtensionValueRange, IntegerPositive) {
SerializationContext ctx;
ValueRange<unsigned> r1{4u, 10u};
unsigned t1{8};
unsigned res1;
TEST(SerializeExtensionValueRange, IntegerPositive)
{
SerializationContext ctx;
ValueRange<unsigned> r1{ 4u, 10u };
unsigned t1{ 8 };
unsigned res1;
ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) {
ser.ext(t1, r1);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
ctx.createSerializer().enableBitPacking(
[&t1, &r1](BPSer& ser) { ser.ext(t1, r1); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
}
TEST(SerializeExtensionValueRange, EnumTypes) {
SerializationContext ctx;
ValueRange<MyEnumClass> r1{MyEnumClass::E2, MyEnumClass::E4};
MyEnumClass t1{MyEnumClass::E2};
MyEnumClass res1;
TEST(SerializeExtensionValueRange, EnumTypes)
{
SerializationContext ctx;
ValueRange<MyEnumClass> r1{ MyEnumClass::E2, MyEnumClass::E4 };
MyEnumClass t1{ MyEnumClass::E2 };
MyEnumClass res1;
ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) {
ser.ext(t1, r1);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
ctx.createSerializer().enableBitPacking(
[&t1, &r1](BPSer& ser) { ser.ext(t1, r1); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
}
TEST(SerializeExtensionValueRange, FloatUsingPrecisionConstraint1) {
SerializationContext ctx;
constexpr float precision{0.01f};
constexpr float min{-1.0f};
constexpr float max{1.0f};
float t1{0.5f};
ValueRange<float> r1{min, max, precision};
TEST(SerializeExtensionValueRange, FloatUsingPrecisionConstraint1)
{
SerializationContext ctx;
constexpr float precision{ 0.01f };
constexpr float min{ -1.0f };
constexpr float max{ 1.0f };
float t1{ 0.5f };
ValueRange<float> r1{ min, max, precision };
float res1;
float res1;
ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) {
ser.ext(t1, r1);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
ctx.createSerializer().enableBitPacking(
[&t1, &r1](BPSer& ser) { ser.ext(t1, r1); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) * precision));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) * precision));
}
TEST(SerializeExtensionValueRange, DoubleUsingPrecisionConstraint2) {
SerializationContext ctx;
constexpr double precision{0.000002};
constexpr double min{50.0};
constexpr double max{100000.0};
double t1{38741.0};
ValueRange<double> r1{min, max, precision};
TEST(SerializeExtensionValueRange, DoubleUsingPrecisionConstraint2)
{
SerializationContext ctx;
constexpr double precision{ 0.000002 };
constexpr double min{ 50.0 };
constexpr double max{ 100000.0 };
double t1{ 38741.0 };
ValueRange<double> r1{ min, max, precision };
double res1;
double res1;
ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) {
ser.ext(t1, r1);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
ctx.createSerializer().enableBitPacking(
[&t1, &r1](BPSer& ser) { ser.ext(t1, r1); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
EXPECT_THAT(ctx.getBufferSize(), Eq(5));
EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) * precision));
EXPECT_THAT(ctx.getBufferSize(), Eq(5));
EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) * precision));
}
TEST(SerializeExtensionValueRange, FloatUsingBitsSizeConstraint1) {
SerializationContext ctx;
constexpr size_t bits = 8;
constexpr float min{-1.0f};
constexpr float max{1.0f};
float t1{0.5f};
ValueRange<float> r1{min, max, BitsConstraint(bits)};
TEST(SerializeExtensionValueRange, FloatUsingBitsSizeConstraint1)
{
SerializationContext ctx;
constexpr size_t bits = 8;
constexpr float min{ -1.0f };
constexpr float max{ 1.0f };
float t1{ 0.5f };
ValueRange<float> r1{ min, max, BitsConstraint(bits) };
float res1;
float res1;
ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) {
ser.ext(t1, r1);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
ctx.createSerializer().enableBitPacking(
[&t1, &r1](BPSer& ser) { ser.ext(t1, r1); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) / (static_cast<bitsery::details::SameSizeUnsigned<float>>(1) << bits)));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(
res1,
::testing::FloatNear(
t1,
(max - min) /
(static_cast<bitsery::details::SameSizeUnsigned<float>>(1) << bits)));
}
TEST(SerializeExtensionValueRange, DoubleUsingBitsSizeConstraint2) {
SerializationContext ctx;
constexpr size_t bits = 50;
constexpr double min{50.0};
constexpr double max{100000.0};
double t1{38741};
ValueRange<double> r1{min, max, BitsConstraint(bits)};
TEST(SerializeExtensionValueRange, DoubleUsingBitsSizeConstraint2)
{
SerializationContext ctx;
constexpr size_t bits = 50;
constexpr double min{ 50.0 };
constexpr double max{ 100000.0 };
double t1{ 38741 };
ValueRange<double> r1{ min, max, BitsConstraint(bits) };
double res1;
double res1;
ctx.createSerializer().enableBitPacking([&t1, &r1](BPSer& ser) {
ser.ext(t1, r1);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
ctx.createSerializer().enableBitPacking(
[&t1, &r1](BPSer& ser) { ser.ext(t1, r1); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
EXPECT_THAT(ctx.getBufferSize(), Eq(7));
EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) / (static_cast<bitsery::details::SameSizeUnsigned<double>>(1) << bits)));
EXPECT_THAT(ctx.getBufferSize(), Eq(7));
EXPECT_THAT(
res1,
::testing::DoubleNear(
t1,
(max - min) /
(static_cast<bitsery::details::SameSizeUnsigned<double>>(1) << bits)));
}
TEST(SerializeExtensionValueRange, WhenDataIsInvalidThenReturnMinimumRangeValue) {
SerializationContext ctx;
ValueRange<int> r1{4, 10};//6 is max, but 3bits required
int res1;
uint8_t tmp{0xFF};//write all 1 so when reading 3 bits we get 7
TEST(SerializeExtensionValueRange, WhenDataIsInvalidThenReturnMinimumRangeValue)
{
SerializationContext ctx;
ValueRange<int> r1{ 4, 10 }; // 6 is max, but 3bits required
int res1;
uint8_t tmp{ 0xFF }; // write all 1 so when reading 3 bits we get 7
ctx.createSerializer().enableBitPacking([&tmp](BPSer& ser) {
ser.value1b(tmp);
});
ctx.createDeserializer().enableBitPacking([&res1, &r1](BPDes& des) {
des.ext(res1, r1);
});
ctx.createSerializer().enableBitPacking(
[&tmp](BPSer& ser) { ser.value1b(tmp); });
ctx.createDeserializer().enableBitPacking(
[&res1, &r1](BPDes& des) { des.ext(res1, r1); });
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(4));
EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(4));
EXPECT_THAT(ctx.des->adapter().error(),
Eq(bitsery::ReaderError::InvalidData));
}

View File

@@ -1,128 +1,132 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bitsery/traits/string.h>
#include <bitsery/traits/array.h>
#include <bitsery/traits/string.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::ContainerEq;
using testing::Eq;
using testing::StrEq;
using testing::ContainerEq;
struct X {
X() {};
X(int v) :x{ v } {}
std::string s{};
int x{};
bool operator ==(const X& r) const {
return r.x == x && r.s == s;
}
struct X
{
X(){};
X(int v)
: x{ v }
{
}
std::string s{};
int x{};
bool operator==(const X& r) const { return r.x == x && r.s == s; }
};
struct Y {
int y{};
int carr[3]{};
std::array<int, 3> arr{};
std::vector<X> vx{};
std::string s{};
struct Y
{
int y{};
int carr[3]{};
std::array<int, 3> arr{};
std::vector<X> vx{};
std::string s{};
};
struct Z { X x{}; Y y{}; };
template <typename S>
void serialize(S& s, Z& o)
struct Z
{
s.object(o.x);
s.object(o.y);
X x{};
Y y{};
};
template<typename S>
void
serialize(S& s, Z& o)
{
s.object(o.x);
s.object(o.y);
}
template <typename S>
void serialize(S& s, X& o)
template<typename S>
void
serialize(S& s, X& o)
{
s.template value<sizeof(o.x)>(o.x);
s.template text<1>(o.s, 1000);
s.template value<sizeof(o.x)>(o.x);
s.template text<1>(o.s, 1000);
}
template <typename S>
void serialize(S& s, Y& o)
template<typename S>
void
serialize(S& s, Y& o)
{
auto writeInt = [](S& s, int& v) { s.template value<sizeof(v)>(v); };
s.template text<1>(o.s, 10000);
s.template value<sizeof(o.y)>(o.y);
s.container(o.arr, writeInt);
s.container(o.carr, writeInt);
s.container(o.vx, 10000, [](S& s, X& v) { s.object(v); });
auto writeInt = [](S& s, int& v) { s.template value<sizeof(v)>(v); };
s.template text<1>(o.s, 10000);
s.template value<sizeof(o.y)>(o.y);
s.container(o.arr, writeInt);
s.container(o.carr, writeInt);
s.container(o.vx, 10000, [](S& s, X& v) { s.object(v); });
}
TEST(SerializeObject, GeneralConceptTest)
{
// std::string buf;
SerializationContext ctx;
Y y{};
y.y = 3423;
y.arr[0] = 111;
y.arr[1] = 222;
y.arr[2] = 333;
y.carr[0] = 123;
y.carr[1] = 456;
y.carr[2] = 789;
y.vx.push_back(X(234));
y.vx.push_back(X(6245));
y.vx.push_back(X(613461));
y.s = "labal diena";
TEST(SerializeObject, GeneralConceptTest) {
//std::string buf;
SerializationContext ctx;
Y y{};
y.y = 3423;
y.arr[0] = 111;
y.arr[1] = 222;
y.arr[2] = 333;
y.carr[0] = 123;
y.carr[1] = 456;
y.carr[2] = 789;
y.vx.push_back(X(234));
y.vx.push_back(X(6245));
y.vx.push_back(X(613461));
y.s = "labal diena";
Z z{};
z.y = y;
z.x = X{ 234 };
Z z{};
z.y = y;
z.x = X{ 234 };
auto& ser = ctx.createSerializer();
ser.object(y);
ser.object(z);
auto& ser = ctx.createSerializer();
ser.object(y);
ser.object(z);
Y yres{};
Z zres{};
auto& des = ctx.createDeserializer();
des.object(yres);
des.object(zres);
Y yres{};
Z zres{};
auto& des = ctx.createDeserializer();
des.object(yres);
des.object(zres);
EXPECT_THAT(yres.y, Eq(y.y));
EXPECT_THAT(yres.vx, ContainerEq(y.vx));
EXPECT_THAT(yres.arr, ContainerEq(y.arr));
EXPECT_THAT(yres.carr, ContainerEq(y.carr));
EXPECT_THAT(yres.s, StrEq(y.s));
EXPECT_THAT(zres.y.y, Eq(z.y.y));
EXPECT_THAT(zres.y.vx, ContainerEq(z.y.vx));
EXPECT_THAT(zres.y.arr, ContainerEq(z.y.arr));
EXPECT_THAT(zres.y.carr, ContainerEq(z.y.carr));
EXPECT_THAT(zres.y.s, StrEq(z.y.s));
EXPECT_THAT(zres.x.s, StrEq(z.x.s));
EXPECT_THAT(zres.x.x, Eq(z.x.x));
EXPECT_THAT(yres.y, Eq(y.y));
EXPECT_THAT(yres.vx, ContainerEq(y.vx));
EXPECT_THAT(yres.arr, ContainerEq(y.arr));
EXPECT_THAT(yres.carr, ContainerEq(y.carr));
EXPECT_THAT(yres.s, StrEq(y.s));
EXPECT_THAT(zres.y.y, Eq(z.y.y));
EXPECT_THAT(zres.y.vx, ContainerEq(z.y.vx));
EXPECT_THAT(zres.y.arr, ContainerEq(z.y.arr));
EXPECT_THAT(zres.y.carr, ContainerEq(z.y.carr));
EXPECT_THAT(zres.y.s, StrEq(z.y.s));
EXPECT_THAT(zres.x.s, StrEq(z.x.s));
EXPECT_THAT(zres.x.x, Eq(z.x.x));
}

View File

@@ -1,64 +1,68 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
bool SerializeDeserializeContainerSize(SerializationContext& ctx, const size_t size) {
std::vector<char> t1(size);
auto& ser = ctx.createSerializer();
ser.container(t1, size+1, [](decltype(ser)& , char& ){});
t1.clear();
auto& des = ctx.createDeserializer();
des.container(t1, size+1, [](decltype(des)&, char& ){});
return t1.size() == size;
bool
SerializeDeserializeContainerSize(SerializationContext& ctx, const size_t size)
{
std::vector<char> t1(size);
auto& ser = ctx.createSerializer();
ser.container(t1, size + 1, [](decltype(ser)&, char&) {});
t1.clear();
auto& des = ctx.createDeserializer();
des.container(t1, size + 1, [](decltype(des)&, char&) {});
return t1.size() == size;
}
TEST(SerializeSize, WhenLengthLessThan128Then1Byte) {
SerializationContext ctx1{};
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 127));
EXPECT_THAT(ctx1.getBufferSize(), Eq(1u));
SerializationContext ctx2;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 128));
EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(1u));
TEST(SerializeSize, WhenLengthLessThan128Then1Byte)
{
SerializationContext ctx1{};
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 127));
EXPECT_THAT(ctx1.getBufferSize(), Eq(1u));
SerializationContext ctx2;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 128));
EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(1u));
}
TEST(SerializeSize, WhenLengthLessThan16384Then2Bytes) {
SerializationContext ctx1;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16383));
EXPECT_THAT(ctx1.getBufferSize(), Eq(2u));
SerializationContext ctx2;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 16384));
EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(2u));
TEST(SerializeSize, WhenLengthLessThan16384Then2Bytes)
{
SerializationContext ctx1;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16383));
EXPECT_THAT(ctx1.getBufferSize(), Eq(2u));
SerializationContext ctx2;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 16384));
EXPECT_THAT(ctx2.getBufferSize(), testing::Gt(2u));
}
TEST(SerializeSize, WhenGreaterThan16383Then4Bytes) {
SerializationContext ctx1;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16384));
EXPECT_THAT(ctx1.getBufferSize(), Eq(4u));
SerializationContext ctx2;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 66384));
EXPECT_THAT(ctx2.getBufferSize(), Eq(4u));
TEST(SerializeSize, WhenGreaterThan16383Then4Bytes)
{
SerializationContext ctx1;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx1, 16384));
EXPECT_THAT(ctx1.getBufferSize(), Eq(4u));
SerializationContext ctx2;
EXPECT_TRUE(SerializeDeserializeContainerSize(ctx2, 66384));
EXPECT_THAT(ctx2.getBufferSize(), Eq(4u));
}

View File

@@ -1,167 +1,210 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef BITSERY_SERIALIZER_TEST_UTILS_H
#define BITSERY_SERIALIZER_TEST_UTILS_H
#include <memory>
#include <bitsery/adapter/buffer.h>
#include <bitsery/bitsery.h>
#include <bitsery/traits/vector.h>
#include <bitsery/adapter/buffer.h>
#include <memory>
/*
* define some types for testing
*/
struct MyStruct1 {
MyStruct1(int32_t v1, int32_t v2) : i1{v1}, i2{v2} {}
struct MyStruct1
{
MyStruct1(int32_t v1, int32_t v2)
: i1{ v1 }
, i2{ v2 }
{
}
MyStruct1() : MyStruct1{0, 0} {}
MyStruct1()
: MyStruct1{ 0, 0 }
{
}
int32_t i1;
int32_t i2;
int32_t i1;
int32_t i2;
bool operator==(const MyStruct1 &rhs) const {
return i1 == rhs.i1 && i2 == rhs.i2;
}
friend bool operator < (const MyStruct1 &lhs, const MyStruct1 &rhs) {
return lhs.i1 < rhs.i1 || (lhs.i1 == rhs.i1 && lhs.i2 < rhs.i2);
}
bool operator==(const MyStruct1& rhs) const
{
return i1 == rhs.i1 && i2 == rhs.i2;
}
friend bool operator<(const MyStruct1& lhs, const MyStruct1& rhs)
{
return lhs.i1 < rhs.i1 || (lhs.i1 == rhs.i1 && lhs.i2 < rhs.i2);
}
static constexpr size_t SIZE = sizeof(MyStruct1::i1) + sizeof(MyStruct1::i2);
static constexpr size_t SIZE = sizeof(MyStruct1::i1) + sizeof(MyStruct1::i2);
};
template <typename S>
void serialize(S& s, MyStruct1& o) {
s.template value<sizeof(o.i1)>(o.i1);
s.template value<sizeof(o.i2)>(o.i2);
template<typename S>
void
serialize(S& s, MyStruct1& o)
{
s.template value<sizeof(o.i1)>(o.i1);
s.template value<sizeof(o.i2)>(o.i2);
}
enum class MyEnumClass:int32_t {
E1, E2, E3, E4, E5, E6
enum class MyEnumClass : int32_t
{
E1,
E2,
E3,
E4,
E5,
E6
};
struct MyStruct2 {
enum MyEnum {
V1, V2, V3, V4, V5, V6
};
struct MyStruct2
{
enum MyEnum
{
V1,
V2,
V3,
V4,
V5,
V6
};
MyStruct2(MyEnum e, MyStruct1 s) : e1{e}, s1{s} {}
MyStruct2(MyEnum e, MyStruct1 s)
: e1{ e }
, s1{ s }
{
}
MyStruct2() : MyStruct2{V1, {0, 0}} {}
MyStruct2()
: MyStruct2{ V1, { 0, 0 } }
{
}
MyEnum e1;
MyStruct1 s1;
MyEnum e1;
MyStruct1 s1;
bool operator==(const MyStruct2 &rhs) const {
return e1 == rhs.e1 && s1 == rhs.s1;
}
bool operator==(const MyStruct2& rhs) const
{
return e1 == rhs.e1 && s1 == rhs.s1;
}
static constexpr size_t SIZE = MyStruct1::SIZE + sizeof(MyStruct2::e1);
static constexpr size_t SIZE = MyStruct1::SIZE + sizeof(MyStruct2::e1);
};
template <typename S>
void serialize(S&s, MyStruct2& o) {
s.template value<sizeof(o.e1)>(o.e1);
s.object(o.s1);
template<typename S>
void
serialize(S& s, MyStruct2& o)
{
s.template value<sizeof(o.e1)>(o.e1);
s.object(o.s1);
}
using Buffer = std::vector<char>;
using Reader = bitsery::InputBufferAdapter<Buffer>;
using Writer = bitsery::OutputBufferAdapter<Buffer>;
template <typename Context>
class BasicSerializationContext {
template<typename Context>
class BasicSerializationContext
{
public:
using TSerializer = bitsery::Serializer<Writer, Context>;
using TDeserializer = bitsery::Deserializer<Reader, Context>;
using TSerializerBPEnabled = typename TSerializer::BPEnabledType;
using TDeserializerBPEnabled = typename TDeserializer::BPEnabledType;
using TSerializer = bitsery::Serializer<Writer, Context>;
using TDeserializer = bitsery::Deserializer<Reader, Context>;
using TSerializerBPEnabled = typename TSerializer::BPEnabledType;
using TDeserializerBPEnabled = typename TDeserializer::BPEnabledType;
Buffer buf{};
std::unique_ptr<TSerializer> ser{};
std::unique_ptr<TDeserializer> des{};
Buffer buf{};
std::unique_ptr<TSerializer> ser{};
std::unique_ptr<TDeserializer> des{};
template <typename T=Context, typename std::enable_if<std::is_void<T>::value>::type* = nullptr>
TSerializer& createSerializer() {
if (!ser) {
ser = std::unique_ptr<TSerializer>(new TSerializer{buf});
}
return *ser;
template<typename T = Context,
typename std::enable_if<std::is_void<T>::value>::type* = nullptr>
TSerializer& createSerializer()
{
if (!ser) {
ser = std::unique_ptr<TSerializer>(new TSerializer{ buf });
}
return *ser;
}
template <typename T=Context>
TSerializer& createSerializer(typename std::enable_if<!std::is_void<T>::value, T>::type& ctx) {
if (!ser) {
ser = std::unique_ptr<TSerializer>(new TSerializer{ctx, buf});
}
return *ser;
template<typename T = Context>
TSerializer& createSerializer(
typename std::enable_if<!std::is_void<T>::value, T>::type& ctx)
{
if (!ser) {
ser = std::unique_ptr<TSerializer>(new TSerializer{ ctx, buf });
}
return *ser;
}
template <typename T=Context, typename std::enable_if<std::is_void<T>::value>::type* = nullptr>
TDeserializer& createDeserializer() {
size_t writtenBytes = 0;
if (ser) {
ser->adapter().flush();
writtenBytes = ser->adapter().writtenBytesCount();
}
if (!des) {
des = std::unique_ptr<TDeserializer>(new TDeserializer{buf.begin(), writtenBytes});
}
return *des;
template<typename T = Context,
typename std::enable_if<std::is_void<T>::value>::type* = nullptr>
TDeserializer& createDeserializer()
{
size_t writtenBytes = 0;
if (ser) {
ser->adapter().flush();
writtenBytes = ser->adapter().writtenBytesCount();
}
template <typename T=Context>
TDeserializer& createDeserializer(typename std::enable_if<!std::is_void<T>::value, T>::type& ctx) {
size_t writtenBytes = 0;
if (ser) {
ser->adapter().flush();
writtenBytes = ser->adapter().writtenBytesCount();
}
if (!des) {
des = std::unique_ptr<TDeserializer>(new TDeserializer{ctx, buf.begin(), writtenBytes});
}
return *des;
if (!des) {
des = std::unique_ptr<TDeserializer>(
new TDeserializer{ buf.begin(), writtenBytes });
}
return *des;
}
size_t getBufferSize() const {
return ser->adapter().writtenBytesCount();
template<typename T = Context>
TDeserializer& createDeserializer(
typename std::enable_if<!std::is_void<T>::value, T>::type& ctx)
{
size_t writtenBytes = 0;
if (ser) {
ser->adapter().flush();
writtenBytes = ser->adapter().writtenBytesCount();
}
//since all containers .size() method returns size_t, it cannot be directly serialized, because size_t is platform dependant
//this function returns number of bytes written to buffer, when reading/writing size of container
static size_t containerSizeSerializedBytesCount(size_t elemsCount) {
if (elemsCount < 0x80u)
return 1;
if (elemsCount < 0x4000u)
return 2;
return 4;
if (!des) {
des = std::unique_ptr<TDeserializer>(
new TDeserializer{ ctx, buf.begin(), writtenBytes });
}
return *des;
}
size_t getBufferSize() const { return ser->adapter().writtenBytesCount(); }
// since all containers .size() method returns size_t, it cannot be directly
// serialized, because size_t is platform dependant this function returns
// number of bytes written to buffer, when reading/writing size of container
static size_t containerSizeSerializedBytesCount(size_t elemsCount)
{
if (elemsCount < 0x80u)
return 1;
if (elemsCount < 0x4000u)
return 2;
return 4;
}
};
//helper type
// helper type
using SerializationContext = BasicSerializationContext<void>;
#endif //BITSERY_SERIALIZER_TEST_UTILS_H
#endif // BITSERY_SERIALIZER_TEST_UTILS_H

View File

@@ -1,129 +1,140 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "serialization_test_utils.h"
#include <bitsery/traits/string.h>
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using namespace testing;
TEST(SerializeText, BasicString) {
SerializationContext ctx;
std::string t1 = "some random text";
std::string res;
TEST(SerializeText, BasicString)
{
SerializationContext ctx;
std::string t1 = "some random text";
std::string res;
ctx.createSerializer().text<sizeof(std::string::value_type)>(t1, 1000);
ctx.createDeserializer().text<sizeof(std::string::value_type)>(res, 1000);
EXPECT_THAT(res, StrEq(t1));
EXPECT_THAT(res, ContainerEq(t1));
ctx.createSerializer().text<sizeof(std::string::value_type)>(t1, 1000);
ctx.createDeserializer().text<sizeof(std::string::value_type)>(res, 1000);
EXPECT_THAT(res, StrEq(t1));
EXPECT_THAT(res, ContainerEq(t1));
}
TEST(SerializeText, WhenSizeOfTypeNotEqualsOneThenSetSizeExplicitly) {
SerializationContext ctx;
constexpr auto VSIZE = sizeof(char32_t);
std::basic_string<char32_t> t1 = U"some random text";
std::basic_string<char32_t> res;
static_assert(VSIZE > 1, "on this system, all character types has sizeof == 1, cannot run this tests");
TEST(SerializeText, WhenSizeOfTypeNotEqualsOneThenSetSizeExplicitly)
{
SerializationContext ctx;
constexpr auto VSIZE = sizeof(char32_t);
std::basic_string<char32_t> t1 = U"some random text";
std::basic_string<char32_t> res;
static_assert(VSIZE > 1,
"on this system, all character types has sizeof == 1, cannot "
"run this tests");
ctx.createSerializer().text<VSIZE>(t1, 1000);
ctx.createDeserializer().text<VSIZE>(res, 1000);
ctx.createSerializer().text<VSIZE>(t1, 1000);
ctx.createDeserializer().text<VSIZE>(res, 1000);
EXPECT_THAT(res, ContainerEq(t1));
EXPECT_THAT(res, ContainerEq(t1));
}
TEST(SerializeText, BasicStringUseSizeMethodNotNullterminatedLength) {
SerializationContext ctx;
std::wstring t1(L"some random text\0xxxxxx", 20);
std::wstring wres;
constexpr auto VSIZE = sizeof(std::wstring::value_type);
TEST(SerializeText, BasicStringUseSizeMethodNotNullterminatedLength)
{
SerializationContext ctx;
std::wstring t1(L"some random text\0xxxxxx", 20);
std::wstring wres;
constexpr auto VSIZE = sizeof(std::wstring::value_type);
ctx.createSerializer().text<VSIZE>(t1, 1000);
ctx.createDeserializer().text<VSIZE>(wres, 1000);
ctx.createSerializer().text<VSIZE>(t1, 1000);
ctx.createDeserializer().text<VSIZE>(wres, 1000);
EXPECT_THAT(wres, StrEq(t1));
EXPECT_THAT(wres.size(), Eq(t1.size()));
EXPECT_THAT(wres.size(), Gt(std::char_traits<std::wstring::value_type>::length(t1.data())));
EXPECT_THAT(wres, StrEq(t1));
EXPECT_THAT(wres.size(), Eq(t1.size()));
EXPECT_THAT(
wres.size(),
Gt(std::char_traits<std::wstring::value_type>::length(t1.data())));
SerializationContext ctx2;
std::string t2("\0no one cares what is there", 10);
std::string res;
ctx2.createSerializer().text<sizeof(std::string::value_type)>(t2, 1000);
ctx2.createDeserializer().text<sizeof(std::string::value_type)>(res, 1000);
SerializationContext ctx2;
std::string t2("\0no one cares what is there", 10);
std::string res;
ctx2.createSerializer().text<sizeof(std::string::value_type)>(t2, 1000);
ctx2.createDeserializer().text<sizeof(std::string::value_type)>(res, 1000);
EXPECT_THAT(res, StrEq(t2));
EXPECT_THAT(res.size(), Eq(t2.size()));
EXPECT_THAT(res, StrEq(t2));
EXPECT_THAT(res.size(), Eq(t2.size()));
SerializationContext ctx3;
std::string t3("never ending buffer that doesnt fit in this string", 10);
ctx3.createSerializer().text<sizeof(std::string::value_type)>(t3, 1000);
ctx3.createDeserializer().text<sizeof(std::string::value_type)>(res, 1000);
EXPECT_THAT(res, StrEq(t3));
EXPECT_THAT(res.size(), Eq(10));
SerializationContext ctx3;
std::string t3("never ending buffer that doesnt fit in this string", 10);
ctx3.createSerializer().text<sizeof(std::string::value_type)>(t3, 1000);
ctx3.createDeserializer().text<sizeof(std::string::value_type)>(res, 1000);
EXPECT_THAT(res, StrEq(t3));
EXPECT_THAT(res.size(), Eq(10));
}
constexpr int CARR_LENGTH = 10;
TEST(SerializeText, CArraySerializesTextLength) {
SerializationContext ctx;
char t1[CARR_LENGTH]{"some text"};
char r1[CARR_LENGTH]{};
TEST(SerializeText, CArraySerializesTextLength)
{
SerializationContext ctx;
char t1[CARR_LENGTH]{ "some text" };
char r1[CARR_LENGTH]{};
ctx.createSerializer().text<1>(t1);
ctx.createDeserializer().text<1>(r1);
ctx.createSerializer().text<1>(t1);
ctx.createDeserializer().text<1>(r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) +
std::char_traits<char>::length(t1)));
EXPECT_THAT(ctx.getBufferSize(),
Eq(ctx.containerSizeSerializedBytesCount(CARR_LENGTH) +
std::char_traits<char>::length(t1)));
EXPECT_THAT(r1, StrEq(t1));
EXPECT_THAT(r1, ContainerEq(t1));
EXPECT_THAT(r1, StrEq(t1));
EXPECT_THAT(r1, ContainerEq(t1));
//zero length string
t1[0] = 0;
SerializationContext ctx2;
ctx2.createSerializer().text<1>(t1);
ctx2.createDeserializer().text<1>(r1);
// zero length string
t1[0] = 0;
SerializationContext ctx2;
ctx2.createSerializer().text<1>(t1);
ctx2.createDeserializer().text<1>(r1);
EXPECT_THAT(ctx2.getBufferSize(), Eq(ctx2.containerSizeSerializedBytesCount(CARR_LENGTH)));
EXPECT_THAT(r1, StrEq(t1));
EXPECT_THAT(r1, ContainerEq(t1));
EXPECT_THAT(ctx2.getBufferSize(),
Eq(ctx2.containerSizeSerializedBytesCount(CARR_LENGTH)));
EXPECT_THAT(r1, StrEq(t1));
EXPECT_THAT(r1, ContainerEq(t1));
}
#ifndef NDEBUG
TEST(SerializeText, WhenCArrayNotNullterminatedThenAssert) {
SerializationContext ctx;
char16_t t1[CARR_LENGTH]{u"some text"};
//make last character not nullterminated
t1[CARR_LENGTH-1] = 'x';
EXPECT_DEATH(ctx.createSerializer().text<2>(t1), "");
TEST(SerializeText, WhenCArrayNotNullterminatedThenAssert)
{
SerializationContext ctx;
char16_t t1[CARR_LENGTH]{ u"some text" };
// make last character not nullterminated
t1[CARR_LENGTH - 1] = 'x';
EXPECT_DEATH(ctx.createSerializer().text<2>(t1), "");
}
#endif
TEST(SerializeText, WhenContainerOrTextSizeIsMoreThanMaxThenInvalidDataError) {
SerializationContext ctx;
std::string tmp = "larger text then allowed";
ctx.createSerializer().text1b(tmp,100);
ctx.createDeserializer().text1b(tmp, 10);
EXPECT_THAT(ctx.des->adapter().error(), Eq(bitsery::ReaderError::InvalidData));
TEST(SerializeText, WhenContainerOrTextSizeIsMoreThanMaxThenInvalidDataError)
{
SerializationContext ctx;
std::string tmp = "larger text then allowed";
ctx.createSerializer().text1b(tmp, 100);
ctx.createDeserializer().text1b(tmp, 10);
EXPECT_THAT(ctx.des->adapter().error(),
Eq(bitsery::ReaderError::InvalidData));
}

View File

@@ -1,112 +1,133 @@
//MIT License
// MIT License
//
//Copyright (c) 2017 Mindaugas Vinkelis
// Copyright (c) 2017 Mindaugas Vinkelis
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <gmock/gmock.h>
using testing::Eq;
template <typename T>
bool SerializeDeserializeValue(const T& v) {
T res{};
SerializationContext ctx;
ctx.createSerializer().value<sizeof(T)>(v);
ctx.createDeserializer().value<sizeof(T)>(res);
return v == res;
template<typename T>
bool
SerializeDeserializeValue(const T& v)
{
T res{};
SerializationContext ctx;
ctx.createSerializer().value<sizeof(T)>(v);
ctx.createDeserializer().value<sizeof(T)>(res);
return v == res;
}
TEST(SerializeValues, IntegerTypes) {
EXPECT_THAT(SerializeDeserializeValue(-449874), Eq(true));
EXPECT_THAT(SerializeDeserializeValue(34u), Eq(true));
TEST(SerializeValues, IntegerTypes)
{
EXPECT_THAT(SerializeDeserializeValue(-449874), Eq(true));
EXPECT_THAT(SerializeDeserializeValue(34u), Eq(true));
}
TEST(SerializeValues, EnumTypes) {
enum E1{
A1,B1,C1,D1
};
EXPECT_THAT(SerializeDeserializeValue(E1::C1), Eq(true));
enum class E2 {
A2,B2,C2,D2
};
EXPECT_THAT(SerializeDeserializeValue(E2::B2), Eq(true));
enum class E3:short {
A3, B3, C3=4568, D3
};
EXPECT_THAT(SerializeDeserializeValue(E3::C3), Eq(true));
TEST(SerializeValues, EnumTypes)
{
enum E1
{
A1,
B1,
C1,
D1
};
EXPECT_THAT(SerializeDeserializeValue(E1::C1), Eq(true));
enum class E2
{
A2,
B2,
C2,
D2
};
EXPECT_THAT(SerializeDeserializeValue(E2::B2), Eq(true));
enum class E3 : short
{
A3,
B3,
C3 = 4568,
D3
};
EXPECT_THAT(SerializeDeserializeValue(E3::C3), Eq(true));
}
TEST(SerializeValues, FloatingPointTypes) {
EXPECT_THAT(SerializeDeserializeValue(-484.465), Eq(true));
EXPECT_THAT(SerializeDeserializeValue(0.00000015f), Eq(true));
TEST(SerializeValues, FloatingPointTypes)
{
EXPECT_THAT(SerializeDeserializeValue(-484.465), Eq(true));
EXPECT_THAT(SerializeDeserializeValue(0.00000015f), Eq(true));
}
TEST(SerializeValues, ValueSizeOverload1Byte) {
int8_t v{54};
int8_t res;
constexpr size_t TSIZE = sizeof(v);
TEST(SerializeValues, ValueSizeOverload1Byte)
{
int8_t v{ 54 };
int8_t res;
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value1b(v);
ctx.createDeserializer().value1b(res);
SerializationContext ctx;
ctx.createSerializer().value1b(v);
ctx.createDeserializer().value1b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
}
TEST(SerializeValues, ValueSizeOverload2Byte) {
int16_t v{54};
int16_t res;
constexpr size_t TSIZE = sizeof(v);
TEST(SerializeValues, ValueSizeOverload2Byte)
{
int16_t v{ 54 };
int16_t res;
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value2b(v);
ctx.createDeserializer().value2b(res);
SerializationContext ctx;
ctx.createSerializer().value2b(v);
ctx.createDeserializer().value2b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
}
TEST(SerializeValues, ValueSizeOverload4Byte) {
float v{54.498f};
float res;
constexpr size_t TSIZE = sizeof(v);
TEST(SerializeValues, ValueSizeOverload4Byte)
{
float v{ 54.498f };
float res;
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value4b(v);
ctx.createDeserializer().value4b(res);
SerializationContext ctx;
ctx.createSerializer().value4b(v);
ctx.createDeserializer().value4b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
}
TEST(SerializeValues, ValueSizeOverload8Byte) {
int64_t v{54};
int64_t res;
constexpr size_t TSIZE = sizeof(v);
TEST(SerializeValues, ValueSizeOverload8Byte)
{
int64_t v{ 54 };
int64_t res;
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value8b(v);
ctx.createDeserializer().value8b(res);
SerializationContext ctx;
ctx.createSerializer().value8b(v);
ctx.createDeserializer().value8b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
}