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 "utils/leb128.h"
17
18#include <gmock/gmock.h>
19#include <gtest/gtest.h>
20
21namespace panda::leb128::test {
22
23template <class T>
24struct TestData {
25    T value;
26    size_t size;
27    uint8_t data[10];
28};
29
30// clang-format off
31
32static std::vector<TestData<uint64_t>> unsigned_test_data {
33    {0x00,                1, {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
34    {0x7f,                1, {0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
35    {0xff,                2, {0xff, 0x01, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
36    {0x2d7f,              2, {0xff, 0x5a, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
37    {0xffff,              3, {0xff, 0xff, 0x03, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
38    {0x192d7f,            3, {0xff, 0xda, 0x64, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
39    {0x1592d7f,           4, {0xff, 0xda, 0xe4, 0x0a, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
40    {0x11592d7f,          5, {0xff, 0xda, 0xe4, 0x8a, 0x01, 0x80, 0x80, 0x80, 0x80, 0x80}},
41    {0xffffffff,          5, {0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x80}},
42    {0x1011592d7f,        6, {0xff, 0xda, 0xe4, 0x8a, 0x81, 0x02, 0x80, 0x80, 0x80, 0x80}},
43    {0xc1011592d7f,       7, {0xff, 0xda, 0xe4, 0x8a, 0x81, 0x82, 0x03, 0x80, 0x80, 0x80}},
44    {0x80c1011592d7f,     8, {0xff, 0xda, 0xe4, 0x8a, 0x81, 0x82, 0x83, 0x04, 0x80, 0x80}},
45    {0xffffffffffffffff, 10, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}}
46};
47
48static std::vector<TestData<uint64_t>> unsigned_partial_decoding_test_data {
49    {0xffffffffffffffff, 10, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03}},
50};
51
52static std::vector<TestData<int8_t>> signed_test_data8 {
53    {0x00,                      1, {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
54    {0x01,                      1, {0x01, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
55    {-1,                        1, {0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
56    {0x40,                      2, {0xc0, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
57    {static_cast<int8_t>(0x80), 2, {0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
58    {-0x40,                     1, {0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}}
59};
60
61static std::vector<TestData<int16_t>> signed_test_data16 {
62    {0x00,                         1, {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
63    {0x0102,                       2, {0x82, 0x02, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
64    {-1,                           1, {0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
65    {-0x40,                        1, {0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
66    {static_cast<int16_t>(0x8000), 3, {0x80, 0x80, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
67    {static_cast<int16_t>(0x4001), 3, {0x81, 0x80, 0x01, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}}
68};
69
70static std::vector<TestData<int32_t>> signed_test_data32 {
71    {0x00,                             1, {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
72    {0x01020304,                       4, {0x84, 0x86, 0x88, 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
73    {-1,                               1, {0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
74    {-0x40,                            1, {0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
75    {static_cast<int32_t>(0x80000000), 5, {0x80, 0x80, 0x80, 0x80, 0x78, 0x80, 0x80, 0x80, 0x80, 0x80}},
76    {static_cast<int32_t>(0x40000001), 5, {0x81, 0x80, 0x80, 0x80, 0x04, 0x80, 0x80, 0x80, 0x80, 0x80}}
77};
78
79static std::vector<TestData<int64_t>> signed_test_data64 {
80    {0x00,                                      1, {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
81    {0x40,                                      2, {0xc0, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
82    {0x7f,                                      2, {0xff, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
83    {-1,                                        1, {0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
84    {static_cast<int64_t>(0x8000000000000000), 10, {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f}},
85    {0x7000000000000001,                       10, {0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x00}},
86    {0x100000000000000,                         9, {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01, 0x00}},
87    {-0x40,                                     1, {0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}},
88    {-0x1122,                                   2, {0xde, 0x5d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}}
89};
90
91static std::vector<TestData<int8_t>> signed_partial_decoding_test_data8 {
92    {1, 10, {0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a}}
93};
94
95static std::vector<TestData<int16_t>> signed_partial_decoding_test_data16 {
96    {-0x3eff, 10, {0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a}}
97};
98
99static std::vector<TestData<int32_t>> signed_partial_decoding_test_data32 {
100    {0x5080c101, 10, {0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a}}
101};
102
103static std::vector<TestData<int64_t>> signed_partial_decoding_test_data64 {
104    {0x9101c305080c101,                        10, {0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a}},
105    {static_cast<int64_t>(0x8000000000000000), 10, {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x5f}}
106};
107
108// clang-format on
109
110template <class T>
111static void TestDecodeUnsigned(const std::vector<TestData<uint64_t>> &data, bool is_partial = false)
112{
113    for (auto &t : data) {
114        std::ostringstream ss;
115        ss << "Test unsigned decoding ";
116        ss << std::hex << t.value;
117        ss << " with sizeof(T) = ";
118        ss << sizeof(T);
119
120        constexpr size_t bitwidth = std::numeric_limits<T>::digits;
121
122        auto [value, size, is_full] = DecodeUnsigned<T>(t.data);
123        EXPECT_EQ(is_full, MinimumBitsToStore(t.value) <= bitwidth && !is_partial) << ss.str();
124        EXPECT_EQ(size, is_full ? t.size : (bitwidth + 6) / 7) << ss.str();
125        EXPECT_EQ(value, static_cast<T>(t.value)) << ss.str();
126    }
127}
128
129TEST(Leb128, DecodeUnsigned)
130{
131    TestDecodeUnsigned<uint8_t>(unsigned_test_data);
132    TestDecodeUnsigned<uint16_t>(unsigned_test_data);
133    TestDecodeUnsigned<uint32_t>(unsigned_test_data);
134    TestDecodeUnsigned<uint64_t>(unsigned_test_data);
135    TestDecodeUnsigned<uint64_t>(unsigned_partial_decoding_test_data, true);
136}
137
138template <class T>
139static void TestDecodeSigned(const std::vector<TestData<T>> &data, bool is_partial = false)
140{
141    for (auto &t : data) {
142        std::ostringstream ss;
143        ss << "Test signed decoding ";
144        ss << std::hex << static_cast<int64_t>(t.value);
145        ss << " with sizeof(T) = ";
146        ss << sizeof(T);
147
148        constexpr size_t bitwidth = std::numeric_limits<std::make_unsigned_t<T>>::digits;
149
150        auto [value, size, is_full] = DecodeSigned<T>(t.data);
151        EXPECT_EQ(is_full, !is_partial) << ss.str();
152        EXPECT_EQ(size, is_full ? t.size : (bitwidth + 6) / 7) << ss.str();
153        EXPECT_EQ(value, t.value) << ss.str();
154    }
155}
156
157TEST(Leb128, DecodeSigned)
158{
159    TestDecodeSigned(signed_test_data8);
160    TestDecodeSigned(signed_test_data16);
161    TestDecodeSigned(signed_test_data32);
162    TestDecodeSigned(signed_test_data64);
163
164    TestDecodeSigned(signed_partial_decoding_test_data8, true);
165    TestDecodeSigned(signed_partial_decoding_test_data16, true);
166    TestDecodeSigned(signed_partial_decoding_test_data32, true);
167    TestDecodeSigned(signed_partial_decoding_test_data64, true);
168}
169
170TEST(Leb128, EncodeUnsigned)
171{
172    for (auto &t : unsigned_test_data) {
173        std::ostringstream ss;
174        ss << "Test unsigned encoding ";
175        ss << std::hex << t.value;
176
177        std::vector<uint8_t> data(t.size);
178        size_t n = EncodeUnsigned(t.value, data.data());
179        EXPECT_EQ(n, t.size) << ss.str();
180        EXPECT_EQ(UnsignedEncodingSize(t.value), t.size) << ss.str();
181        EXPECT_THAT(data, ::testing::ElementsAreArray(t.data, t.size)) << ss.str();
182    }
183}
184
185template <class T>
186void TestEncodeSigned(const std::vector<TestData<T>> &data_vec)
187{
188    for (auto &t : data_vec) {
189        std::ostringstream ss;
190        ss << "Test signed encoding ";
191        ss << std::hex << static_cast<int64_t>(t.value);
192
193        std::vector<uint8_t> data(t.size);
194        size_t n = EncodeSigned(t.value, data.data());
195        EXPECT_EQ(n, t.size) << ss.str();
196        EXPECT_EQ(SignedEncodingSize(t.value), t.size) << ss.str();
197        EXPECT_THAT(data, ::testing::ElementsAreArray(t.data, t.size)) << ss.str();
198    }
199}
200
201TEST(Leb128, EncodeSigned)
202{
203    TestEncodeSigned(signed_test_data8);
204    TestEncodeSigned(signed_test_data16);
205    TestEncodeSigned(signed_test_data32);
206    TestEncodeSigned(signed_test_data64);
207}
208
209}  // namespace panda::leb128::test
210