1/**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "serializer/serializer.h"
17#include <gtest/gtest.h>
18
19namespace panda {
20
21class SerializatorTest : public testing::Test {
22protected:
23    void SetUp()
24    {
25        buffer.resize(0);
26    }
27    std::vector<uint8_t> buffer;
28};
29
30template <typename T>
31void SerializerTypeToBuffer(const T &type, /* out */ std::vector<uint8_t> &buffer, size_t ret_val)
32{
33    auto ret = serializer::TypeToBuffer(type, buffer);
34    ASSERT_TRUE(ret);
35    ASSERT_EQ(ret.Value(), ret_val);
36}
37
38template <typename T>
39void SerializerBufferToType(const std::vector<uint8_t> &buffer, /* out */ T &type, size_t ret_val)
40{
41    auto ret = serializer::BufferToType(buffer.data(), buffer.size(), type);
42    ASSERT_TRUE(ret);
43    ASSERT_EQ(ret.Value(), ret_val);
44}
45
46template <typename T>
47void DoTest(T value, int ret_val)
48{
49    constexpr const int64_t IMM_FOUR = 4;
50    T a = value;
51    T b;
52    std::vector<uint8_t> buffer;
53    SerializerTypeToBuffer(a, buffer, ret_val);
54    buffer.resize(IMM_FOUR * buffer.size());
55    SerializerBufferToType(buffer, b, ret_val);
56    ASSERT_EQ(a, value);
57    ASSERT_EQ(b, value);
58    ASSERT_EQ(a, b);
59}
60
61template <typename T>
62void TestPod(T value)
63{
64    static_assert(std::is_pod<T>::value, "Type is not supported");
65
66    DoTest(value, sizeof(value));
67}
68
69struct PodStruct {
70    uint8_t a;
71    int16_t b;
72    uint32_t c;
73    int64_t d;
74    float e;
75    long double f;
76};
77bool operator==(const PodStruct &lhs, const PodStruct &rhs)
78{
79    return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c && lhs.d == rhs.d && lhs.e == rhs.e && lhs.f == rhs.f;
80}
81
82TEST_F(SerializatorTest, TestPodTypes)
83{
84    TestPod<uint8_t>(0xac);
85    TestPod<uint16_t>(0xc0de);
86    TestPod<uint32_t>(0x123f567f);
87    TestPod<uint64_t>(0xff12345789103c4b);
88
89    TestPod<int8_t>(0x1c);
90    TestPod<int16_t>(0x1ebd);
91    TestPod<int32_t>(0xfe52567f);
92    TestPod<int64_t>(0xff1234fdec57891b);
93
94    TestPod<float>(0.234664);
95    TestPod<double>(22345.3453453);
96    TestPod<long double>(99453.64345);
97
98    TestPod<PodStruct>({0xff, -23458, 10345893, -98343451, -3.54634, 1.44e6});
99}
100
101TEST_F(SerializatorTest, TestString)
102{
103    DoTest<std::string>({}, 4);
104    DoTest<std::string>("", 4);
105    DoTest<std::string>("Hello World!", 4 + 12);
106    DoTest<std::string>("1", 4 + 1);
107    DoTest<std::string>({}, 4);
108}
109
110TEST_F(SerializatorTest, TestVectorPod)
111{
112    DoTest<std::vector<uint8_t>>({1, 2, 3, 4}, 4 + 1 * 4);
113    DoTest<std::vector<uint16_t>>({143, 452, 334}, 4 + 2 * 3);
114    DoTest<std::vector<uint32_t>>({15434, 4564562, 33453, 43456, 346346}, 4 + 5 * 4);
115    DoTest<std::vector<uint64_t>>({14345665644345, 34645345465}, 4 + 8 * 2);
116    DoTest<std::vector<char>>({}, 4 + 1 * 0);
117}
118
119TEST_F(SerializatorTest, TestUnorderedMap1)
120{
121    using Map = std::unordered_map<uint32_t, uint16_t>;
122    DoTest<Map>(
123        {
124            {12343526, 23424},
125            {3, 234356},
126            {45764746, 4},
127        },
128        4 + 3 * (4 + 2));
129}
130
131TEST_F(SerializatorTest, TestUnorderedMap2)
132{
133    using Map = std::unordered_map<std::string, std::string>;
134    DoTest<Map>(
135        {
136            {"one", {}},
137            {"two", "123"},
138            {"three", ""},
139            {"", {}},
140        },
141        4 + 4 + 3 + 4 + 0 + 4 + 3 + 4 + 3 + 4 + 5 + 4 + 0 + 4 + 0 + 4 + 0);
142}
143
144TEST_F(SerializatorTest, TestUnorderedMap3)
145{
146    using Map = std::unordered_map<std::string, std::vector<uint32_t>>;
147    DoTest<Map>(
148        {
149            {"one", {}},
150            {"two", {1, 2, 3, 4}},
151            {"three", {9, 34, 45335}},
152            {"", {}},
153        },
154        4 + 4 + 3 + 4 + 4 * 0 + 4 + 3 + 4 + 4 * 4 + 4 + 5 + 4 + 4 * 3 + 4 + 0 + 4 + 4 * 0);
155}
156
157struct TestStruct {
158    uint8_t a;
159    uint16_t b;
160    uint32_t c;
161    uint64_t d;
162    std::string e;
163    std::vector<int> f;
164};
165bool operator==(const TestStruct &lhs, const TestStruct &rhs)
166{
167    return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c && lhs.d == rhs.d && lhs.e == rhs.e && lhs.f == rhs.f;
168}
169
170TEST_F(SerializatorTest, TestStruct)
171{
172    TestStruct test_struct {1, 2, 3, 4, "Liza", {8, 9, 5}};
173    unsigned test_ret = 1 + 2 + 4 + 8 + 4 + 4 + 4 + sizeof(int) * 3;
174
175    TestStruct a = test_struct;
176    TestStruct b;
177    ASSERT_EQ(serializer::StructToBuffer<6>(a, buffer), true);
178    buffer.resize(4 * buffer.size());
179    auto ret = serializer::RawBufferToStruct<6>(buffer.data(), buffer.size(), b);
180    ASSERT_TRUE(ret.HasValue());
181    ASSERT_EQ(ret.Value(), test_ret);
182    ASSERT_EQ(a, test_struct);
183    ASSERT_EQ(b, test_struct);
184    ASSERT_EQ(a, b);
185}
186
187}  // namespace panda
188