mirror of
https://github.com/fraillt/bitsery.git
synced 2026-06-08 08:13:56 +00:00
format code base in Mozilla style
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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]));
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user