separated advanced features from core functionality

This commit is contained in:
fraillt
2017-09-19 16:10:49 +03:00
parent ad7090539e
commit f0508025f6
36 changed files with 1194 additions and 964 deletions

View File

@@ -24,7 +24,7 @@
#include <gmock/gmock.h>
#include <bitsery/buffer_writer.h>
#include <bitsery/buffer_reader.h>
#include <bitsery/details/serialization_common.h>
#include <bitsery/ext/value_range.h>
using testing::Eq;
using testing::ContainerEq;
@@ -38,9 +38,8 @@ constexpr EndiannessType getInverseEndianness(EndiannessType e) {
: EndiannessType::LittleEndian;
}
struct InverseEndiannessConfig {
struct InverseEndiannessConfig:public DefaultConfig {
static constexpr bitsery::EndiannessType NetworkEndianness = getInverseEndianness(DefaultConfig::NetworkEndianness);
using BufferType = DefaultConfig::BufferType;
};
struct IntegralTypes {

View File

@@ -24,7 +24,7 @@
#include <gmock/gmock.h>
#include <bitsery/buffer_writer.h>
#include <bitsery/buffer_reader.h>
#include <bitsery/details/serialization_common.h>
#include <bitsery/ext/value_range.h>
using testing::Eq;
using testing::ContainerEq;

View File

@@ -31,13 +31,11 @@ using bitsery::EndiannessType;
using bitsery::DefaultConfig;
using Buffer = bitsery::DefaultConfig::BufferType;
struct FixedBufferConfig {
static constexpr bitsery::EndiannessType NetworkEndianness = DefaultConfig::NetworkEndianness;
struct FixedBufferConfig: public DefaultConfig {
using BufferType = std::array<uint8_t, 100>;
};
struct NonFixedBufferConfig {
static constexpr bitsery::EndiannessType NetworkEndianness = DefaultConfig::NetworkEndianness;
struct NonFixedBufferConfig: public DefaultConfig {
using BufferType = std::vector<uint8_t>;
};

View File

@@ -23,11 +23,12 @@
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <algorithm>
#include <numeric>
#include <deque>
#include <list>
#include "serialization_test_utils.h"
using testing::ContainerEq;
using testing::Eq;

View File

@@ -1,135 +0,0 @@
//MIT License
//
//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:
//
//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.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
using namespace testing;
TEST(SerializeEntropyEncoding, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits) {
int32_t v = 4849;
int32_t res;
constexpr size_t N = 3;
int32_t entropyValues[3]{485,4849,89};
SerializationContext ctx;
ctx.createSerializer().entropy<4>(v, entropyValues);
ctx.createDeserializer().entropy<4>(res, entropyValues);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
SerializationContext ctx1;
ctx1.createSerializer().entropy<4>(v, entropyValues);
auto des = ctx1.createDeserializer();
des.range(res, {0, N + 1});
EXPECT_THAT(res, Eq(2));
}
TEST(SerializeEntropyEncoding, WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrObject) {
int16_t v = 8945;
int16_t res;
int16_t entropyValues[3]{485,4849,89};
SerializationContext ctx;
ctx.createSerializer().entropy<2>(v, entropyValues);
ctx.createDeserializer().entropy<2>(res, entropyValues);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(sizeof(int16_t)+1));
}
TEST(SerializeEntropyEncoding, CustomTypeEntropyEncoded) {
MyStruct1 v = {12,10};
MyStruct1 res;
constexpr size_t N = 4;
MyStruct1 entropyValues[N]{
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
SerializationContext ctx;
ctx.createSerializer().entropy(v, entropyValues);
ctx.createDeserializer().entropy(res, entropyValues);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}
TEST(SerializeEntropyEncoding, CustomTypeNotEntropyEncoded) {
MyStruct1 v = {8945,4456};
MyStruct1 res;
constexpr size_t N = 4;
MyStruct1 entropyValues[N] {
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
SerializationContext ctx;
ctx.createSerializer().entropy(v, entropyValues);
ctx.createDeserializer().entropy(res, entropyValues);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1));
}
TEST(SerializeEntropyEncoding, CustomFunctionNotEntropyEncoded) {
MyStruct1 v = {8945,4456};
MyStruct1 res;
constexpr size_t N = 4;
MyStruct1 entropyValues[N] {
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
auto rangeForValue = bitsery::RangeSpec<int>(0, 10000);
auto rangeForIndex = bitsery::RangeSpec<size_t>{0, N+1};
SerializationContext ctx;
auto ser = ctx.createSerializer();
//lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind...
auto serLambda = [&ser, rangeForValue](MyStruct1& v) {
ser.range(v.i1, rangeForValue);
ser.range(v.i2, rangeForValue);
};
ser.entropy(v, entropyValues, serLambda);
auto des = ctx.createDeserializer();
auto desLambda = [&des, rangeForValue](MyStruct1& v) {
des.range(v.i1, rangeForValue);
des.range(v.i2, rangeForValue);
};
des.entropy(res, entropyValues, desLambda);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq((rangeForIndex.bitsRequired + rangeForValue.bitsRequired * 2 - 1) / 8 + 1 ));
}
TEST(SerializeEntropyEncoding, WhenEntropyEncodedThenCustomFunctionNotInvoked) {
MyStruct1 v = {4849,89};
MyStruct1 res;
constexpr size_t N = 4;
MyStruct1 entropyValues[N] {
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
SerializationContext ctx;
ctx.createSerializer().entropy(v, entropyValues, [](MyStruct1& ) {});
ctx.createDeserializer().entropy(res, entropyValues, []( MyStruct1& ) {});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}

View File

@@ -24,10 +24,11 @@
#include "serialization_test_utils.h"
#include <bitsery/ext/container_map.h>
#include <bitsery/ext/entropy.h>
#include <unordered_map>
#include <map>
using containerMap = bitsery::ext::containerMap;
using ContainerMap = bitsery::ext::ContainerMap;
using testing::Eq;
@@ -96,7 +97,7 @@ namespace bitsery {
template <typename S>
void serialize(S& s, std::unordered_map<std::string, MyStruct1>& o) {
s.extend(o, containerMap{}, [&s](std::string& key, MyStruct1& value) {
s.ext(o, ContainerMap{10}, [&s](std::string& key, MyStruct1& value) {
s.text1b(key, 100);
s.object(value);
});
@@ -104,7 +105,7 @@ namespace bitsery {
template <typename S>
void serialize(S& s, std::unordered_map<int32_t, float>& o) {
s.extend(o, containerMap{}, [&s](int32_t& key, float& value) {
s.ext(o, ContainerMap{10}, [&s](int32_t& key, float& value) {
s.value4b(key);
s.value4b(value);
});
@@ -112,7 +113,7 @@ namespace bitsery {
template <typename S>
void serialize(S& s, std::map<MyEnumClass , MyStruct1>& o) {
s.extend(o, containerMap{}, [&s](MyEnumClass& key, MyStruct1& value) {
s.ext(o, ContainerMap{10}, [&s](MyEnumClass& key, MyStruct1& value) {
s.value4b(key);
s.object(value);
});
@@ -120,10 +121,11 @@ namespace bitsery {
template <typename S>
void serialize(S& s, std::map<int32_t ,int64_t>& o) {
s.extend(o, containerMap{}, [&s](int32_t& key, int64_t& value) {
s.range(key, bitsery::RangeSpec<int32_t>{-100,100});
constexpr int64_t ev[3]{1ll, 2ll, 3ll};
s.entropy8b(value, ev);
s.ext(o, ContainerMap{10}, [&s](int32_t& key, int64_t& value) {
int64_t values[3]{1ll, 2ll, 3ll};
s.ext(key, bitsery::ext::ValueRange<int32_t>{-100,100});
s.ext8b(value, bitsery::ext::Entropy<int64_t[3]>{values});
});
}

View File

@@ -0,0 +1,143 @@
//MIT License
//
//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:
//
//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.
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <bitsery/ext/entropy.h>
#include <vector>
#include <list>
using namespace testing;
using bitsery::ext::Entropy;
TEST(SerializeExtensionEntropy, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits) {
int32_t v = 4849;
int32_t res;
constexpr size_t N = 3;
int32_t values[3] = {485,4849,89};
SerializationContext ctx;
ctx.createSerializer().ext4b(v, Entropy<int32_t[3]>{values});
ctx.createDeserializer().ext4b(res, Entropy<int32_t[3]>{values});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
SerializationContext ctx1;
ctx1.createSerializer().ext4b(v, Entropy<int32_t[3]>{values});
auto des = ctx1.createDeserializer();
des.ext(res, bitsery::ext::ValueRange<int32_t>{0, static_cast<int32_t>(N + 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().ext2b(v, Entropy<std::initializer_list<int>>{values});
ctx.createDeserializer().ext2b(res, Entropy<std::initializer_list<int>>{values});
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;
MyStruct1 values[N]{
MyStruct1{12, 10}, MyStruct1{485, 454},
MyStruct1{4849, 89}, MyStruct1{0, 1}};
SerializationContext ctx;
ctx.createSerializer().ext(v, Entropy<MyStruct1[N]>{values});
ctx.createDeserializer().ext(res, Entropy<MyStruct1[N]>{values});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}
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().ext(v, Entropy<std::initializer_list<MyStruct1>>{values});
ctx.createDeserializer().ext(res, Entropy<std::initializer_list<MyStruct1>>{values});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1));
}
TEST(SerializeExtensionEntropy, CustomFunctionNotEntropyEncoded) {
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}};
auto rangeForValue = bitsery::ext::ValueRange<int>{0, 10000};
auto rangeForIndex = bitsery::ext::ValueRange<size_t>{0u, N+1};
SerializationContext ctx;
auto ser = ctx.createSerializer();
//lambdas differ only in capture clauses, it would make sense to use std::bind, but debugger crashes when it sees std::bind...
auto serLambda = [&ser, &rangeForValue](MyStruct1& v) {
ser.ext(v.i1, rangeForValue);
ser.ext(v.i2, rangeForValue);
};
ser.ext(v, Entropy<std::vector<MyStruct1>>(values), serLambda);
auto des = ctx.createDeserializer();
auto desLambda = [&des, &rangeForValue](MyStruct1& v) {
des.ext(v.i1, rangeForValue);
des.ext(v.i2, rangeForValue);
};
des.ext(res, Entropy<std::vector<MyStruct1>>(values), desLambda);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq((rangeForIndex.getRequiredBits() + rangeForValue.getRequiredBits() * 2 - 1) / 8 + 1 ));
}
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}};
SerializationContext ctx;
ctx.createSerializer().ext(v, Entropy<std::list<MyStruct1>>{values}, [](MyStruct1& ) {});
ctx.createDeserializer().ext(res, Entropy<std::list<MyStruct1>>{values}, []( MyStruct1& ) {});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}

View File

@@ -22,9 +22,12 @@
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <bitsery/ext/growable.h>
using namespace testing;
using bitsery::ext::Growable;
using Buffer = typename bitsery::DefaultConfig::BufferType;
using DiffType = typename bitsery::details::BufferContainerTraits<Buffer>::TDifference;
@@ -44,16 +47,16 @@ struct DataV3 {
};
TEST(SerializeGrowable, WriteSessionsDataAtBufferEndAfterFlush) {
TEST(SerializeExtensionGrowable, WriteSessionsDataAtBufferEndAfterFlush) {
SerializationContext ctx;
ctx.createSerializer().growable(int8_t{}, [] (int8_t& v) { });
ctx.createSerializer().ext(int8_t{}, Growable{}, [] (int8_t& v) { });
EXPECT_THAT(ctx.getBufferSize(), Eq(0));
ctx.bw->flush();
EXPECT_THAT(ctx.getBufferSize(), Gt(0));
}
TEST(SerializeGrowable, SessionDataConsistOfSessionsEndPosAnd2BytesSessionsDataOffset) {
TEST(SerializeExtensionGrowable, SessionDataConsistOfSessionsEndPosAnd2BytesSessionsDataOffset) {
SerializationContext ctx;
@@ -61,7 +64,7 @@ TEST(SerializeGrowable, SessionDataConsistOfSessionsEndPosAnd2BytesSessionsDataO
int32_t data{};
auto ser = ctx.createSerializer();
ser.growable(data, [&ser](int32_t & v) { ser.value4b(v);});
ser.ext(data, Growable{}, [&ser](int32_t & v) { ser.value4b(v);});
ctx.createDeserializer();//to flush data and create buffer reader
EXPECT_THAT(ctx.getBufferSize(), Eq(3 + DATA_SIZE));
@@ -72,7 +75,7 @@ TEST(SerializeGrowable, SessionDataConsistOfSessionsEndPosAnd2BytesSessionsDataO
size_t sessionEnd{};
//there should start session data with first size of session
bitsery::details::readSize(br, sessionEnd);
bitsery::details::readSize(br, sessionEnd, 1000000u);
EXPECT_THAT(sessionEnd, Eq(DATA_SIZE));
//this is the the offset from the end of buffer where actual data ends
uint16_t sessionsOffset{};//bufferEnd - sessionsOffset = dataEnd
@@ -83,7 +86,7 @@ TEST(SerializeGrowable, SessionDataConsistOfSessionsEndPosAnd2BytesSessionsDataO
EXPECT_THAT(dSize, Eq(DATA_SIZE));
}
TEST(SerializeGrowable, WhenNestedSessionsThenStoreEachDepthAndSize) {
TEST(SerializeExtensionGrowable, WhenNestedSessionsThenStoreEachDepthAndSize) {
SerializationContext ctx;
DataV3 data{19457,846, 498418};
ctx.createSerializer();
@@ -107,15 +110,15 @@ TEST(SerializeGrowable, WhenNestedSessionsThenStoreEachDepthAndSize) {
EXPECT_THAT(res.v3, Eq(data.v3));
size_t sessionEnd[3];
//read sessions sizes
bitsery::details::readSize(*(ctx.br), sessionEnd[0]);
bitsery::details::readSize(*(ctx.br),sessionEnd[1]);
bitsery::details::readSize(*(ctx.br), sessionEnd[2]);
bitsery::details::readSize(*(ctx.br), sessionEnd[0],10000000u);
bitsery::details::readSize(*(ctx.br), sessionEnd[1],10000000u);
bitsery::details::readSize(*(ctx.br), sessionEnd[2],10000000u);
EXPECT_THAT(sessionEnd[0], Eq(12));
EXPECT_THAT(sessionEnd[1], Eq(8));
EXPECT_THAT(sessionEnd[2], Eq(12));
}
TEST(SerializeGrowable, WhenSessionsDataIsMoreThan0x7FFFThenWrite4BytesForSessionsOffset) {
TEST(SerializeExtensionGrowable, WhenSessionsDataIsMoreThan0x7FFFThenWrite4BytesForSessionsOffset) {
SerializationContext ctx;
ctx.createSerializer();
//create more sessions that can fit in 2 bytes
@@ -136,7 +139,7 @@ TEST(SerializeGrowable, WhenSessionsDataIsMoreThan0x7FFFThenWrite4BytesForSessio
EXPECT_THAT(ctx.br->getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
}
TEST(SerializeGrowable, MultipleSessionsReadSameVersionData) {
TEST(SerializeExtensionGrowable, MultipleSessionsReadSameVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
@@ -162,7 +165,7 @@ TEST(SerializeGrowable, MultipleSessionsReadSameVersionData) {
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleSessionsReadNewerVersionData) {
TEST(SerializeExtensionGrowable, MultipleSessionsReadNewerVersionData) {
SerializationContext ctx;
DataV3 data{8454,987451,54};
ctx.createSerializer();
@@ -189,7 +192,7 @@ TEST(SerializeGrowable, MultipleSessionsReadNewerVersionData) {
EXPECT_THAT(br.isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleSessionsReadOlderVersionData) {
TEST(SerializeExtensionGrowable, MultipleSessionsReadOlderVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
@@ -217,7 +220,7 @@ TEST(SerializeGrowable, MultipleSessionsReadOlderVersionData) {
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadSameVersionData) {
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadSameVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
@@ -253,7 +256,7 @@ TEST(SerializeGrowable, MultipleNestedSessionsReadSameVersionData) {
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadOlderVersionData) {
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadOlderVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
@@ -293,7 +296,7 @@ TEST(SerializeGrowable, MultipleNestedSessionsReadOlderVersionData) {
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadNewerVersionData1) {
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadNewerVersionData1) {
SerializationContext ctx;
DataV3 data{8454,987451,54};
ctx.createSerializer();
@@ -349,7 +352,7 @@ TEST(SerializeGrowable, MultipleNestedSessionsReadNewerVersionData1) {
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadNewerVersionData2) {
TEST(SerializeExtensionGrowable, MultipleNestedSessionsReadNewerVersionData2) {
SerializationContext ctx;
DataV3 data{8454,987451,54};
ctx.createSerializer();
@@ -411,3 +414,32 @@ TEST(SerializeGrowable, MultipleNestedSessionsReadNewerVersionData2) {
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeExtensionGrowable, SessionsStartsAtEndOfSerialization) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
auto& bw = (*ctx.bw);
for (auto i = 0; i < 100; ++i)
bw.writeBytes<4>(data.v1);
for (auto i = 0; i < 10; ++i) {
bw.beginSession();
bw.writeBytes<4>(data.v1);
bw.writeBytes<4>(data.v2);
bw.endSession();
}
//create more sessions that can fit in 2 bytes
ctx.createDeserializer();//to flush data and create buffer reader
DataV2 res{};
auto& br = (*ctx.br);
for (auto i = 0; i < 100; ++i)
br.readBytes<4>(res.v1);
for (auto i = 0; i < 10; ++i) {
br.beginSession();
br.readBytes<4>(res.v1);
br.readBytes<4>(res.v2);
br.endSession();
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
}
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}

View File

@@ -24,27 +24,25 @@
#include "serialization_test_utils.h"
#if __cplusplus > 201402L
# include<optional>
#else
# include <experimental/optional>
namespace std {
template <typename T>
using optional = experimental::optional<T>;
}
#endif
#include<optional>
#include <bitsery/ext/optional.h>
using extoptional = bitsery::ext::optional;
using Optional = bitsery::ext::Optional;
using testing::Eq;
template <typename T>
void test(SerializationContext& ctx, const T& v, T& r) {
ctx.createSerializer().extend4b(v, extoptional{});
ctx.createDeserializer().extend4b(r, extoptional{});
ctx.createSerializer().ext4b(v, Optional{});
ctx.createDeserializer().ext4b(r, Optional{});
}
TEST(SerializeExtensionOptional, EmptyOptional) {
@@ -80,3 +78,5 @@ TEST(SerializeExtensionOptional, OptionalHasValue) {
EXPECT_THAT(t1.value(), Eq(r1.value()));
}
#endif

View File

@@ -23,11 +23,15 @@
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <bitsery/ext/value_range.h>
using namespace testing;
using bitsery::RangeSpec;
using bitsery::BitsConstraint;
using bitsery::details::RangeSpec;
using bitsery::ext::BitsConstraint;
using bitsery::ext::ValueRange;
TEST(SerializeRange, RequiredBitsIsConstexpr) {
#if __cplusplus > 201402L
TEST(SerializeExtensionValueRange, RequiredBitsIsConstexpr) {
constexpr RangeSpec<int> r1{0, 31};
static_assert(r1.bitsRequired == 5, "r1.bitsRequired == 5");
@@ -43,123 +47,125 @@ TEST(SerializeRange, RequiredBitsIsConstexpr) {
}
TEST(SerializeRange, IntegerNegative) {
#endif
TEST(SerializeExtensionValueRange, IntegerNegative) {
SerializationContext ctx;
constexpr RangeSpec<int> r1{-50, 50};
ValueRange<int> r1{-50, 50};
int t1{-8};
int res1;
ctx.createSerializer().range(t1, r1);
ctx.createDeserializer().range(res1, r1);
ctx.createSerializer().ext(t1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
}
TEST(SerializeRange, IntegerPositive) {
TEST(SerializeExtensionValueRange, IntegerPositive) {
SerializationContext ctx;
constexpr RangeSpec<unsigned> r1{4, 10};
ValueRange<unsigned> r1{4u, 10u};
unsigned t1{8};
unsigned res1;
ctx.createSerializer().range(t1, r1);
ctx.createDeserializer().range(res1, r1);
ctx.createSerializer().ext(t1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
}
TEST(SerializeRange, EnumTypes) {
TEST(SerializeExtensionValueRange, EnumTypes) {
SerializationContext ctx;
constexpr RangeSpec<MyEnumClass> r1{MyEnumClass::E2, MyEnumClass::E4};
ValueRange<MyEnumClass> r1{MyEnumClass::E2, MyEnumClass::E4};
MyEnumClass t1{MyEnumClass::E2};
MyEnumClass res1;
ctx.createSerializer().range(t1, r1);
ctx.createDeserializer().range(res1, r1);
ctx.createSerializer().ext(t1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(t1));
}
TEST(SerializeRange, FloatUsingPrecisionConstraint1) {
TEST(SerializeExtensionValueRange, FloatUsingPrecisionConstraint1) {
SerializationContext ctx;
constexpr float precision{0.01f};
constexpr float min{-1.0f};
constexpr float max{1.0f};
float t1{0.5f};
constexpr RangeSpec<float> r1{min, max, precision};
ValueRange<float> r1{min, max, precision};
float res1;
ctx.createSerializer().range(t1, r1);
ctx.createDeserializer().range(res1, r1);
ctx.createSerializer().ext(t1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) * precision));
}
TEST(SerializeRange, DoubleUsingPrecisionConstraint2) {
TEST(SerializeExtensionValueRange, DoubleUsingPrecisionConstraint2) {
SerializationContext ctx;
constexpr double precision{0.000002};
constexpr double min{50.0};
constexpr double max{100000.0};
double t1{38741.0};
constexpr RangeSpec<double> r1{min, max, precision};
ValueRange<double> r1{min, max, precision};
double res1;
ctx.createSerializer().range(t1, r1);
ctx.createDeserializer().range(res1, r1);
ctx.createSerializer().ext(t1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(5));
EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) * precision));
}
TEST(SerializeRange, FloatUsingBitsSizeConstraint1) {
TEST(SerializeExtensionValueRange, FloatUsingBitsSizeConstraint1) {
SerializationContext ctx;
constexpr size_t bits = 8;
constexpr float min{-1.0f};
constexpr float max{1.0f};
float t1{0.5f};
constexpr RangeSpec<float> r1{min, max, BitsConstraint(bits)};
ValueRange<float> r1{min, max, BitsConstraint(bits)};
float res1;
ctx.createSerializer().range(t1, r1);
ctx.createDeserializer().range(res1, r1);
ctx.createSerializer().ext(t1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, ::testing::FloatNear(t1, (max - min) / (static_cast<bitsery::details::SAME_SIZE_UNSIGNED<float>>(1) << bits)));
}
TEST(SerializeRange, DoubleUsingBitsSizeConstraint2) {
TEST(SerializeExtensionValueRange, DoubleUsingBitsSizeConstraint2) {
SerializationContext ctx;
constexpr size_t bits = 50;
constexpr double min{50.0};
constexpr double max{100000.0};
double t1{38741};
constexpr RangeSpec<double> r1{min, max, BitsConstraint(bits)};
ValueRange<double> r1{min, max, BitsConstraint(bits)};
double res1;
ctx.createSerializer().range(t1, r1);
ctx.createDeserializer().range(res1, r1);
ctx.createSerializer().ext(t1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(7));
EXPECT_THAT(res1, ::testing::DoubleNear(t1, (max - min) / (static_cast<bitsery::details::SAME_SIZE_UNSIGNED<double>>(1) << bits)));
}
TEST(SerializeRange, WhenDataIsInvalidThenReturnMinimumRangeValue) {
TEST(SerializeExtensionValueRange, WhenDataIsInvalidThenReturnMinimumRangeValue) {
SerializationContext ctx;
constexpr RangeSpec<int> r1{4, 10};//6 is max, but 3bits required
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().value1b(tmp);
ctx.createDeserializer().range(res1, r1);
ctx.createDeserializer().ext(res1, r1);
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(4));