5#include <c++utilities/conversion/stringbuilder.h>
6#include <c++utilities/conversion/stringconversion.h>
7#include <c++utilities/io/misc.h>
8#include <c++utilities/tests/testutils.h>
10using CppUtilities::operator<<;
11#include <cppunit/TestFixture.h>
12#include <cppunit/extensions/HelperMacros.h>
21#include <unordered_map>
25using namespace CPPUNIT_NS;
26using namespace CppUtilities;
27using namespace CppUtilities::Literals;
39enum class SomeEnumClassBinary : std::uint16_t {
51 map<string, int> someMap;
52 unordered_map<string, bool> someHash;
54 multiset<string> someMultiset;
55 unordered_set<string> someUnorderedSet;
56 unordered_multiset<string> someUnorderedMultiset;
57 SomeEnumBinary someEnum;
58 SomeEnumClassBinary someEnumClass;
65 vector<TestObjectBinary> testObjects;
69 variant<int, string, monostate> someVariant;
70 variant<string, float> anotherVariant;
71 variant<string, int> yetAnotherVariant;
76namespace BinaryReflector {
80 CPP_UTILITIES_UNUSED(version)
81 deserializer.read(customType.number);
82 deserializer.read(customType.number2);
83 deserializer.read(customType.numbers);
84 deserializer.read(customType.text);
85 deserializer.read(customType.boolean);
86 deserializer.read(customType.someMap);
87 deserializer.read(customType.someHash);
88 deserializer.read(customType.someSet);
89 deserializer.read(customType.someMultiset);
90 deserializer.read(customType.someUnorderedSet);
91 deserializer.read(customType.someUnorderedMultiset);
92 deserializer.read(customType.someEnum);
93 deserializer.read(customType.someEnumClass);
94 deserializer.read(customType.timeSpan);
95 deserializer.read(customType.dateTime);
101 CPP_UTILITIES_UNUSED(version)
102 serializer.write(customType.number);
103 serializer.write(customType.number2);
104 serializer.write(customType.numbers);
105 serializer.write(customType.text);
106 serializer.write(customType.boolean);
107 serializer.write(customType.someMap);
108 serializer.write(customType.someHash);
109 serializer.write(customType.someSet);
110 serializer.write(customType.someMultiset);
111 serializer.write(customType.someUnorderedSet);
112 serializer.write(customType.someUnorderedMultiset);
113 serializer.write(customType.someEnum);
114 serializer.write(customType.someEnumClass);
115 serializer.write(customType.timeSpan);
116 serializer.write(customType.dateTime);
121 CPP_UTILITIES_UNUSED(version)
122 deserializer.read(customType.name);
123 deserializer.read(customType.testObjects);
129 CPP_UTILITIES_UNUSED(version)
130 serializer.write(customType.name);
131 serializer.write(customType.testObjects);
137 CPP_UTILITIES_UNUSED(version)
138 deserializer.read(customType.someVariant);
139 deserializer.read(customType.anotherVariant);
140 deserializer.read(customType.yetAnotherVariant);
147 CPP_UTILITIES_UNUSED(version)
148 serializer.write(customType.someVariant);
149 serializer.write(customType.anotherVariant);
150 serializer.write(customType.yetAnotherVariant);
174 CPPUNIT_TEST_SUITE_END();
179 void setUp()
override;
194 vector<unsigned char> m_buffer;
195 TestObjectBinary m_testObj;
196 NestingArrayBinary m_nestedTestObj;
197 vector<unsigned char> m_expectedTestObj;
198 vector<unsigned char> m_expectedNestedTestObj;
208 , m_expectedTestObj({
209 0x00, 0x00, 0x00, 0x05,
210 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x01,
213 0x00, 0x00, 0x00, 0x02,
214 0x00, 0x00, 0x00, 0x03,
215 0x00, 0x00, 0x00, 0x04,
216 0x00, 0x00, 0x00, 0x05,
218 0x73, 0x6F, 0x6D, 0x65, 0x20, 0x74, 0x65, 0x78, 0x74,
221 0x83, 0x62, 0x61, 0x72, 0x00, 0x00, 0x00, 0x13,
222 0x83, 0x66, 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x11,
235 0x00, 0x00, 0x00, 0x01,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xCD,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xAB,
240 , m_expectedNestedTestObj({
241 0x93, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67,
250 m_testObj.number = 5;
251 m_testObj.number2 = 2.5;
252 m_testObj.numbers = { 1, 2, 3, 4, 5 };
253 m_testObj.text =
"some text";
254 m_testObj.boolean =
true;
255 m_testObj.someMap = {
259 m_testObj.someSet = {
"1",
"2",
"3",
"2" };
260 m_testObj.someMultiset = {
"1",
"2",
"3",
"2" };
261 m_testObj.someEnum = SomeEnumItem2;
262 m_testObj.someEnumClass = SomeEnumClassBinary::Item3;
263 m_testObj.timeSpan = TimeSpan(0xABCD);
264 m_testObj.dateTime = DateTime(0xEFAB);
265 m_nestedTestObj.name =
"struct with nesting";
266 m_expectedNestedTestObj.reserve(m_expectedNestedTestObj.size() + 2 * m_expectedTestObj.size());
267 m_expectedNestedTestObj.insert(m_expectedNestedTestObj.end(), m_expectedTestObj.cbegin(), m_expectedTestObj.cend());
268 m_expectedNestedTestObj.insert(m_expectedNestedTestObj.end(), m_expectedTestObj.cbegin(), m_expectedTestObj.cend());
269 m_nestedTestObj.testObjects.insert(m_nestedTestObj.testObjects.end(), 2, m_testObj);
276static void setBuffer(std::stringstream &stream,
unsigned char *buffer, std::size_t bufferSize)
278#if defined(__GLIBCXX__) && !defined(_LIBCPP_VERSION)
279 stream.rdbuf()->pubsetbuf(
reinterpret_cast<char *
>(buffer),
static_cast<std::streamsize
>(bufferSize));
281 CPP_UTILITIES_UNUSED(stream)
282 CPP_UTILITIES_UNUSED(buffer)
283 CPP_UTILITIES_UNUSED(bufferSize)
287static void readBuffer(std::stringstream &stream,
unsigned char *buffer, std::size_t bufferSize)
289#if defined(__GLIBCXX__) && !defined(_LIBCPP_VERSION)
290 CPP_UTILITIES_UNUSED(stream)
291 CPP_UTILITIES_UNUSED(buffer)
292 CPP_UTILITIES_UNUSED(bufferSize)
294 stream.read(
reinterpret_cast<char *
>(buffer),
static_cast<std::streamsize
>(bufferSize));
297static void writeBuffer(std::stringstream &stream,
unsigned char *buffer, std::size_t bufferSize)
299#if defined(__GLIBCXX__) && !defined(_LIBCPP_VERSION)
300 stream.rdbuf()->pubsetbuf(
reinterpret_cast<char *
>(buffer),
static_cast<std::streamsize
>(bufferSize));
302 stream.write(
reinterpret_cast<const char *
>(buffer),
static_cast<std::streamsize
>(bufferSize));
308 stringstream stream(ios_base::out | ios_base::binary);
309 stream.exceptions(ios_base::failbit | ios_base::badbit);
310 m_buffer.resize(m_expectedTestObj.size());
311 setBuffer(stream, m_buffer.data(), m_buffer.size());
312 m_testObj.toBinary(stream);
313 readBuffer(stream, m_buffer.data(), m_buffer.size());
315 CPPUNIT_ASSERT_EQUAL(m_expectedTestObj, m_buffer);
320 stringstream stream(ios_base::in | ios_base::binary);
321 stream.exceptions(ios_base::failbit | ios_base::badbit);
322 writeBuffer(stream, m_expectedTestObj.data(), m_expectedTestObj.size());
323 const auto deserialized(TestObjectBinary::fromBinary(stream));
329 stringstream stream(ios_base::out | ios_base::binary);
330 stream.exceptions(ios_base::failbit | ios_base::badbit);
331 m_buffer.resize(m_expectedNestedTestObj.size());
332 setBuffer(stream, m_buffer.data(), m_buffer.size());
333 m_nestedTestObj.toBinary(stream);
334 readBuffer(stream, m_buffer.data(), m_buffer.size());
336 CPPUNIT_ASSERT_EQUAL(m_expectedNestedTestObj, m_buffer);
341 stringstream stream(ios_base::in | ios_base::binary);
342 stream.exceptions(ios_base::failbit | ios_base::badbit);
343 writeBuffer(stream, m_expectedNestedTestObj.data(), m_expectedNestedTestObj.size());
345 const auto deserialized(NestingArrayBinary::fromBinary(stream));
346 CPPUNIT_ASSERT_EQUAL(m_nestedTestObj.name, deserialized.name);
347 for (
const auto &testObj : deserialized.testObjects) {
354 CPPUNIT_ASSERT_EQUAL(m_testObj.number, deserialized.number);
355 CPPUNIT_ASSERT_EQUAL(m_testObj.number2, deserialized.number2);
356 CPPUNIT_ASSERT_EQUAL(m_testObj.numbers, deserialized.numbers);
357 CPPUNIT_ASSERT_EQUAL(m_testObj.text, deserialized.text);
358 CPPUNIT_ASSERT_EQUAL(m_testObj.boolean, deserialized.boolean);
359 CPPUNIT_ASSERT_EQUAL(m_testObj.someMap, deserialized.someMap);
360 CPPUNIT_ASSERT_EQUAL(m_testObj.someHash, deserialized.someHash);
361 CPPUNIT_ASSERT_EQUAL(m_testObj.someSet, deserialized.someSet);
362 CPPUNIT_ASSERT_EQUAL(m_testObj.someMultiset, deserialized.someMultiset);
363 CPPUNIT_ASSERT_EQUAL(m_testObj.someUnorderedSet, deserialized.someUnorderedSet);
364 CPPUNIT_ASSERT_EQUAL(m_testObj.someUnorderedMultiset, deserialized.someUnorderedMultiset);
370 shared_ptr<int> sharedPointer(
reinterpret_cast<int *
>(fakePointer), [](
int *) {});
373 stringstream stream(ios_base::in | ios_base::out | ios_base::binary);
374 stream.exceptions(ios_base::failbit | ios_base::badbit);
378 serializer.m_pointer[fakePointer] =
true;
379 serializer.
write(sharedPointer);
383 shared_ptr<int> readPtr;
384 deserializer.m_pointer[fakePointer] =
"foo";
385 CPPUNIT_ASSERT_THROW(deserializer.
read(readPtr), CppUtilities::ConversionException);
386 CPPUNIT_ASSERT(readPtr ==
nullptr);
390 deserializer.m_pointer[fakePointer] = make_shared<int>(42);
391 deserializer.
read(readPtr);
392 CPPUNIT_ASSERT(readPtr !=
nullptr);
393 CPPUNIT_ASSERT_EQUAL(42, *readPtr);
409 ObjectWithVariantsBinary variants;
410 variants.someVariant = std::monostate{};
411 variants.anotherVariant =
"foo";
412 variants.yetAnotherVariant = 42;
415 stringstream stream(ios_base::in | ios_base::out | ios_base::binary);
416 stream.exceptions(ios_base::failbit | ios_base::badbit);
417 variants.toBinary(stream);
420 const auto deserializedVariants = ObjectWithVariantsBinary::fromBinary(stream);
422 CPPUNIT_ASSERT_EQUAL(2_st, deserializedVariants.someVariant.index());
423 CPPUNIT_ASSERT_EQUAL(0_st, deserializedVariants.anotherVariant.index());
424 CPPUNIT_ASSERT_EQUAL(1_st, deserializedVariants.yetAnotherVariant.index());
425 CPPUNIT_ASSERT_EQUAL(
"foo"s, get<0>(deserializedVariants.anotherVariant));
426 CPPUNIT_ASSERT_EQUAL(42, get<1>(deserializedVariants.yetAnotherVariant));
432 const auto str = std::make_optional<std::string>(
"foo");
433 const auto nullStr = std::optional<std::string>();
436 auto stream = std::stringstream(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
437 stream.exceptions(std::ios_base::failbit | std::ios_base::badbit);
444 auto deserStr = std::optional<std::string>();
445 auto deserNullStr = std::optional<std::string>();
446 deser.read(deserStr);
447 deser.read(deserNullStr);
449 CPPUNIT_ASSERT(deserStr.has_value());
450 CPPUNIT_ASSERT_EQUAL(
"foo"s, deserStr.value());
451 CPPUNIT_ASSERT(!nullStr.has_value());
Contains functions for (de)serializing objects from the chrono utilities provided by the C++ utilitie...
Contains BinaryReader and BinaryWriter supporting binary (de)serialization of primitive and custom ty...
Contains only the definition of the BinarySerializable template class which makes the reflection acce...
CPPUNIT_TEST_SUITE_REGISTRATION(BinaryReflectorTests)
The BinaryReflectorTests class tests the (de)serializer.
void testDeserializeSimpleStruct()
void testSharedPointer(std::uintptr_t fakePointer)
void testDeserializeNestedStruct()
void testBigSharedPointer()
void assertTestObject(const TestObjectBinary &deserialized)
void testSerializeNestedStruct()
void testSerializeSimpleStruct()
void testSmallSharedPointer()
The BinaryDeserializer class can read various data types, including custom ones, from an std::istream...
The BinarySerializer class can write various data types, including custom ones, to an std::ostream.
void write(const Type &pair)
BinaryVersion readCustomType(BinaryDeserializer &deserializer, Type &customType, BinaryVersion version=0)
Reads customType via deserializer.
void writeCustomType(BinarySerializer &serializer, const Type &customType, BinaryVersion version=0)
Writes customType via serializer.
std::uint64_t BinaryVersion
The BinarySerializable class provides the CRTP-base for (de)serializable objects.