File: serialization_v100.cpp

package info (click to toggle)
liblsl 1.16.2b1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 1,724 kB
  • sloc: cpp: 12,515; ansic: 666; python: 28; sh: 25; makefile: 18
file content (105 lines) | stat: -rw-r--r-- 3,596 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "sample.h"
#include <catch2/catch.hpp>
#include <fstream>
#include <sstream>
#include <type_traits>

// clazy:excludeall=non-pod-global-static

#define NO_EXPLICIT_TEMPLATE_INSTANTIATION
#include "portable_archive/portable_iarchive.hpp"
#include "portable_archive/portable_oarchive.hpp"

static lsl::factory doublefac{cft_double64, 4, 1}, strfac{cft_string, 4, 1};

struct Testclass {
	std::string teststr;
	double testdouble{0};
	uint64_t testbigint{0};
	int32_t negativeint{0}, testint{0};
	lsl::sample_p s1, s2;
	char testchar{0};

	template <typename Archive> void serialize_(Archive &a) {
		a &testchar &testint &negativeint &testbigint &testdouble &teststr &*s1 &*s2;
	}
	void serialize(eos::portable_iarchive &a, uint32_t) { serialize_(a); }

	void serialize(eos::portable_oarchive &a, uint32_t) const {
		const_cast<Testclass *>(this)->serialize_(a);
	}

	Testclass() : s1(doublefac.new_sample(0.0, false)), s2(strfac.new_sample(0.0, false)) {}
	Testclass(bool /*dummy*/)
		: teststr("String\x00with\x00nulls"), testdouble(17.3), testbigint(0xff), negativeint(-1),
		  testint(0x00abcdef), s1(doublefac.new_sample(17.3, true)),
		  s2(strfac.new_sample(18.3, true)), testchar('a') {
		s1->assign_test_pattern(2);
		s2->assign_test_pattern(4);
	}
};

struct Testclass2 {
	uint64_t i;

	void serialize(eos::portable_iarchive &a, uint32_t) { a &i; }
	void serialize(eos::portable_oarchive &a, uint32_t) const { a &i; }
};

TEST_CASE("v100 protocol serialization", "[basic][serialization]") {
	Testclass out1(true);
	Testclass2 out2, out3;
	out2.i = out3.i = 0x00ab00cd00ef0012u;
	std::stringbuf osb(std::ios::out);
	{
		eos::portable_oarchive outarch(osb);
		outarch << out2 << out3;
		outarch << std::string("Testclass") << out1;
	}

	// Preserialized, generate with
	// python -c "import re;print(re.sub('(?<=x[0-9a-f]{2})[0-9a-f]', r'\"\\n\"\\g<0>',
	// str(open('serialization_found.bin','rb').read())))"
	static const char binpacket[] =
		"\x7f\x01\t\x00\x00\x07\x12\x00\xef\x00\xcd\x00\xab\x07\x12\x00\xef"
		"\x00\xcd\x00\xab\x01\t"
		"Testclass\x00\x00\x01"
		"a\x03\xef\xcd\xab\xff\xff\x01\xff\x08\xcd\xcc\xcc\xcc\xccL1@\x01\x06"
		"String\x00\x00\x01\x02\x08\xc9v\xbe\x9f\x0c$\xfe@\x08\x00\x00\x00"
		"0\x00\x00pA\x08\x00\x00\x00@\x00\x00p\xc1\x08\x00\x00\x00P\x00\x00pA"
		"\x08\x00\x00\x00`\x00\x00p\xc1\x01\x02\x08\xc9v\xbe\x9f\x0c$\xfe@\x01\x02"
		"10\x01\x03-11\x01\x02"
		"12\x01\x03-13";
	const std::string preserialized(binpacket, sizeof(binpacket) - 1);
	std::string res(osb.str());

	if (res.size() != preserialized.size() || res != preserialized) {
		// dump mismatching data for further analysis
		std::ofstream("serialization_expected.bin", std::ios::binary) << preserialized;
		std::ofstream("serialization_found.bin", std::ios::binary) << res;
		FAIL();
	}

	std::stringbuf isb(preserialized, std::ios::in);
	try {
		eos::portable_iarchive inarch(isb);
		Testclass in1;
		Testclass2 in2, in3;
		inarch >> in2 >> in3;
		REQUIRE(in2.i == 0x00ab00cd00ef0012u);
		REQUIRE(in3.i == 0x00ab00cd00ef0012u);

		std::string teststr;
		inarch >> teststr >> in1;
		REQUIRE(teststr == std::string("Testclass"));
		REQUIRE(in1.testdouble == Approx(out1.testdouble));
		REQUIRE(in1.testbigint == out1.testbigint);
		REQUIRE(in1.testchar == out1.testchar);
		REQUIRE(in1.negativeint == out1.negativeint);
		REQUIRE(in1.testint == out1.testint);
		REQUIRE(in1.teststr == out1.teststr);

		if (*in1.s1 != *out1.s1) FAIL("Sample 1 serialization mismatch");
		if (*in1.s2 != *out1.s2) FAIL("Sample 2 serialization mismatch");
	} catch (std::exception &e) { FAIL(e.what()); }
}