1 #include "../binary/reflector-chronoutilities.h"
2 #include "../binary/reflector.h"
3 #include "../binary/serializable.h"
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>
10 using CppUtilities::operator<<;
11 #include <cppunit/TestFixture.h>
12 #include <cppunit/extensions/HelperMacros.h>
21 #include <unordered_map>
25 using namespace CPPUNIT_NS;
26 using namespace CppUtilities;
27 using namespace CppUtilities::Literals;
39 enum 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;
68 struct ObjectWithVariantsBinary :
public BinarySerializable<ObjectWithVariantsBinary> {
69 variant<int, string, monostate> someVariant;
70 variant<string, float> anotherVariant;
71 variant<string, int> yetAnotherVariant;
76 namespace BinaryReflector {
78 template <>
void readCustomType<TestObjectBinary>(BinaryDeserializer &deserializer, TestObjectBinary &customType)
80 deserializer.read(customType.number);
81 deserializer.read(customType.number2);
82 deserializer.read(customType.numbers);
83 deserializer.read(customType.text);
84 deserializer.read(customType.boolean);
85 deserializer.read(customType.someMap);
86 deserializer.read(customType.someHash);
87 deserializer.read(customType.someSet);
88 deserializer.read(customType.someMultiset);
89 deserializer.read(customType.someUnorderedSet);
90 deserializer.read(customType.someUnorderedMultiset);
91 deserializer.read(customType.someEnum);
92 deserializer.read(customType.someEnumClass);
93 deserializer.read(customType.timeSpan);
94 deserializer.read(customType.dateTime);
97 template <>
void writeCustomType<TestObjectBinary>(BinarySerializer &serializer,
const TestObjectBinary &customType)
99 serializer.write(customType.number);
100 serializer.write(customType.number2);
101 serializer.write(customType.numbers);
102 serializer.write(customType.text);
103 serializer.write(customType.boolean);
104 serializer.write(customType.someMap);
105 serializer.write(customType.someHash);
106 serializer.write(customType.someSet);
107 serializer.write(customType.someMultiset);
108 serializer.write(customType.someUnorderedSet);
109 serializer.write(customType.someUnorderedMultiset);
110 serializer.write(customType.someEnum);
111 serializer.write(customType.someEnumClass);
112 serializer.write(customType.timeSpan);
113 serializer.write(customType.dateTime);
116 template <>
void readCustomType<NestingArrayBinary>(BinaryDeserializer &deserializer, NestingArrayBinary &customType)
118 deserializer.read(customType.name);
119 deserializer.read(customType.testObjects);
122 template <>
void writeCustomType<NestingArrayBinary>(BinarySerializer &serializer,
const NestingArrayBinary &customType)
124 serializer.write(customType.name);
125 serializer.write(customType.testObjects);
128 template <>
void readCustomType<ObjectWithVariantsBinary>(BinaryDeserializer &deserializer, ObjectWithVariantsBinary &customType)
130 deserializer.read(customType.someVariant);
131 deserializer.read(customType.anotherVariant);
132 deserializer.read(customType.yetAnotherVariant);
135 template <>
void writeCustomType<ObjectWithVariantsBinary>(BinarySerializer &serializer,
const ObjectWithVariantsBinary &customType)
137 serializer.write(customType.someVariant);
138 serializer.write(customType.anotherVariant);
139 serializer.write(customType.yetAnotherVariant);
155 CPPUNIT_TEST(testSerializeSimpleStruct);
156 CPPUNIT_TEST(testDeserializeSimpleStruct);
157 CPPUNIT_TEST(testSerializeNestedStruct);
158 CPPUNIT_TEST(testDeserializeNestedStruct);
159 CPPUNIT_TEST(testSmallSharedPointer);
160 CPPUNIT_TEST(testBigSharedPointer);
161 CPPUNIT_TEST(testVariant);
162 CPPUNIT_TEST_SUITE_END();
167 void setUp()
override;
168 void tearDown()
override;
170 void testSerializeSimpleStruct();
171 void testDeserializeSimpleStruct();
172 void testSerializeNestedStruct();
173 void testDeserializeNestedStruct();
174 void assertTestObject(
const TestObjectBinary &deserialized);
175 void testSharedPointer(std::uintptr_t fakePointer);
176 void testSmallSharedPointer();
177 void testBigSharedPointer();
181 vector<unsigned char> m_buffer;
182 TestObjectBinary m_testObj;
183 NestingArrayBinary m_nestedTestObj;
184 vector<unsigned char> m_expectedTestObj;
185 vector<unsigned char> m_expectedNestedTestObj;
195 , m_expectedTestObj({
196 0x00, 0x00, 0x00, 0x05,
197 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x01,
200 0x00, 0x00, 0x00, 0x02,
201 0x00, 0x00, 0x00, 0x03,
202 0x00, 0x00, 0x00, 0x04,
203 0x00, 0x00, 0x00, 0x05,
205 0x73, 0x6F, 0x6D, 0x65, 0x20, 0x74, 0x65, 0x78, 0x74,
208 0x83, 0x62, 0x61, 0x72, 0x00, 0x00, 0x00, 0x13,
209 0x83, 0x66, 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x11,
222 0x00, 0x00, 0x00, 0x01,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xCD,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xAB,
227 , m_expectedNestedTestObj({
228 0x93, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67,
237 m_testObj.number = 5;
238 m_testObj.number2 = 2.5;
239 m_testObj.numbers = { 1, 2, 3, 4, 5 };
240 m_testObj.text =
"some text";
241 m_testObj.boolean =
true;
242 m_testObj.someMap = {
246 m_testObj.someSet = {
"1",
"2",
"3",
"2" };
247 m_testObj.someMultiset = {
"1",
"2",
"3",
"2" };
248 m_testObj.someEnum = SomeEnumItem2;
249 m_testObj.someEnumClass = SomeEnumClassBinary::Item3;
250 m_testObj.timeSpan = TimeSpan(0xABCD);
251 m_testObj.dateTime = DateTime(0xEFAB);
252 m_nestedTestObj.name =
"struct with nesting";
253 m_expectedNestedTestObj.reserve(m_expectedNestedTestObj.size() + 2 * m_expectedTestObj.size());
254 m_expectedNestedTestObj.insert(m_expectedNestedTestObj.end(), m_expectedTestObj.cbegin(), m_expectedTestObj.cend());
255 m_expectedNestedTestObj.insert(m_expectedNestedTestObj.end(), m_expectedTestObj.cbegin(), m_expectedTestObj.cend());
256 m_nestedTestObj.testObjects.insert(m_nestedTestObj.testObjects.end(), 2, m_testObj);
265 stringstream stream(ios_base::out | ios_base::binary);
266 stream.exceptions(ios_base::failbit | ios_base::badbit);
267 m_buffer.resize(m_expectedTestObj.size());
268 stream.rdbuf()->pubsetbuf(
reinterpret_cast<char *
>(m_buffer.data()),
static_cast<streamsize
>(m_buffer.size()));
269 m_testObj.toBinary(stream);
271 CPPUNIT_ASSERT_EQUAL(m_expectedTestObj, m_buffer);
276 stringstream stream(ios_base::in | ios_base::binary);
277 stream.exceptions(ios_base::failbit | ios_base::badbit);
278 stream.rdbuf()->pubsetbuf(
reinterpret_cast<char *
>(m_expectedTestObj.data()),
static_cast<streamsize
>(m_expectedTestObj.size()));
279 const auto deserialized(TestObjectBinary::fromBinary(stream));
285 stringstream stream(ios_base::out | ios_base::binary);
286 stream.exceptions(ios_base::failbit | ios_base::badbit);
287 m_buffer.resize(m_expectedNestedTestObj.size());
288 stream.rdbuf()->pubsetbuf(
reinterpret_cast<char *
>(m_buffer.data()),
static_cast<streamsize
>(m_buffer.size()));
289 m_nestedTestObj.toBinary(stream);
291 CPPUNIT_ASSERT_EQUAL(m_expectedNestedTestObj, m_buffer);
296 stringstream stream(ios_base::in | ios_base::binary);
297 stream.exceptions(ios_base::failbit | ios_base::badbit);
298 stream.rdbuf()->pubsetbuf(
reinterpret_cast<char *
>(m_expectedNestedTestObj.data()),
static_cast<streamsize
>(m_expectedNestedTestObj.size()));
300 const auto deserialized(NestingArrayBinary::fromBinary(stream));
301 CPPUNIT_ASSERT_EQUAL(m_nestedTestObj.name, deserialized.name);
302 for (
const auto &testObj : deserialized.testObjects) {
309 CPPUNIT_ASSERT_EQUAL(m_testObj.number, deserialized.number);
310 CPPUNIT_ASSERT_EQUAL(m_testObj.number2, deserialized.number2);
311 CPPUNIT_ASSERT_EQUAL(m_testObj.numbers, deserialized.numbers);
312 CPPUNIT_ASSERT_EQUAL(m_testObj.text, deserialized.text);
313 CPPUNIT_ASSERT_EQUAL(m_testObj.boolean, deserialized.boolean);
314 CPPUNIT_ASSERT_EQUAL(m_testObj.someMap, deserialized.someMap);
315 CPPUNIT_ASSERT_EQUAL(m_testObj.someHash, deserialized.someHash);
316 CPPUNIT_ASSERT_EQUAL(m_testObj.someSet, deserialized.someSet);
317 CPPUNIT_ASSERT_EQUAL(m_testObj.someMultiset, deserialized.someMultiset);
318 CPPUNIT_ASSERT_EQUAL(m_testObj.someUnorderedSet, deserialized.someUnorderedSet);
319 CPPUNIT_ASSERT_EQUAL(m_testObj.someUnorderedMultiset, deserialized.someUnorderedMultiset);
325 shared_ptr<int> sharedPointer(
reinterpret_cast<int *
>(fakePointer), [](
int *) {});
328 stringstream stream(ios_base::in | ios_base::out | ios_base::binary);
329 stream.exceptions(ios_base::failbit | ios_base::badbit);
333 serializer.m_pointer[fakePointer] =
true;
334 serializer.
write(sharedPointer);
338 shared_ptr<int> readPtr;
339 deserializer.m_pointer[fakePointer] =
"foo";
340 CPPUNIT_ASSERT_THROW(deserializer.
read(readPtr), CppUtilities::ConversionException);
341 CPPUNIT_ASSERT(readPtr ==
nullptr);
345 deserializer.m_pointer[fakePointer] = make_shared<int>(42);
346 deserializer.
read(readPtr);
347 CPPUNIT_ASSERT(readPtr !=
nullptr);
348 CPPUNIT_ASSERT_EQUAL(42, *readPtr);
364 ObjectWithVariantsBinary variants;
365 variants.someVariant = std::monostate{};
366 variants.anotherVariant =
"foo";
367 variants.yetAnotherVariant = 42;
370 stringstream stream(ios_base::in | ios_base::out | ios_base::binary);
371 stream.exceptions(ios_base::failbit | ios_base::badbit);
372 variants.toBinary(stream);
375 const auto deserializedVariants = ObjectWithVariantsBinary::fromBinary(stream);
377 CPPUNIT_ASSERT_EQUAL(2_st, deserializedVariants.someVariant.index());
378 CPPUNIT_ASSERT_EQUAL(0_st, deserializedVariants.anotherVariant.index());
379 CPPUNIT_ASSERT_EQUAL(1_st, deserializedVariants.yetAnotherVariant.index());
380 CPPUNIT_ASSERT_EQUAL(
"foo"s, get<0>(deserializedVariants.anotherVariant));
381 CPPUNIT_ASSERT_EQUAL(42, get<1>(deserializedVariants.yetAnotherVariant));