|
| 1 | +#include "catch.hpp" |
| 2 | +#include "portable_archive/portable_iarchive.hpp" |
| 3 | +#include "portable_archive/portable_oarchive.hpp" |
| 4 | +#include "sample.h" |
| 5 | +#include <fstream> |
| 6 | +#include <sstream> |
| 7 | +#include <type_traits> |
| 8 | + |
| 9 | +struct Testclass { |
| 10 | + std::string teststr; |
| 11 | + double testdouble; |
| 12 | + uint64_t testbigint; |
| 13 | + int32_t negativeint, testint; |
| 14 | + std::unique_ptr<lsl::sample> s1 = nullptr, s2 = nullptr; |
| 15 | + char testchar; |
| 16 | + template <typename Archive> void serialize(Archive &a, const uint32_t) { |
| 17 | + a &testchar &testint &negativeint &testbigint &testdouble &teststr &*s1 &*s2; |
| 18 | + } |
| 19 | + template <typename Archive> void load(Archive &a, const uint32_t archive_version) { |
| 20 | + serialize(a, archive_version); |
| 21 | + } |
| 22 | + template <typename Archive> void save(Archive &a, const uint32_t archive_version) const { |
| 23 | + const_cast<Testclass *>(this)->serialize(a, archive_version); |
| 24 | + } |
| 25 | + |
| 26 | + Testclass(): s1(lsl::factory::new_sample_unmanaged(cft_double64, 4, 0.0, false)), |
| 27 | + s2(lsl::factory::new_sample_unmanaged(cft_string, 4, 0.0, false)) {} |
| 28 | + Testclass(bool /*dummy*/) |
| 29 | + : teststr("String\x00with\x00nulls"), testdouble(17.3), testbigint(0xff), negativeint(-1), |
| 30 | + testint(0x00abcdef), s1(lsl::factory::new_sample_unmanaged(cft_double64, 4, 17.3, true)), |
| 31 | + s2(lsl::factory::new_sample_unmanaged(cft_string, 4, 18.3, true)), testchar('a') { |
| 32 | + s1->assign_test_pattern(2); |
| 33 | + s2->assign_test_pattern(4); |
| 34 | + } |
| 35 | +}; |
| 36 | + |
| 37 | +struct Testclass2 { |
| 38 | + uint64_t i; |
| 39 | + |
| 40 | + template <typename Archive> void serialize(Archive &a, const uint32_t) { a &i; } |
| 41 | + template <typename Archive> void load(Archive &a, const uint32_t archive_version) { |
| 42 | + serialize(a, archive_version); |
| 43 | + } |
| 44 | + template <typename Archive> void save(Archive &a, const uint32_t archive_version) const { |
| 45 | + const_cast<Testclass2 *>(this)->serialize(a, archive_version); |
| 46 | + } |
| 47 | +}; |
| 48 | + |
| 49 | +TEST_CASE("v100 protocol serialization", "[basic][serialization]") { |
| 50 | + Testclass out1(true); |
| 51 | + Testclass2 out2, out3; |
| 52 | + out2.i = out3.i = 0x00ab00cd00ef0012u; |
| 53 | + std::stringbuf osb(std::ios::out); |
| 54 | + { |
| 55 | + eos::portable_oarchive outarch(osb); |
| 56 | + outarch << out2 << out3; |
| 57 | + outarch << std::string("Testclass") << out1; |
| 58 | + } |
| 59 | + |
| 60 | + // Preserialized, generate with |
| 61 | + // python -c "import re;print(re.sub('(?<=x[0-9a-f]{2})[0-9a-f]', r'\"\\n\"\\g<0>', |
| 62 | + // str(open('serialization_found.bin','rb').read())))" |
| 63 | + static const char binpacket[] = |
| 64 | + "\x7f\x01\t\x00\x00\x07\x12\x00\xef\x00\xcd\x00\xab\x07\x12\x00\xef" |
| 65 | + "\x00\xcd\x00\xab\x01\t" |
| 66 | + "Testclass\x00\x00\x01" |
| 67 | + "a\x03\xef\xcd\xab\xff\xff\x01\xff\x08\xcd\xcc\xcc\xcc\xccL1@\x01\x06" |
| 68 | + "String\x00\x00\x01\x02\x08\xc9v\xbe\x9f\x0c$\xfe@\x08\x00\x00\x00" |
| 69 | + "0\x00\x00pA\x08\x00\x00\x00@\x00\x00p\xc1\x08\x00\x00\x00P\x00\x00pA" |
| 70 | + "\x08\x00\x00\x00`\x00\x00p\xc1\x01\x02\x08\xc9v\xbe\x9f\x0c$\xfe@\x01\x02" |
| 71 | + "10\x01\x03-11\x01\x02" |
| 72 | + "12\x01\x03-13"; |
| 73 | + const std::string preserialized(binpacket, sizeof(binpacket) - 1); |
| 74 | + std::string res(osb.str()); |
| 75 | + |
| 76 | + if (res.size() != preserialized.size() || res != preserialized) { |
| 77 | + // dump mismatching data for further analysis |
| 78 | + std::ofstream("serialization_expected.bin", std::ios::binary) << preserialized; |
| 79 | + std::ofstream("serialization_found.bin", std::ios::binary) << res; |
| 80 | + FAIL(); |
| 81 | + } |
| 82 | + |
| 83 | + std::stringbuf isb(preserialized, std::ios::in); |
| 84 | + try { |
| 85 | + eos::portable_iarchive inarch(isb); |
| 86 | + Testclass in1; |
| 87 | + Testclass2 in2, in3; |
| 88 | + inarch >> in2 >> in3; |
| 89 | + REQUIRE(in2.i == 0x00ab00cd00ef0012u); |
| 90 | + REQUIRE(in3.i == 0x00ab00cd00ef0012u); |
| 91 | + std::string teststr; |
| 92 | + inarch >> teststr >> in1; |
| 93 | + REQUIRE(teststr == std::string("Testclass")); |
| 94 | + REQUIRE(in1.testdouble == Approx(out1.testdouble)); |
| 95 | + REQUIRE(in1.testbigint == out1.testbigint); |
| 96 | + REQUIRE(in1.testchar == out1.testchar); |
| 97 | + REQUIRE(in1.negativeint == out1.negativeint); |
| 98 | + REQUIRE(in1.testint == out1.testint); |
| 99 | + REQUIRE(in1.teststr == out1.teststr); |
| 100 | + REQUIRE(*in1.s1 == *out1.s1); |
| 101 | + REQUIRE(*in1.s2 == *out1.s2); |
| 102 | + CHECK(true); |
| 103 | + } catch (std::exception &e) { FAIL(e.what()); } |
| 104 | +} |
| 105 | + |
| 106 | +TEST_CASE("read v100 protocol samples", "[basic][serialization]") {} |
0 commit comments