#include #include "assert_def.h" #include "rpc_core.hpp" #include "serialize/CustomType.h" namespace rpc_core_test { static size_t last_serialize_size = 0; template void serialize_test(const T& a, R& b) { std::string data = rpc_core::serialize(a); last_serialize_size = data.size(); RPC_CORE_LOGI(" size: %zu", last_serialize_size); bool ret = rpc_core::deserialize(data, b); ASSERT(ret); } template void raw_type_test() { T a = 123; T b; serialize_test(a, b); auto ok = (0 == memcmp(&a, &b, sizeof(T))); // NOLINT ASSERT(ok); } #define RAW_TYPE_TEST(t) \ RPC_CORE_LOGI(" <" #t ">"); \ raw_type_test(); #define ASSERT_SERIALIZE_SIZE(x) ASSERT(last_serialize_size == x) static bool is_little_endian() { int x = 1; return *(char*)&x != 0; } static void test_auto_size() { using namespace rpc_core::detail; auto test_auto_size = [](size_t value, int except_size) { RPC_CORE_LOGI("value: 0x%" PRIxMAX "(%" PRIiMAX ") except: %d", value, value, except_size); auto_size a(value); std::string payload = a.serialize(); ASSERT(payload.size() == (size_t)except_size); auto_size b; int cost = b.deserialize(payload.data()); ASSERT(cost = except_size); ASSERT(value == b.value); }; test_auto_size(0x00, 1); test_auto_size(0x01, 2); test_auto_size(0xff, 2); test_auto_size(0xfff, 3); test_auto_size(0xffff, 3); test_auto_size(0xfffff, 4); test_auto_size(0xffffff, 4); test_auto_size(0xfffffff, 5); test_auto_size(0xffffffff, 5); auto test_auto_int = [](intmax_t value, int except_size) { RPC_CORE_LOGI("value: 0x%" PRIxMAX "(%" PRIiMAX ") except: %d", value, value, except_size); auto_intmax a(value); std::string payload = a.serialize(); ASSERT(payload.size() == (size_t)except_size); auto_intmax b; int cost = b.deserialize(payload.data()); ASSERT(cost = except_size); ASSERT(value == b.value); }; test_auto_int(0x00, 1); test_auto_int(0xff, 2); test_auto_int(-0xff, 2); test_auto_int(0xffff, 3); test_auto_int(-0xffff, 3); test_auto_int(0xffffff, 4); test_auto_int(-0xffffff, 4); test_auto_int(intmax_t(0xffffffff), 5); test_auto_int(-(intmax_t(0xffffffff)), 5); auto test_auto_uint = [](uintmax_t value, int except_size) { RPC_CORE_LOGI("value: 0x%" PRIxMAX "(%" PRIiMAX ") except: %d", value, value, except_size); auto_uintmax a(value); std::string payload = a.serialize(); ASSERT(payload.size() == (size_t)except_size); auto_uintmax b; int cost = b.deserialize(payload.data()); ASSERT(cost = except_size); ASSERT(value == b.value); }; test_auto_uint(0x00, 1); test_auto_uint(0xff, 2); test_auto_uint(0xffff, 3); test_auto_uint(0xffffff, 4); test_auto_uint(uintmax_t(0xffffffff), 5); } void test_serialize() { /// only support little endian ASSERT(is_little_endian()); /// auto_size test_auto_size(); /// raw type { int32_t a = -1; int32_t b = 0; std::string data = rpc_core::serialize(a); bool ret = rpc_core::deserialize(data, b); ASSERT(ret); RPC_CORE_LOGI("raw type test..."); RAW_TYPE_TEST(char); ASSERT_SERIALIZE_SIZE(1); RAW_TYPE_TEST(int8_t); ASSERT_SERIALIZE_SIZE(1); RAW_TYPE_TEST(uint8_t); ASSERT_SERIALIZE_SIZE(1); RAW_TYPE_TEST(int16_t); ASSERT_SERIALIZE_SIZE(2); RAW_TYPE_TEST(uint16_t); ASSERT_SERIALIZE_SIZE(2); RAW_TYPE_TEST(int32_t); ASSERT_SERIALIZE_SIZE(2); RAW_TYPE_TEST(uint32_t); ASSERT_SERIALIZE_SIZE(2); RAW_TYPE_TEST(int64_t); ASSERT_SERIALIZE_SIZE(2); RAW_TYPE_TEST(uint64_t); ASSERT_SERIALIZE_SIZE(2); RAW_TYPE_TEST(float); ASSERT_SERIALIZE_SIZE(4); RAW_TYPE_TEST(double); ASSERT_SERIALIZE_SIZE(8); RAW_TYPE_TEST(long double); ASSERT_SERIALIZE_SIZE(16); } /// enum { enum class Enum { k_0, k_1, }; RPC_CORE_LOGI("enum..."); Enum a = Enum::k_1; Enum b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2); } /// std::array { RPC_CORE_LOGI("std::array..."); std::array a{1, 2, 3}; std::array b{}; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } /// std::string { RPC_CORE_LOGI("std::string..."); std::string a = "test"; std::string b; serialize_test(a, b); ASSERT(b == a); ASSERT_SERIALIZE_SIZE(a.size()); } /// std::wstring { RPC_CORE_LOGI("std::wstring..."); std::wstring a = L"中文"; std::wstring b; serialize_test(a, b); ASSERT(b == a); ASSERT_SERIALIZE_SIZE(a.size() * sizeof(wchar_t)); } /// std::tuple { RPC_CORE_LOGI("std::tuple..."); bool msg1 = true; uint32_t msg2 = 12; std::string msg3 = "test"; std::tuple a(msg1, msg2, msg3); std::tuple b; serialize_test(a, b); ASSERT(std::get<0>(b) == msg1); ASSERT(std::get<1>(b) == msg2); ASSERT(std::get<2>(b) == msg3); ASSERT(a == b); ASSERT_SERIALIZE_SIZE((1) + (2) + (2 /*size*/ + msg3.size())); } /// std::pair { RPC_CORE_LOGI("std::pair..."); std::pair a{"k:1", "v:1"}; std::pair b; serialize_test(a, b); ASSERT(b == a); ASSERT_SERIALIZE_SIZE((2 /*size*/ + 3) * 2); } /// list_like type { RPC_CORE_LOGI("std::vector..."); std::vector a{1, 2, 3}; std::vector b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } { RPC_CORE_LOGI("std::list..."); std::list a{1, 2, 3}; std::list b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } { RPC_CORE_LOGI("std::deque..."); std::deque a{1, 2, 3}; std::deque b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } /// std container adaptors { RPC_CORE_LOGI("std::stack..."); std::stack a; a.push(1); a.push(2); a.push(3); std::stack b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } { RPC_CORE_LOGI("std::queue..."); std::queue a; a.push(1); a.push(2); a.push(3); std::queue b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } { RPC_CORE_LOGI("std::priority_queue..."); std::priority_queue a; a.push(1); a.push(2); a.push(3); std::priority_queue b; serialize_test(a, b); for (uint32_t i = 0; i < a.size(); ++i) { ASSERT(a.top() == b.top()); a.pop(); b.pop(); } ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } /// std::bitset { RPC_CORE_LOGI("std::bitset..."); std::bitset<8> a; a.set(); std::bitset<8> b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(8 /*11111111*/); } /// std::forward_list { RPC_CORE_LOGI("std::forward_list..."); std::forward_list a{1, 2, 3}; std::forward_list b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } /// std::set { RPC_CORE_LOGI("std::set..."); std::set a{1, 2, 3}; std::set b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } /// std::multiset { RPC_CORE_LOGI("std::multiset..."); std::multiset a{1, 2, 3}; std::multiset b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } /// std::unordered_multiset { RPC_CORE_LOGI("std::unordered_multiset..."); std::unordered_multiset a{1, 2, 3}; std::unordered_multiset b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3); } /// std::map { RPC_CORE_LOGI("std::map..."); std::map a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}}; std::map b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3); } /// std::unordered_map { RPC_CORE_LOGI("std::unordered_map..."); std::unordered_map a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}}; std::unordered_map b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3); } /// std::multimap { RPC_CORE_LOGI("std::multimap..."); std::multimap a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}}; std::multimap b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3); } /// std::unordered_multimap { RPC_CORE_LOGI("std::unordered_multimap..."); std::unordered_multimap a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}}; std::unordered_multimap b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3); } /// ptr { RPC_CORE_LOGI("ptr..."); int* a = (int*)123; int* b = nullptr; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2); // auto size } /// binary_wrap { RPC_CORE_LOGI("binary_wrap..."); { uint8_t array[] = {1, 2, 3}; size_t data_bytes = sizeof(array); rpc_core::binary_wrap a(array, data_bytes); rpc_core::binary_wrap b; serialize_test(a, b); ASSERT(b.size == data_bytes); ASSERT(b.data != array); ASSERT(0 == memcmp(array, b.data, data_bytes)); ASSERT_SERIALIZE_SIZE(2 /*size*/ + data_bytes); } { uint8_t array[] = {1, 2, 3}; struct Test { uint8_t* ptr = nullptr; rpc_core::binary_wrap bin; RPC_CORE_DEFINE_TYPE_INNER(ptr, bin); }; Test a; a.ptr = array; a.bin = {array, sizeof(array)}; Test b; serialize_test(a, b); ASSERT(b.ptr == array); ASSERT(b.bin.size == sizeof(array)); ASSERT(b.bin.data != array); ASSERT(0 == memcmp(array, b.bin.data, sizeof(array))); } } /// std::shared_ptr { RPC_CORE_LOGI("std::shared_ptr..."); { std::shared_ptr a = std::make_shared("test"); std::shared_ptr b; serialize_test(a, b); ASSERT(*a == *b); ASSERT_SERIALIZE_SIZE(1 /*flag*/ + a->size()); } { std::shared_ptr a = nullptr; std::shared_ptr b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(1 /*flag*/); } } /// std::unique_ptr { RPC_CORE_LOGI("std::unique_ptr..."); { std::unique_ptr a = std::unique_ptr(new std::string("test")); std::unique_ptr b; serialize_test(a, b); ASSERT(*a == *b); ASSERT_SERIALIZE_SIZE(1 /*flag*/ + a->size()); } { std::unique_ptr a = nullptr; std::unique_ptr b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(1 /*flag*/); } } /// std::complex { RPC_CORE_LOGI("std::complex..."); { std::complex a; a.real(1.23f); a.imag(3.21f); std::complex b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(4 /*float*/ * 2); } { std::complex a; { CustomType t; t.id = 1; t.ids = {1, 2, 3}; t.name = "test"; a.real(t); a.imag(t); } std::complex b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(40); } } /// std::duration { RPC_CORE_LOGI("std::duration..."); std::chrono::seconds a(123); std::chrono::seconds b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(2); // auto size } /// std::time_point { RPC_CORE_LOGI("std::time_point..."); std::chrono::time_point a = std::chrono::time_point::max(); std::chrono::time_point b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(9); } /// custom class/struct { RPC_CORE_LOGI("custom type..."); CustomType a; a.id = 1; a.ids = {1, 2, 3}; a.name = "test"; CustomType b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE((2) + (2 /*ids bytes*/ + 2 /*ids size*/ + 2 * 3) + (2 /*name bytes*/ + 4)); } { RPC_CORE_LOGI("custom ptr..."); CustomTypePtr a; a.int_n = nullptr; a.int_v = (int32_t*)1; a.unique_ptr_n = nullptr; a.unique_ptr_v = std::unique_ptr(new int32_t(1)); a.shared_ptr_n = nullptr; a.shared_ptr_v = std::make_shared(1); CustomTypePtr b; serialize_test(a, b); ASSERT(b.int_n == nullptr); ASSERT(b.int_v == (int32_t*)1); ASSERT(b.unique_ptr_n == nullptr); ASSERT(*b.unique_ptr_v == 1); ASSERT(b.shared_ptr_n == nullptr); ASSERT(*b.shared_ptr_v == 1); ASSERT_SERIALIZE_SIZE(23); } { RPC_CORE_LOGI("custom type(different alignas)..."); CustomType2 a; a.id1 = 1; a.id2 = 2; a.id3 = 3; CustomType3 b; serialize_test(a, b); ASSERT(a.id1 == b.id1); ASSERT(a.id2 == b.id2); ASSERT(a.id3 == b.id3); ASSERT_SERIALIZE_SIZE(4); } { RPC_CORE_LOGI("custom type(nest define)..."); test::CustomTypeNest a; a.c2.id1 = 1; a.c2.id2 = 2; a.c2.id3 = 3; test::CustomTypeNest b; serialize_test(a, b); ASSERT(a.c2.id1 == b.c2.id1); ASSERT(a.c2.id2 == b.c2.id2); ASSERT(a.c2.id3 == b.c2.id3); ASSERT_SERIALIZE_SIZE(14); } { RPC_CORE_LOGI("custom type(inner)..."); test::CustomTypeNest2 a; a.c2.id1 = 1; a.c2.id2 = 2; a.c2.id3 = 3; test::CustomTypeNest2 b; serialize_test(a, b); ASSERT(a.c2.id1 == b.c2.id1); ASSERT(a.c2.id2 == b.c2.id2); ASSERT(a.c2.id3 == b.c2.id3); ASSERT_SERIALIZE_SIZE(14); } /// misc types { RPC_CORE_LOGI("misc types..."); CustomType customType; customType.id = 1; customType.ids = {1, 2, 3}; customType.name = "test"; std::tuple>, std::string, CustomType> a{true, {{1}, {2}}, "test", customType}; std::tuple>, std::string, CustomType> b; serialize_test(a, b); ASSERT(a == b); ASSERT_SERIALIZE_SIZE(39); } } } // namespace rpc_core_test