added -growable- function

This commit is contained in:
fraillt
2017-09-08 16:22:54 +03:00
parent cba80774e4
commit 2f8ae0075c
38 changed files with 1723 additions and 1264 deletions

View File

@@ -109,19 +109,24 @@ TEST(BufferBitsAndBytesOperations, BufferSizeIsCountedPerByteNotPerBit) {
//read from buffer
BufferReader br{range};
uint16_t tmp;
EXPECT_THAT(br.readBits(tmp,4), Eq(true));
EXPECT_THAT(br.readBits(tmp,2), Eq(true));
EXPECT_THAT(br.readBits(tmp,2), Eq(true));
EXPECT_THAT(br.readBits(tmp,2), Eq(false));
br.readBits(tmp,4);
br.readBits(tmp,2);
br.readBits(tmp,2);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
br.readBits(tmp,2);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
//part of next byte
BufferReader br1{range};
EXPECT_THAT(br1.readBits(tmp,2), Eq(true));
EXPECT_THAT(br1.readBits(tmp,7), Eq(false));
br1.readBits(tmp,2);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
br1.readBits(tmp,7);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
//bigger than byte
BufferReader br2{range};
EXPECT_THAT(br2.readBits(tmp,9), Eq(false));
br2.readBits(tmp,9);
EXPECT_THAT(br2.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));//false
}
TEST(BufferBitsAndBytesOperations, ConsecutiveCallsToAlignHasNoEffect) {
@@ -141,18 +146,20 @@ TEST(BufferBitsAndBytesOperations, ConsecutiveCallsToAlignHasNoEffect) {
unsigned char tmp;
BufferReader br{bw.getWrittenRange()};
EXPECT_THAT(br.readBits(tmp,2), Eq(true));
br.readBits(tmp,2);
EXPECT_THAT(tmp, Eq(3u));
EXPECT_THAT(br.align(), Eq(true));
EXPECT_THAT(br.readBits(tmp,3), Eq(true));
br.align();
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
br.readBits(tmp,3);
br.align();
br.align();
br.align();
EXPECT_THAT(tmp, Eq(7u));
EXPECT_THAT(br.align(), Eq(true));
EXPECT_THAT(br.align(), Eq(true));
EXPECT_THAT(br.align(), Eq(true));
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
EXPECT_THAT(br.readBits(tmp,4), Eq(true));
br.readBits(tmp,4);
EXPECT_THAT(tmp, Eq(15u));
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
}
TEST(BufferBitsAndBytesOperations, AlignWritesZerosBits) {
@@ -166,18 +173,20 @@ TEST(BufferBitsAndBytesOperations, AlignWritesZerosBits) {
bw.writeBits(3u, 2);
bw.align();
bw.flush();
auto range = bw.getWrittenRange();
EXPECT_THAT(std::distance(range.begin(), range.end()), Eq(1));
unsigned char tmp;
BufferReader br1{bw.getWrittenRange()};
BufferReader br1{range};
br1.readBits(tmp,2);
//read aligned bits
EXPECT_THAT(br1.readBits(tmp,6), Eq(true));
br1.readBits(tmp,6);
EXPECT_THAT(tmp, Eq(0));
BufferReader br2{bw.getWrittenRange()};
BufferReader br2{range};
//read 2 bits
br2.readBits(tmp,2);
EXPECT_THAT(br2.align(), Eq(true));
br2.align();
EXPECT_THAT(br2.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
}
@@ -219,12 +228,13 @@ TEST(BufferBitsAndBytesOperations, WriteAndReadBytes) {
//read from buffer
BufferReader br{range};
IntegralTypes res{};
EXPECT_THAT(br.readBytes<4>(res.b), Eq(true));
EXPECT_THAT(br.readBytes<2>(res.c), Eq(true));
EXPECT_THAT(br.readBytes<1>(res.d), Eq(true));
EXPECT_THAT(br.readBytes<8>(res.a), Eq(true));
EXPECT_THAT(br.readBytes<1>(res.e), Eq(true));
EXPECT_THAT(br.readBuffer<1>(res.f, 2), Eq(true));
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.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
//assert results
EXPECT_THAT(data.a, Eq(res.a));
@@ -248,13 +258,9 @@ TEST(BufferBitsAndBytesOperations, ReadWriteBufferFncCanAcceptSignedData) {
//read from buffer
BufferReader br1{bw.getWrittenRange()};
int16_t dst[DATA_SIZE]{};
EXPECT_THAT(br1.readBuffer<2>(dst, DATA_SIZE), Eq(true));
br1.readBuffer<2>(dst, DATA_SIZE);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
EXPECT_THAT(dst, ContainerEq(src));
//read more than available
BufferReader br2{bw.getWrittenRange()};
int16_t dstMore[DATA_SIZE+1]{};
EXPECT_THAT(br2.readBuffer<2>(dstMore, DATA_SIZE+1), Eq(false));
}
TEST(BufferBitsAndBytesOperations, ReadWriteBufferCanWorkOnUnalignedData) {
@@ -277,16 +283,37 @@ TEST(BufferBitsAndBytesOperations, ReadWriteBufferCanWorkOnUnalignedData) {
uint8_t tmp{};
br1.readBits(tmp, 4);
EXPECT_THAT(tmp, Eq(15));
EXPECT_THAT(br1.readBuffer<2>(dst, DATA_SIZE), Eq(true));
br1.readBuffer<2>(dst, DATA_SIZE);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
EXPECT_THAT(dst, ContainerEq(src));
br1.readBits(tmp, 4);
EXPECT_THAT(tmp, Eq(12));
//read more than available
BufferReader br2{range};
br2.readBits(tmp, 4);
int16_t dstMore[DATA_SIZE+1]{};
EXPECT_THAT(tmp, Eq(15));
EXPECT_THAT(br2.readBuffer<2>(dstMore, DATA_SIZE+1), Eq(false));
}
TEST(BufferBitsAndBytesOperations, RegressionTestReadBytesAfterReadBitsWithLotsOfZeroBits) {
//setup data
int16_t data[2]{0x0000, 0x7FFF};
int16_t res[2]{};
//create and write to buffer
Buffer buf{};
BufferWriter bw{buf};
bw.writeBits(2u, 2);
bw.writeBytes<2>(data[0]);
bw.writeBytes<2>(data[1]);
bw.align();
bw.flush();
auto range = bw.getWrittenRange();
//read from buffer
BufferReader br{range};
uint8_t tmp{};
br.readBits(tmp, 2);
EXPECT_THAT(tmp, Eq(2));
br.readBytes<2>(res[0]);
br.readBytes<2>(res[1]);
br.align();
EXPECT_THAT(res[0], Eq(data[0]));
EXPECT_THAT(res[1], Eq(data[1]));
}

View File

@@ -28,7 +28,6 @@
#include <bitset>
using testing::Eq;
using testing::ContainerEq;
using bitsery::BufferWriter;
using bitsery::BufferReader;
using Buffer = bitsery::DefaultConfig::BufferType;
@@ -42,7 +41,7 @@ struct IntegralTypes {
int8_t f[2];
};
TEST(BufferReading, ReadReturnsFalseIfNotEnoughBufferSize) {
TEST(BufferReading, WhenReadingMoreThanAvailableThenEmptyBufferError) {
//setup data
uint8_t a = 111;
@@ -56,19 +55,34 @@ TEST(BufferReading, ReadReturnsFalseIfNotEnoughBufferSize) {
bw.flush();
//read from buffer
BufferReader br{bw.getWrittenRange()};
int16_t b;
int32_t c;
EXPECT_THAT(br.readBytes<4>(c), Eq(false));
EXPECT_THAT(br.readBytes<2>(b), Eq(true));
EXPECT_THAT(br.readBytes<2>(b), Eq(false));
EXPECT_THAT(br.readBytes<1>(a), Eq(true));
EXPECT_THAT(br.readBytes<1>(a), Eq(false));
EXPECT_THAT(br.readBytes<2>(b), Eq(false));
EXPECT_THAT(br.readBytes<4>(c), Eq(false));
br.readBytes<4>(c);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
}
TEST(BufferReading, ReadIsCompletedWhenAllBytesAreRead) {
TEST(BufferReading, WhenErrorOccursThenAllOtherOperationsFailsForSameError) {
//setup data
uint8_t a = 111;
//create and write to buffer
Buffer buf{};
BufferWriter bw{buf};
bw.writeBytes<1>(a);
bw.writeBytes<1>(a);
bw.writeBytes<1>(a);
bw.flush();
//read from buffer
BufferReader br{bw.getWrittenRange()};
int32_t c;
br.readBytes<4>(c);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
br.readBytes<1>(a);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
}
TEST(BufferReading, ReadIsCompletedSuccessfullyWhenAllBytesAreReadWithoutErrors) {
//setup data
IntegralTypes data;
data.b = 94545646;
@@ -86,22 +100,59 @@ TEST(BufferReading, ReadIsCompletedWhenAllBytesAreRead) {
//read from buffer
BufferReader br{bw.getWrittenRange()};
IntegralTypes res;
EXPECT_THAT(br.readBytes<4>(res.b), Eq(true));
EXPECT_THAT(br.readBytes<2>(res.c), Eq(true));
EXPECT_THAT(br.isCompleted(), Eq(false));
EXPECT_THAT(br.readBytes<1>(res.d), Eq(true));
EXPECT_THAT(br.isCompleted(), Eq(true));
EXPECT_THAT(br.readBytes<1>(res.d), Eq(false));
EXPECT_THAT(br.isCompleted(), Eq(true));
br.readBytes<4>(res.b);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
br.readBytes<2>(res.c);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
EXPECT_THAT(br.isCompletedSuccessfully(), Eq(false));
br.readBytes<1>(res.d);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
EXPECT_THAT(br.isCompletedSuccessfully(), Eq(true));
br.readBytes<1>(res.d);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
EXPECT_THAT(br.isCompletedSuccessfully(), Eq(false));
BufferReader br1{bw.getWrittenRange()};
EXPECT_THAT(br1.readBytes<4>(res.b), Eq(true));
EXPECT_THAT(br1.readBytes<2>(res.c), Eq(true));
EXPECT_THAT(br1.isCompleted(), Eq(false));
EXPECT_THAT(br1.readBytes<2>(res.c), Eq(false));
EXPECT_THAT(br1.isCompleted(), Eq(false));
EXPECT_THAT(br1.readBytes<1>(res.d), Eq(true));
EXPECT_THAT(br1.isCompleted(), Eq(true));
br1.readBytes<4>(res.b);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
br1.readBytes<2>(res.c);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
EXPECT_THAT(br1.isCompletedSuccessfully(), Eq(false));
br1.readBytes<2>(res.c);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
EXPECT_THAT(br1.isCompletedSuccessfully(), Eq(false));
br1.readBytes<1>(res.d);
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
EXPECT_THAT(br1.isCompletedSuccessfully(), Eq(false));
}
TEST(BufferReading, WhenReaderHasErrorsAllOperationsReadsReturnZero) {
//setup data
uint8_t a = 111;
//create and write to buffer
Buffer buf{};
BufferWriter bw{buf};
bw.writeBytes<1>(a);
bw.writeBytes<1>(a);
bw.writeBytes<1>(a);
bw.flush();
//read from buffer
BufferReader br{bw.getWrittenRange()};
int32_t c;
br.readBytes<4>(c);
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
int16_t r1= {-645};
uint32_t r2[2] = {54898,87854};
uint8_t r3 = 0xFF;
br.readBytes<2>(r1);
br.readBuffer<4>(r2, 2);
br.readBits(r3, 7);
EXPECT_THAT(r1, Eq(0));
EXPECT_THAT(r2[0], Eq(0u));
EXPECT_THAT(r2[1], Eq(0u));
EXPECT_THAT(r3, Eq(0u));
}

View File

@@ -0,0 +1,119 @@
//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 testing::Eq;
using bitsery::BufferWriter;
using bitsery::BufferReader;
using Buffer = bitsery::DefaultConfig::BufferType;
TEST(BufferReadingErrors, WhenContainerOrTextSizeIsMoreThanMaxThenInvalidBufferDataError) {
SerializationContext ctx;
std::string tmp = "larger text then allowed";
ctx.createSerializer().text1b(tmp,100);
ctx.createDeserializer().text1b(tmp, 10);
EXPECT_THAT(ctx.br->getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
}
TEST(BufferReadingErrors, WhenReadingBoolByteReadsMoreThanOneThenInvalidBufferDataErrorAndResultIsFalse) {
SerializationContext ctx;
auto ser = ctx.createSerializer();
ser.value1b(uint8_t{1});
ser.value1b(uint8_t{2});
bool res{};
auto des = ctx.createDeserializer();
des.boolByte(res);
EXPECT_THAT(res, Eq(true));
des.boolByte(res);
EXPECT_THAT(res, Eq(false));
EXPECT_THAT(ctx.br->getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
}
TEST(BufferReadingErrors, WhenReadingAlignHasNonZerosThenInvalidBufferDataError) {
Buffer buf{};
BufferWriter bw{buf};
uint8_t tmp{0xFF};
bw.writeBytes<1>(tmp);
bw.flush();
BufferReader br{bw.getWrittenRange()};
br.readBits(tmp,3);
br.align();
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
}
TEST(BufferReadingErrors, WhenReadingNewSessionInMiddleOfOldDataThenInvalidBufferError) {
uint8_t tmp{0xFF};
Buffer buf{};
BufferWriter bw{buf};
for (auto i = 0; i < 2; ++i) {
bw.beginSession();
bw.writeBytes<1>(tmp);
bw.writeBytes<1>(tmp);
bw.endSession();
}
bw.flush();
BufferReader br{bw.getWrittenRange()};
for (auto i = 0; i < 2; ++i) {
br.beginSession();
br.readBytes<1>(tmp);
br.beginSession();
br.readBytes<1>(tmp);
br.endSession();
br.endSession();
}
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
}
TEST(BufferReadingErrors, WhenInitializingSessionsWhenNotEnoughDataThenInvalidBufferData) {
uint8_t tmp1{0xFF};
Buffer buf1{};
BufferWriter bw1{buf1};
bw1.writeBytes<1>(tmp1);
bw1.flush();
BufferReader br1{bw1.getWrittenRange()};
br1.beginSession();
EXPECT_THAT(br1.getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
Buffer buf2{};
BufferWriter bw2{buf2};
uint16_t tmp2{0x8000};
bw2.writeBytes<2>(tmp2);
bw2.flush();
BufferReader br2{bw2.getWrittenRange()};
br2.beginSession();
EXPECT_THAT(br2.getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
}
TEST(BufferReadingErrors, WhenInitializingSessionsWhereSessionsDataOffsetIsCorruptedThenInvalidBufferData) {
Buffer buf{};
BufferWriter bw{buf};
bw.writeBytes<1>(uint8_t{1});
bw.writeBytes<1>(uint8_t{1});
bw.writeBytes<2>(uint16_t{10});
BufferReader br{bw.getWrittenRange()};
br.beginSession();
EXPECT_THAT(br.getError(), Eq(bitsery::BufferReaderError::INVALID_BUFFER_DATA));
}

View File

@@ -81,9 +81,10 @@ TYPED_TEST(BufferWriting, GetWrittenRangeReturnsBeginEndIterators) {
}
TYPED_TEST(BufferWriting, WhenWritingBitsThenMustFlushWriter) {
Buffer buf;
bitsery::BufferWriter bw{buf};
using Config = typename TestFixture::type;
using Buffer = typename Config::BufferType;
Buffer buf{};
bitsery::BasicBufferWriter<Config> bw{buf};
bw.writeBits(3u, 2);
auto range1 = bw.getWrittenRange();
bw.flush();

View File

@@ -24,6 +24,7 @@
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <algorithm>
#include <numeric>
#include <deque>
#include <list>
@@ -36,29 +37,29 @@ using testing::Eq;
* overload to get container of types
*/
template <typename Container>
template<typename Container>
Container getFilledContainer() {
return {1,2,3,4,5,78,456,8,54};
return {1, 2, 3, 4, 5, 78, 456, 8, 54};
}
template <>
template<>
std::vector<MyStruct1> getFilledContainer<std::vector<MyStruct1>>() {
return {
{0,1},
{2,3},
{4,5},
{6,7},
{8,9},
{11,34},
{5134,1532}
{0, 1},
{2, 3},
{4, 5},
{6, 7},
{8, 9},
{11, 34},
{5134, 1532}
};
}
template <>
template<>
std::list<MyStruct2> getFilledContainer<std::list<MyStruct2>>() {
return {
{MyStruct2::V1, {0,1}} ,
{MyStruct2::V3, {-45,45}}
{MyStruct2::V1, {0, 1}},
{MyStruct2::V3, {-45, 45}}
};
}
@@ -66,16 +67,16 @@ std::list<MyStruct2> getFilledContainer<std::list<MyStruct2>>() {
* start testing session
*/
template <typename T>
class SerializeContainerArthmeticTypes:public testing::Test {
template<typename T>
class SerializeContainerDynamicSizeArthmeticTypes : public testing::Test {
public:
using TContainer = T;
using TValue = typename T::value_type;
const TContainer src= getFilledContainer<TContainer>() ;
const TContainer src = getFilledContainer<TContainer>();
TContainer res{};
size_t getExpectedBufSize(const SerializationContext& ctx) const {
size_t getExpectedBufSize(const SerializationContext &ctx) const {
return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * sizeof(TValue);
}
};
@@ -85,9 +86,9 @@ using SequenceContainersWithArthmeticTypes = ::testing::Types<
std::list<float>,
std::deque<unsigned short>>;
TYPED_TEST_CASE(SerializeContainerArthmeticTypes, SequenceContainersWithArthmeticTypes);
TYPED_TEST_CASE(SerializeContainerDynamicSizeArthmeticTypes, SequenceContainersWithArthmeticTypes);
TYPED_TEST(SerializeContainerArthmeticTypes, Values) {
TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, Values) {
SerializationContext ctx{};
using TValue = typename TestFixture::TValue;
@@ -98,7 +99,7 @@ TYPED_TEST(SerializeContainerArthmeticTypes, Values) {
EXPECT_THAT(this->res, ContainerEq(this->src));
}
TYPED_TEST(SerializeContainerArthmeticTypes, CustomFunctionIncrements) {
TYPED_TEST(SerializeContainerDynamicSizeArthmeticTypes, CustomFunctionIncrements) {
SerializationContext ctx{};
auto ser = ctx.createSerializer();
@@ -108,13 +109,13 @@ TYPED_TEST(SerializeContainerArthmeticTypes, CustomFunctionIncrements) {
s.template value<sizeof(v)>(v);
});
auto des = ctx.createDeserializer();
des.container(this->res, 1000, [](auto &s, auto&v ) {
des.container(this->res, 1000, [](auto &s, auto &v) {
s.template value<sizeof(v)>(v);
//increment by 1 after reading
v++;
});
//decrement result by 2, before comparing for eq
for(auto& v:this->res)
for (auto &v:this->res)
v -= 2;
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getExpectedBufSize(ctx)));
@@ -122,29 +123,28 @@ TYPED_TEST(SerializeContainerArthmeticTypes, CustomFunctionIncrements) {
}
template <typename T>
class SerializeContainerCompositeTypes:public testing::Test {
template<typename T>
class SerializeContainerDynamicSizeCompositeTypes : public testing::Test {
public:
using TContainer = T;
using TValue = typename T::value_type;
const TContainer src= getFilledContainer<TContainer>();
const TContainer src = getFilledContainer<TContainer>();
TContainer res{};
size_t getExpectedBufSize(const SerializationContext& ctx) const {
size_t getExpectedBufSize(const SerializationContext &ctx) const {
return ctx.containerSizeSerializedBytesCount(src.size()) + src.size() * TValue::SIZE;
}
};
using SequenceContainersWithCompositeTypes = ::testing::Types<
using SerializeContainerDynamicSizeWithCompositeTypes = ::testing::Types<
std::vector<MyStruct1>,
std::list<MyStruct2>>;
TYPED_TEST_CASE(SerializeContainerCompositeTypes, SequenceContainersWithCompositeTypes);
TYPED_TEST_CASE(SerializeContainerDynamicSizeCompositeTypes, SerializeContainerDynamicSizeWithCompositeTypes);
TYPED_TEST(SerializeContainerCompositeTypes, DefaultSerializeFunction) {
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, DefaultSerializeFunction) {
SerializationContext ctx{};
ctx.createSerializer().container(this->src, 1000);
@@ -155,15 +155,95 @@ TYPED_TEST(SerializeContainerCompositeTypes, DefaultSerializeFunction) {
}
TYPED_TEST(SerializeContainerCompositeTypes, CustomFunctionThatDoNothing) {
TYPED_TEST(SerializeContainerDynamicSizeCompositeTypes, CustomFunctionThatDoNothing) {
SerializationContext ctx{};
auto emptyFnc = [](auto& s, auto& v) {};
auto emptyFnc = [](auto &s, auto &v) {};
ctx.createSerializer().container(this->src, 1000, emptyFnc);
ctx.createDeserializer().container(this->res, 1000, emptyFnc);
EXPECT_THAT(ctx.getBufferSize(), Eq(ctx.containerSizeSerializedBytesCount(this->src.size())));
}
template<typename 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 StaticContainersWithIntegralTypes = ::testing::Types<
std::array<int16_t, 4>,
int16_t[4]>;
TYPED_TEST_CASE(SerializeContainerFixedSizeArithmeticTypes, StaticContainersWithIntegralTypes);
TYPED_TEST(SerializeContainerFixedSizeArithmeticTypes, ArithmeticValues) {
using Container = typename TestFixture::TContainer;
Container src{5, 9, 15, -459};
Container res{};
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));
}
template<typename T>
class SerializeContainerFixedSizeCompositeTypes : public SerializeContainerFixedSizeArithmeticTypes<T> {
};
using StaticContainersWithCompositeTypes = ::testing::Types<
std::array<MyStruct1, 4>,
MyStruct1[4]>;
TYPED_TEST_CASE(SerializeContainerFixedSizeCompositeTypes, StaticContainersWithCompositeTypes);
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));
}
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{};
SerializationContext ctx;
auto ser = ctx.createSerializer();
ser.container(src, [](auto &s, auto &v) {
char tmp{};
s.object(v);
s.value1b(tmp);
});
auto des = ctx.createDeserializer();
des.container(res, [](auto &s, auto &v) {
char tmp{};
s.object(v);
s.value1b(tmp);
});
EXPECT_THAT(ctx.getBufferSize(), Eq(this->getContainerSize() * (MyStruct1::SIZE + sizeof(char))));
EXPECT_THAT(res, ContainerEq(src));
}

View File

@@ -25,72 +25,72 @@
#include "serialization_test_utils.h"
using namespace testing;
TEST(SerializeSubstitution, WhenSubstitutedThenOnlyWriteIndexUsingMinRequiredBits) {
TEST(SerializeEntropyEncoding, WhenEntropyEncodedThenOnlyWriteIndexUsingMinRequiredBits) {
int32_t v = 4849;
int32_t res;
constexpr size_t N = 3;
std::array<int32_t,N> subsitution{485,4849,89};
int32_t entropyValues[3]{485,4849,89};
SerializationContext ctx;
ctx.createSerializer().substitution<4>(v, subsitution);
ctx.createDeserializer().substitution<4>(res, subsitution);
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().substitution<4>(v, subsitution);
ctx1.createSerializer().entropy<4>(v, entropyValues);
auto des = ctx1.createDeserializer();
des.range(res, {0, N + 1});
EXPECT_THAT(res, Eq(2));
}
TEST(SerializeSubstitution, WhenNoSubstitutionThenWriteZeroBitsAndValueOrObject) {
TEST(SerializeEntropyEncoding, WhenNoEntropyEncodedThenWriteZeroBitsAndValueOrObject) {
int16_t v = 8945;
int16_t res;
std::array<int16_t,3> subsitution{485,4849,89};
int16_t entropyValues[3]{485,4849,89};
SerializationContext ctx;
ctx.createSerializer().substitution<2>(v, subsitution);
ctx.createDeserializer().substitution<2>(res, subsitution);
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(SerializeSubstitution, CustomTypeSubstituted) {
TEST(SerializeEntropyEncoding, CustomTypeEntropyEncoded) {
MyStruct1 v = {12,10};
MyStruct1 res;
constexpr size_t N = 4;
std::array<MyStruct1, N> subsitution = {
MyStruct1 entropyValues[N]{
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
SerializationContext ctx;
ctx.createSerializer().substitution(v, subsitution);
ctx.createDeserializer().substitution(res, subsitution);
ctx.createSerializer().entropy(v, entropyValues);
ctx.createDeserializer().entropy(res, entropyValues);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
}
TEST(SerializeSubstitution, CustomTypeNotSubstituted) {
TEST(SerializeEntropyEncoding, CustomTypeNotEntropyEncoded) {
MyStruct1 v = {8945,4456};
MyStruct1 res;
constexpr size_t N = 4;
std::array<MyStruct1, N> subsitution = {
MyStruct1 entropyValues[N] {
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
SerializationContext ctx;
ctx.createSerializer().substitution(v, subsitution);
ctx.createDeserializer().substitution(res, subsitution);
ctx.createSerializer().entropy(v, entropyValues);
ctx.createDeserializer().entropy(res, entropyValues);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(MyStruct1::SIZE + 1));
}
TEST(SerializeSubstitution, CustomFunctionNotSubstituted) {
TEST(SerializeEntropyEncoding, CustomFunctionNotEntropyEncoded) {
MyStruct1 v = {8945,4456};
MyStruct1 res;
constexpr size_t N = 4;
std::array<MyStruct1, N> subsitution = {
MyStruct1 entropyValues[N] {
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
@@ -105,30 +105,30 @@ TEST(SerializeSubstitution, CustomFunctionNotSubstituted) {
s.range(v.i1, rangeForValue);
s.range(v.i2, rangeForValue);
};
ser.substitution(v, subsitution, serLambda);
ser.entropy(v, entropyValues, serLambda);
auto des = ctx.createDeserializer();
auto desLambda = [rangeForValue](auto& s, MyStruct1& v) {
s.range(v.i1, rangeForValue);
s.range(v.i2, rangeForValue);
};
des.substitution(res, subsitution, desLambda);
des.entropy(res, entropyValues, desLambda);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq((rangeForIndex.bitsRequired + rangeForValue.bitsRequired * 2 - 1) / 8 + 1 ));
}
TEST(SerializeSubstitution, WhenSubstitutedThenCustomFunctionNotInvoked) {
TEST(SerializeEntropyEncoding, WhenEntropyEncodedThenCustomFunctionNotInvoked) {
MyStruct1 v = {4849,89};
MyStruct1 res;
constexpr size_t N = 4;
std::array<MyStruct1, N> subsitution = {
MyStruct1 entropyValues[N] {
MyStruct1{12,10}, MyStruct1{485, 454},
MyStruct1{4849,89}, MyStruct1{0,1}};
SerializationContext ctx;
ctx.createSerializer().substitution(v, subsitution, [](bitsery::Serializer<bitsery::BufferWriter>& ,const MyStruct1& ) {});
ctx.createDeserializer().substitution(res, subsitution, [](bitsery::Deserializer<bitsery::BufferReader>&, MyStruct1& ) {});
ctx.createSerializer().entropy(v, entropyValues, [](bitsery::Serializer<bitsery::BufferWriter>& ,const MyStruct1& ) {});
ctx.createDeserializer().entropy(res, entropyValues, [](bitsery::Deserializer<bitsery::BufferReader>&, MyStruct1& ) {});
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(ctx.getBufferSize(), Eq(1));

View File

@@ -43,8 +43,8 @@ using testing::Eq;
template <typename T>
void test(SerializationContext& ctx, const T& v, T& r) {
ctx.createSerializer().extension4(v, extoptional{});
ctx.createDeserializer().extension4(r, extoptional{});
ctx.createSerializer().extend4b(v, extoptional{});
ctx.createDeserializer().extend4b(r, extoptional{});
}
TEST(SerializeExtensionOptional, EmptyOptional) {

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"
#include <type_traits>
using testing::ContainerEq;
using testing::Eq;
TEST(SerializeFSArrayStdArray, ArithmeticValues) {
SerializationContext ctx;
std::array<int, 4> src{5,9,15,-459};
std::array<int, 4> res{};
ctx.createSerializer().array<sizeof(int)>(src);
ctx.createDeserializer().array<sizeof(int)>(res);
EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * sizeof(int)));
EXPECT_THAT(res, ContainerEq(src));
}
TEST(SerializeFSArrayStdArray, CompositeTypes) {
SerializationContext ctx;
std::array<MyStruct1, 7> src{
MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7},
MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}};
std::array<MyStruct1, 7> res{};
ctx.createSerializer().array(src);
ctx.createDeserializer().array(res);
EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * MyStruct1::SIZE));
EXPECT_THAT(res, ContainerEq(src));
}
//
//
TEST(SerializeFSArrayStdArray, CustomFunctionThatSerializesAnEmptyByteEveryElement) {
SerializationContext ctx;
std::array<MyStruct1, 7> src{
MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7},
MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}};
std::array<MyStruct1, 7> res{};
auto ser = ctx.createSerializer();
ser.array(src, [](auto &s, auto& v) {
char tmp{};
s.object(v);
s.value1(tmp);
});
auto des = ctx.createDeserializer();
des.array(res, [](auto &s, auto& v) {
char tmp{};
s.object(v);
s.value1(tmp);
});
EXPECT_THAT(ctx.getBufferSize(), Eq(src.size() * (MyStruct1::SIZE + sizeof(char))));
EXPECT_THAT(res, ContainerEq(src));
}
TEST(SerializeFSArrayCArray, ArithmeticValuesSettingValueSizeExplicitly) {
SerializationContext ctx;
int src[4]{5,9,15,-459};
int res[4]{};
ctx.createSerializer().array<sizeof(int)>(src);
ctx.createDeserializer().array<sizeof(int)>(res);
EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent<decltype(src)>::value * sizeof(int)));
EXPECT_THAT(res, ContainerEq(src));
}
TEST(SerializeFSArrayCArray, CompositeTypes) {
SerializationContext ctx;
MyStruct1 src[]{
MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7},
MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}};
MyStruct1 res[7]{};
ctx.createSerializer().array(src);
ctx.createDeserializer().array(res);
EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent<decltype(src)>::value * MyStruct1::SIZE));
EXPECT_THAT(res, ContainerEq(src));
}
//
//
TEST(SerializeFSArrayCArray, CustomFunctionThatSerializesAnEmptyByteEveryElement) {
SerializationContext ctx;
MyStruct1 src[]{
MyStruct1{0,1}, MyStruct1{2,3}, MyStruct1{4,5}, MyStruct1{6,7},
MyStruct1{8,9}, MyStruct1{11,34}, MyStruct1{5134,1532}};
MyStruct1 res[7]{};
auto ser = ctx.createSerializer();
ser.array(src, [](auto& s, auto& v) {
char tmp{};
s.object(v);
s.value1(tmp);
});
auto des = ctx.createDeserializer();
des.array(res, [](auto& s, auto& v) {
char tmp{};
s.object(v);
s.value1(tmp);
});
EXPECT_THAT(ctx.getBufferSize(), Eq(std::extent<decltype(src)>::value * (MyStruct1::SIZE + sizeof(char))));
EXPECT_THAT(res, ContainerEq(src));
}

View File

@@ -0,0 +1,412 @@
//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;
using Buffer = typename bitsery::DefaultConfig::BufferType;
using DiffType = typename Buffer::difference_type;
struct DataV1 {
int32_t v1;
};
struct DataV2 {
int32_t v1;
int32_t v2;
};
struct DataV3 {
int32_t v1;
int32_t v2;
int32_t v3;
};
TEST(SerializeGrowable, WriteSessionsDataAtBufferEndAfterFlush) {
SerializationContext ctx;
ctx.createSerializer().growable(int8_t{}, [] (auto& s, auto& v) { });
EXPECT_THAT(ctx.getBufferSize(), Eq(0));
ctx.bw->flush();
EXPECT_THAT(ctx.getBufferSize(), Gt(0));
}
TEST(SerializeGrowable, SessionDataConsistOfSessionsEndPosAnd2BytesSessionsDataOffset) {
SerializationContext ctx;
constexpr size_t DATA_SIZE = 4;
int32_t data{};
ctx.createSerializer().growable(data, [](auto&s, auto& v) { s.value4b(v);});
ctx.createDeserializer();//to flush data and create buffer reader
EXPECT_THAT(ctx.getBufferSize(), Eq(3 + DATA_SIZE));
//read value back
auto& br = *(ctx.br);
br.readBytes<DATA_SIZE>(data);
size_t sessionEnd{};
//there should start session data with first size of session
bitsery::details::readSize(br, sessionEnd);
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
br.readBytes<2>(sessionsOffset);
EXPECT_THAT(sessionsOffset, Eq(1+2));//1byte for session info, 2 bytes for session offset variable
auto range = ctx.bw->getWrittenRange();
auto dSize = std::distance(range.begin(), std::next(range.end(), -sessionsOffset));
EXPECT_THAT(dSize, Eq(DATA_SIZE));
}
TEST(SerializeGrowable, WhenNestedSessionsThenStoreEachDepthAndSize) {
SerializationContext ctx;
DataV3 data{19457,846, 498418};
ctx.createSerializer();
ctx.bw->beginSession();
ctx.bw->writeBytes<4>(data.v1);
ctx.bw->beginSession();
ctx.bw->writeBytes<4>(data.v2);
ctx.bw->endSession();
ctx.bw->beginSession();
ctx.bw->writeBytes<4>(data.v3);
ctx.bw->endSession();
ctx.bw->endSession();
DataV3 res{};
ctx.createDeserializer();//to flush data and create buffer reader
ctx.br->readBytes<4>(res.v1);
ctx.br->readBytes<4>(res.v2);
ctx.br->readBytes<4>(res.v3);
//read data correctly
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
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]);
EXPECT_THAT(sessionEnd[0], Eq(12));
EXPECT_THAT(sessionEnd[1], Eq(8));
EXPECT_THAT(sessionEnd[2], Eq(12));
}
TEST(SerializeGrowable, WhenSessionsDataIsMoreThan0x7FFFThenWrite4BytesForSessionsOffset) {
SerializationContext ctx;
ctx.createSerializer();
//create more sessions that can fit in 2 bytes
for (auto i = 0u; i < 0x8000; ++i) {
ctx.bw->beginSession();
ctx.bw->endSession();
}
ctx.createDeserializer();//to flush data and create buffer reader
EXPECT_THAT(ctx.getBufferSize(), Eq(0x8000+4));
uint8_t tmp{};
for (auto i = 0u; i < 0x8000; ++i) {
ctx.br->beginSession();
ctx.br->endSession();
}
EXPECT_THAT(ctx.br->getError(), Eq(bitsery::BufferReaderError::NO_ERROR));
ctx.br->readBytes<1>(tmp);
EXPECT_THAT(ctx.br->getError(), Eq(bitsery::BufferReaderError::BUFFER_OVERFLOW));
}
TEST(SerializeGrowable, MultipleSessionsReadSameVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
auto& bw = (*ctx.bw);
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 < 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));
}
TEST(SerializeGrowable, MultipleSessionsReadNewerVersionData) {
SerializationContext ctx;
DataV3 data{8454,987451,54};
ctx.createSerializer();
auto& bw = (*ctx.bw);
for (auto i = 0; i < 10; ++i) {
bw.beginSession();
bw.writeBytes<4>(data.v1);
bw.writeBytes<4>(data.v2);
bw.writeBytes<4>(data.v3);
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 < 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(br.isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleSessionsReadOlderVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
auto& bw = (*ctx.bw);
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
DataV3 res{4798,657891,985};
auto& br = (*ctx.br);
for (auto i = 0; i < 10; ++i) {
br.beginSession();
br.readBytes<4>(res.v1);
br.readBytes<4>(res.v2);
br.readBytes<4>(res.v3);
br.endSession();
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
EXPECT_THAT(res.v3, Eq(0));
}
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadSameVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
auto& bw = (*ctx.bw);
for (auto i = 0; i < 2; ++i) {
bw.beginSession();
bw.writeBytes<4>(data.v1);
bw.writeBytes<4>(data.v2);
bw.beginSession();
bw.writeBytes<4>(data.v1);
bw.writeBytes<4>(data.v2);
bw.endSession();
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 < 2; ++i) {
br.beginSession();
br.readBytes<4>(res.v1);
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
br.beginSession();
br.readBytes<4>(res.v1);
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
br.endSession();
br.endSession();
}
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadOlderVersionData) {
SerializationContext ctx;
DataV2 data{8454,987451};
ctx.createSerializer();
auto& bw = (*ctx.bw);
for (auto i = 0; i < 5; ++i) {
bw.beginSession();
bw.writeBytes<4>(data.v1);
bw.endSession();
bw.writeBytes<4>(data.v2);
}
//create more sessions that can fit in 2 bytes
ctx.createDeserializer();//to flush data and create buffer reader
DataV3 res{};
auto& br = (*ctx.br);
for (auto i = 0; i < 5; ++i) {
br.beginSession();
br.readBytes<4>(res.v1);
EXPECT_THAT(res.v1, Eq(data.v1));
//new flow
br.beginSession();
br.readBytes<4>(res.v3);
EXPECT_THAT(res.v3, Eq(0));
br.beginSession();
br.readBytes<4>(res.v3);
EXPECT_THAT(res.v3, Eq(0));
br.endSession();
br.endSession();
br.beginSession();
br.readBytes<4>(res.v3);
EXPECT_THAT(res.v3, Eq(0));
br.endSession();
br.endSession();
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v2, Eq(data.v2));
}
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadNewerVersionData1) {
SerializationContext ctx;
DataV3 data{8454,987451,54};
ctx.createSerializer();
auto& bw = (*ctx.bw);
for (auto i = 0; i < 2; ++i) {
bw.beginSession();
{
bw.writeBytes<4>(data.v1);
bw.writeBytes<4>(data.v2);
//new flow
bw.beginSession();
{
bw.writeBytes<4>(data.v3);
}
bw.endSession();
bw.beginSession();
{
bw.writeBytes<4>(data.v3);
bw.beginSession();
{
bw.beginSession();
{
bw.writeBytes<4>(data.v3);
bw.writeBytes<4>(data.v3);
}
bw.endSession();
bw.writeBytes<4>(data.v3);
}
bw.endSession();
}
bw.endSession();
bw.writeBytes<4>(data.v3);
}
bw.endSession();
bw.writeBytes<4>(data.v2);
}
//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 < 2; ++i) {
br.beginSession();
{
br.readBytes<4>(res.v1);
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
}
br.endSession();
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v2, Eq(data.v2));
}
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}
TEST(SerializeGrowable, MultipleNestedSessionsReadNewerVersionData2) {
SerializationContext ctx;
DataV3 data{8454,987451,54};
ctx.createSerializer();
auto& bw = (*ctx.bw);
for (auto i = 0; i < 2; ++i) {
bw.beginSession();
bw.writeBytes<4>(data.v1);
bw.writeBytes<4>(data.v2);
bw.beginSession();
bw.writeBytes<4>(data.v1);
bw.writeBytes<4>(data.v2);
//new flow
bw.beginSession();
bw.writeBytes<4>(data.v3);
bw.endSession();
bw.beginSession();
bw.writeBytes<4>(data.v3);
bw.beginSession();
bw.beginSession();
bw.writeBytes<4>(data.v3);
bw.writeBytes<4>(data.v3);
bw.endSession();
bw.writeBytes<4>(data.v3);
bw.endSession();
bw.endSession();
bw.writeBytes<4>(data.v3);
bw.endSession();
bw.writeBytes<4>(data.v2);
//new flow
bw.writeBytes<4>(data.v3);
bw.beginSession();
bw.writeBytes<4>(data.v3);
bw.endSession();
bw.writeBytes<4>(data.v3);
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 < 2; ++i) {
br.beginSession();
br.readBytes<4>(res.v1);
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
br.beginSession();
br.readBytes<4>(res.v1);
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v1, Eq(data.v1));
EXPECT_THAT(res.v2, Eq(data.v2));
br.endSession();
br.readBytes<4>(res.v2);
EXPECT_THAT(res.v2, Eq(data.v2));
br.endSession();
}
EXPECT_THAT(ctx.br->isCompletedSuccessfully(), Eq(true));
}

View File

@@ -24,13 +24,6 @@
#include <gmock/gmock.h>
#include "serialization_test_utils.h"
#include <bitsery/delta_serializer.h>
#include <bitsery/delta_deserializer.h>
#include <list>
using testing::Eq;
using testing::StrEq;
using testing::ContainerEq;
@@ -73,8 +66,8 @@ SERIALIZE(Y)
auto writeInt = [](auto& s, auto& v) { s.template value<sizeof(v)>(v); };
s.template text<1>(o.s, 10000);
s.template value<sizeof(o.y)>(o.y);
s.array(o.arr, writeInt);
s.array(o.carr, writeInt);
s.container(o.arr, writeInt);
s.container(o.carr, writeInt);
s.container(o.vx, 10000, [](auto& s, auto& v) { s.object(v); });
}
@@ -126,49 +119,4 @@ TEST(SerializeObject, GeneralConceptTest) {
EXPECT_THAT(zres.x.s, StrEq(z.x.s));
EXPECT_THAT(zres.x.x, Eq(z.x.x));
}
TEST(DeltaSerializer, GeneralConceptTest) {
//std::string buf;
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";
y.vx[0].s = "very nice";
y.vx[1].s = "very nice string, that is a little bit longer that previous";
Y yRead = y;
Y yNew = y;
yNew.y = 111111;
yNew.arr[2] = 0xFFFFFFFF;
yNew.carr[1] = 0xFFFFFFFF;
yNew.s = "labas dienaABC";
yNew.vx[0].s = "very opapa";
yNew.vx[1].s = "bla";
yNew.vx.push_back(X{ 3 });
bitsery::DefaultConfig::BufferType buf;
bitsery::BufferWriter bw{ buf };
bitsery::DeltaSerializer<bitsery::BufferWriter, Y> ser(bw, y, yNew);
serialize(ser, yNew);
bw.flush();
bitsery::BufferReader br{ bw.getWrittenRange() };
bitsery::DeltaDeserializer<bitsery::BufferReader, Y> des(br, y, yRead);
serialize(des, yRead);
EXPECT_THAT(yRead.y, Eq(yNew.y));
EXPECT_THAT(yRead.vx, ContainerEq(yNew.vx));
EXPECT_THAT(yRead.arr, ContainerEq(yNew.arr));
EXPECT_THAT(yRead.carr, ContainerEq(yNew.carr));
EXPECT_THAT(yRead.s, StrEq(yNew.s));
}
}

View File

@@ -152,3 +152,15 @@ TEST(SerializeRange, DoubleUsingBitsSizeConstraint2) {
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) {
SerializationContext ctx;
constexpr RangeSpec<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);
EXPECT_THAT(ctx.getBufferSize(), Eq(1));
EXPECT_THAT(res1, Eq(4));
}

View File

@@ -21,8 +21,8 @@
//SOFTWARE.
#ifndef BITSERY_SERIALIZERTESTS_H
#define BITSERY_SERIALIZERTESTS_H
#ifndef BITSERY_SERIALIZER_TEST_UTILS_H
#define BITSERY_SERIALIZER_TEST_UTILS_H
#include <bitsery/bitsery.h>
#include <memory>
@@ -82,10 +82,11 @@ SERIALIZE(MyStruct2) {
class SerializationContext {
public:
bitsery::DefaultConfig::BufferType buf{};
std::unique_ptr<bitsery::BufferWriter> bw;
std::unique_ptr<bitsery::BufferReader> br;
public:
bitsery::Serializer<bitsery::BufferWriter> createSerializer() {
bw = std::make_unique<bitsery::BufferWriter>(buf);
return {*bw};
@@ -113,4 +114,4 @@ public:
};
};
#endif //BITSERY_SERIALIZERTESTS_H
#endif //BITSERY_SERIALIZER_TEST_UTILS_H

View File

@@ -65,8 +65,8 @@ TEST(SerializeValues, ValueSizeOverload1Byte) {
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value1(v);
ctx.createDeserializer().value1(res);
ctx.createSerializer().value1b(v);
ctx.createDeserializer().value1b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
@@ -78,8 +78,8 @@ TEST(SerializeValues, ValueSizeOverload2Byte) {
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value2(v);
ctx.createDeserializer().value2(res);
ctx.createSerializer().value2b(v);
ctx.createDeserializer().value2b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
@@ -91,8 +91,8 @@ TEST(SerializeValues, ValueSizeOverload4Byte) {
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value4(v);
ctx.createDeserializer().value4(res);
ctx.createSerializer().value4b(v);
ctx.createDeserializer().value4b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));
@@ -104,8 +104,8 @@ TEST(SerializeValues, ValueSizeOverload8Byte) {
constexpr size_t TSIZE = sizeof(v);
SerializationContext ctx;
ctx.createSerializer().value8(v);
ctx.createDeserializer().value8(res);
ctx.createSerializer().value8b(v);
ctx.createDeserializer().value8b(res);
EXPECT_THAT(res, Eq(v));
EXPECT_THAT(TSIZE, Eq(ctx.getBufferSize()));