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
21 namespace panda::leb128::test {
22
23 template <class T>
24 struct TestData {
25 T value;
26 size_t size;
27 uint8_t data[10];
28 };
29
30 // clang-format off
31
32 static 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
48 static 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
52 static 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
61 static 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
70 static 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
79 static 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
91 static 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
95 static 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
99 static 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
103 static 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
110 template <class T>
TestDecodeUnsigned(const std::vector<TestData<uint64_t>> & data,bool is_partial=false)111 static 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
TEST(Leb128,DecodeUnsigned)129 TEST(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
138 template <class T>
TestDecodeSigned(const std::vector<TestData<T>> & data,bool is_partial=false)139 static 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
TEST(Leb128,DecodeSigned)157 TEST(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
TEST(Leb128,EncodeUnsigned)170 TEST(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
185 template <class T>
TestEncodeSigned(const std::vector<TestData<T>> & data_vec)186 void 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
TEST(Leb128,EncodeSigned)201 TEST(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