xref: /aosp_15_r20/external/zucchini/buffer_source_unittest.cc (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved.
2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be
3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file.
4*a03ca8b9SKrzysztof Kosiński 
5*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/buffer_source.h"
6*a03ca8b9SKrzysztof Kosiński 
7*a03ca8b9SKrzysztof Kosiński #include <stddef.h>
8*a03ca8b9SKrzysztof Kosiński #include <stdint.h>
9*a03ca8b9SKrzysztof Kosiński 
10*a03ca8b9SKrzysztof Kosiński #include <iterator>
11*a03ca8b9SKrzysztof Kosiński #include <string>
12*a03ca8b9SKrzysztof Kosiński #include <tuple>
13*a03ca8b9SKrzysztof Kosiński #include <vector>
14*a03ca8b9SKrzysztof Kosiński 
15*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/test_utils.h"
16*a03ca8b9SKrzysztof Kosiński #include "testing/gtest/include/gtest/gtest.h"
17*a03ca8b9SKrzysztof Kosiński 
18*a03ca8b9SKrzysztof Kosiński namespace zucchini {
19*a03ca8b9SKrzysztof Kosiński 
20*a03ca8b9SKrzysztof Kosiński using vec = std::vector<uint8_t>;
21*a03ca8b9SKrzysztof Kosiński 
22*a03ca8b9SKrzysztof Kosiński class BufferSourceTest : public testing::Test {
23*a03ca8b9SKrzysztof Kosiński  protected:
24*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> bytes_ = ParseHexString("10 32 54 76 98 BA DC FE 10 00");
25*a03ca8b9SKrzysztof Kosiński 
26*a03ca8b9SKrzysztof Kosiński   BufferSource source_ = {bytes_.data(), bytes_.size()};
27*a03ca8b9SKrzysztof Kosiński };
28*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,Skip)29*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, Skip) {
30*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(bytes_.size(), source_.Remaining());
31*a03ca8b9SKrzysztof Kosiński   source_.Skip(2);
32*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(bytes_.size() - 2, source_.Remaining());
33*a03ca8b9SKrzysztof Kosiński   source_.Skip(10);  // Skipping past end just moves cursor to end.
34*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(0), source_.Remaining());
35*a03ca8b9SKrzysztof Kosiński }
36*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,CheckNextBytes)37*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, CheckNextBytes) {
38*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.CheckNextBytes({0x10, 0x32, 0x54, 0x76}));
39*a03ca8b9SKrzysztof Kosiński   source_.Skip(4);
40*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.CheckNextBytes({0x98, 0xBA, 0xDC, 0xFE}));
41*a03ca8b9SKrzysztof Kosiński 
42*a03ca8b9SKrzysztof Kosiński   // Cursor has not advanced, so check fails.
43*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.CheckNextBytes({0x10, 0x00}));
44*a03ca8b9SKrzysztof Kosiński 
45*a03ca8b9SKrzysztof Kosiński   source_.Skip(4);
46*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
47*a03ca8b9SKrzysztof Kosiński 
48*a03ca8b9SKrzysztof Kosiński   // Goes beyond end by 2 bytes.
49*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.CheckNextBytes({0x10, 0x00, 0x00, 0x00}));
50*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
51*a03ca8b9SKrzysztof Kosiński }
52*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,ConsumeBytes)53*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, ConsumeBytes) {
54*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.ConsumeBytes({0x10, 0x00}));
55*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(bytes_.size(), source_.Remaining());
56*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.ConsumeBytes({0x10, 0x32, 0x54, 0x76}));
57*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(6), source_.Remaining());
58*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.ConsumeBytes({0x98, 0xBA, 0xDC, 0xFE}));
59*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
60*a03ca8b9SKrzysztof Kosiński 
61*a03ca8b9SKrzysztof Kosiński   // Goes beyond end by 2 bytes.
62*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.ConsumeBytes({0x10, 0x00, 0x00, 0x00}));
63*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
64*a03ca8b9SKrzysztof Kosiński }
65*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,CheckNextValue)66*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, CheckNextValue) {
67*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.CheckNextValue(uint32_t(0x76543210)));
68*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.CheckNextValue(uint32_t(0x0)));
69*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.CheckNextValue(uint64_t(0xFEDCBA9876543210)));
70*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.CheckNextValue(uint64_t(0x0)));
71*a03ca8b9SKrzysztof Kosiński 
72*a03ca8b9SKrzysztof Kosiński   source_.Skip(8);
73*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
74*a03ca8b9SKrzysztof Kosiński 
75*a03ca8b9SKrzysztof Kosiński   // Goes beyond end by 2 bytes.
76*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.CheckNextValue(uint32_t(0x1000)));
77*a03ca8b9SKrzysztof Kosiński }
78*a03ca8b9SKrzysztof Kosiński 
79*a03ca8b9SKrzysztof Kosiński // Supported by MSVC, g++, and clang++.
80*a03ca8b9SKrzysztof Kosiński // Ensures no gaps in packing.
81*a03ca8b9SKrzysztof Kosiński #pragma pack(push, 1)
82*a03ca8b9SKrzysztof Kosiński struct ValueType {
83*a03ca8b9SKrzysztof Kosiński   uint32_t a;
84*a03ca8b9SKrzysztof Kosiński   uint16_t b;
85*a03ca8b9SKrzysztof Kosiński };
86*a03ca8b9SKrzysztof Kosiński #pragma pack(pop)
87*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetValueIntegral)88*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetValueIntegral) {
89*a03ca8b9SKrzysztof Kosiński   uint32_t value = 0;
90*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.GetValue(&value));
91*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0x76543210), value);
92*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(6), source_.Remaining());
93*a03ca8b9SKrzysztof Kosiński 
94*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.GetValue(&value));
95*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0xFEDCBA98), value);
96*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
97*a03ca8b9SKrzysztof Kosiński 
98*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.GetValue(&value));
99*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
100*a03ca8b9SKrzysztof Kosiński }
101*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetValueAggregate)102*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetValueAggregate) {
103*a03ca8b9SKrzysztof Kosiński   ValueType value = {};
104*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.GetValue(&value));
105*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0x76543210), value.a);
106*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0xBA98), value.b);
107*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(4), source_.Remaining());
108*a03ca8b9SKrzysztof Kosiński }
109*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetRegion)110*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetRegion) {
111*a03ca8b9SKrzysztof Kosiński   ConstBufferView region;
112*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.GetRegion(0, &region));
113*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(bytes_.size(), source_.Remaining());
114*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(region.empty());
115*a03ca8b9SKrzysztof Kosiński 
116*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(source_.GetRegion(2, &region));
117*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), region.size());
118*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(vec({0x10, 0x32}), vec(region.begin(), region.end()));
119*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(8), source_.Remaining());
120*a03ca8b9SKrzysztof Kosiński 
121*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(source_.GetRegion(bytes_.size(), &region));
122*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(8), source_.Remaining());
123*a03ca8b9SKrzysztof Kosiński   // |region| is left untouched.
124*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(vec({0x10, 0x32}), vec(region.begin(), region.end()));
125*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), region.size());
126*a03ca8b9SKrzysztof Kosiński }
127*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetPointerIntegral)128*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetPointerIntegral) {
129*a03ca8b9SKrzysztof Kosiński   const uint32_t* ptr = source_.GetPointer<uint32_t>();
130*a03ca8b9SKrzysztof Kosiński   EXPECT_NE(nullptr, ptr);
131*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0x76543210), *ptr);
132*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(6), source_.Remaining());
133*a03ca8b9SKrzysztof Kosiński 
134*a03ca8b9SKrzysztof Kosiński   ptr = source_.GetPointer<uint32_t>();
135*a03ca8b9SKrzysztof Kosiński   EXPECT_NE(nullptr, ptr);
136*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0xFEDCBA98), *ptr);
137*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
138*a03ca8b9SKrzysztof Kosiński 
139*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(nullptr, source_.GetPointer<uint32_t>());
140*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
141*a03ca8b9SKrzysztof Kosiński }
142*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetPointerAggregate)143*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetPointerAggregate) {
144*a03ca8b9SKrzysztof Kosiński   const ValueType* ptr = source_.GetPointer<ValueType>();
145*a03ca8b9SKrzysztof Kosiński   EXPECT_NE(nullptr, ptr);
146*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0x76543210), ptr->a);
147*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0xBA98), ptr->b);
148*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(4), source_.Remaining());
149*a03ca8b9SKrzysztof Kosiński }
150*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetArrayIntegral)151*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetArrayIntegral) {
152*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(nullptr, source_.GetArray<uint32_t>(3));
153*a03ca8b9SKrzysztof Kosiński 
154*a03ca8b9SKrzysztof Kosiński   const uint32_t* ptr = source_.GetArray<uint32_t>(2);
155*a03ca8b9SKrzysztof Kosiński   EXPECT_NE(nullptr, ptr);
156*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0x76543210), ptr[0]);
157*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0xFEDCBA98), ptr[1]);
158*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(2), source_.Remaining());
159*a03ca8b9SKrzysztof Kosiński }
160*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetArrayAggregate)161*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetArrayAggregate) {
162*a03ca8b9SKrzysztof Kosiński   const ValueType* ptr = source_.GetArray<ValueType>(2);
163*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(nullptr, ptr);
164*a03ca8b9SKrzysztof Kosiński 
165*a03ca8b9SKrzysztof Kosiński   ptr = source_.GetArray<ValueType>(1);
166*a03ca8b9SKrzysztof Kosiński 
167*a03ca8b9SKrzysztof Kosiński   EXPECT_NE(nullptr, ptr);
168*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0x76543210), ptr[0].a);
169*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(uint32_t(0xBA98), ptr[0].b);
170*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(size_t(4), source_.Remaining());
171*a03ca8b9SKrzysztof Kosiński }
172*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetUleb128)173*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetUleb128) {
174*a03ca8b9SKrzysztof Kosiński   using size_type = BufferSource::size_type;
175*a03ca8b9SKrzysztof Kosiński   // Result = {success, value, bytes_consumed}.
176*a03ca8b9SKrzysztof Kosiński   using Result = std::tuple<bool, uint32_t, size_type>;
177*a03ca8b9SKrzysztof Kosiński 
178*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kUnInit = 0xCCCCCCCC;  // Arbitrary value.
179*a03ca8b9SKrzysztof Kosiński   constexpr Result kBad{false, kUnInit, 0U};
180*a03ca8b9SKrzysztof Kosiński 
181*a03ca8b9SKrzysztof Kosiński   auto run = [](const std::string hex_string) -> Result {
182*a03ca8b9SKrzysztof Kosiński     std::vector<uint8_t> bytes = ParseHexString(hex_string);
183*a03ca8b9SKrzysztof Kosiński     BufferSource source(ConstBufferView{bytes.data(), bytes.size()});
184*a03ca8b9SKrzysztof Kosiński     BufferSource::iterator base = source.begin();
185*a03ca8b9SKrzysztof Kosiński     // Initialize |value| to |kUnInit| to ensure no write on failure.
186*a03ca8b9SKrzysztof Kosiński     uint32_t value = kUnInit;
187*a03ca8b9SKrzysztof Kosiński     bool success = source.GetUleb128(&value);
188*a03ca8b9SKrzysztof Kosiński     return {success, value, source.begin() - base};
189*a03ca8b9SKrzysztof Kosiński   };
190*a03ca8b9SKrzysztof Kosiński 
191*a03ca8b9SKrzysztof Kosiński   auto good = [](uint32_t value, size_type bytes_consumed) -> Result {
192*a03ca8b9SKrzysztof Kosiński     return Result{true, value, bytes_consumed};
193*a03ca8b9SKrzysztof Kosiński   };
194*a03ca8b9SKrzysztof Kosiński 
195*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0U, 1U), run("00"));
196*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x20U, 1U), run("20"));
197*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x42U, 1U), run("42"));
198*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x7FU, 1U), run("7F"));
199*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80"));               // Out of data.
200*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0U, 2U), run("80 00"));  // Redundant code.
201*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x80U, 2U), run("80 01"));
202*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x7FU, 2U), run("FF 00"));  // Redundant (unsigned).
203*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x3FFFU, 2U), run("FF 7F"));
204*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0U, 1U), run("00 80"));     // Only reads byte 0.
205*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80 80"));               // Out of data.
206*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("F1 88"));               // Out of data.
207*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0U, 3U), run("80 80 00"));  // Redundant code.
208*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x4000U, 3U), run("80 80 01"));
209*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x00100000U, 3U), run("80 80 40"));
210*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x001FFFFFU, 3U), run("FF FF 7F"));
211*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0U, 1U), run("00 00 80"));     // Only reads byte 0.
212*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80 80 80"));               // Out of data.
213*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("AB CD EF"));               // Out of data.
214*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0U, 4U), run("80 80 80 00"));  // Redundant code.
215*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x00100000U, 4U), run("80 80 C0 00"));
216*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x00200000U, 4U), run("80 80 80 01"));
217*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x08000000U, 4U), run("80 80 80 40"));
218*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x001FC07FU, 4U), run("FF 80 FF 00"));
219*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0U, 5U), run("80 80 80 80 00"));  // Redundant code.
220*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x10000000U, 5U), run("80 80 80 80 01"));
221*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x10204081U, 5U), run("81 81 81 81 01"));
222*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x7FFFFFFFU, 5U), run("FF FF FF FF 07"));
223*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x80000000U, 5U), run("80 80 80 80 08"));
224*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0xFFFFFFFFU, 5U), run("FF FF FF FF 0F"));
225*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("FF FF FF FF 80"));  // Too long / out of data.
226*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0FFFFFFFU, 5U), run("FF FF FF FF 10"));  // "1" discarded.
227*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x00000000U, 5U), run("80 80 80 80 20"));  // "2" discarded.
228*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0xA54A952AU, 5U), run("AA AA AA AA 7A"));  // "7" discarded.
229*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("FF FF FF FF FF 00"));                // Too long.
230*a03ca8b9SKrzysztof Kosiński }
231*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,GetSleb128)232*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, GetSleb128) {
233*a03ca8b9SKrzysztof Kosiński   using size_type = BufferSource::size_type;
234*a03ca8b9SKrzysztof Kosiński   // Result = {success, value, bytes_consumed}.
235*a03ca8b9SKrzysztof Kosiński   using Result = std::tuple<bool, int32_t, size_type>;
236*a03ca8b9SKrzysztof Kosiński 
237*a03ca8b9SKrzysztof Kosiński   constexpr int32_t kUnInit = 0xCCCCCCCC;  // Arbitrary value.
238*a03ca8b9SKrzysztof Kosiński   constexpr Result kBad{false, kUnInit, 0U};
239*a03ca8b9SKrzysztof Kosiński 
240*a03ca8b9SKrzysztof Kosiński   auto run = [](const std::string hex_string) -> Result {
241*a03ca8b9SKrzysztof Kosiński     std::vector<uint8_t> bytes = ParseHexString(hex_string);
242*a03ca8b9SKrzysztof Kosiński     BufferSource source(ConstBufferView{bytes.data(), bytes.size()});
243*a03ca8b9SKrzysztof Kosiński     BufferSource::iterator base = source.begin();
244*a03ca8b9SKrzysztof Kosiński     // Initialize |value| to |kUnInit| to ensure no write on failure.
245*a03ca8b9SKrzysztof Kosiński     int32_t value = kUnInit;
246*a03ca8b9SKrzysztof Kosiński     bool success = source.GetSleb128(&value);
247*a03ca8b9SKrzysztof Kosiński     return {success, value, source.begin() - base};
248*a03ca8b9SKrzysztof Kosiński   };
249*a03ca8b9SKrzysztof Kosiński 
250*a03ca8b9SKrzysztof Kosiński   auto good = [](int32_t value, size_type bytes_consumed) -> Result {
251*a03ca8b9SKrzysztof Kosiński     return Result{true, value, bytes_consumed};
252*a03ca8b9SKrzysztof Kosiński   };
253*a03ca8b9SKrzysztof Kosiński 
254*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0, 1U), run("00"));
255*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x20U, 1U), run("20"));
256*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-0x3E, 1U), run("42"));
257*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-0x1, 1U), run("7F"));
258*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80"));              // Out of data.
259*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0, 2U), run("80 00"));  // Redundant code.
260*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x80, 2U), run("80 01"));
261*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x7F, 2U), run("FF 00"));    // Not redudnant.
262*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-0x1, 2U), run("FF 7F"));    // Redundant code.
263*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0, 1U), run("00 80"));     // Only reads byte 0.
264*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80 80"));              // Out of data.
265*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("F1 88"));              // Out of data.
266*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0, 3U), run("80 80 00"));  // Redundant code.
267*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x4000, 3U), run("80 80 01"));
268*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-0x100000, 3U), run("80 80 40"));
269*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-0x1, 3U), run("FF FF 7F"));    // Redundant code.
270*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0, 1U), run("00 00 80"));     // Only reads byte 0.
271*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80 80 80"));              // Out of data.
272*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("AB CD EF"));              // Out of data.
273*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0, 4U), run("80 80 80 00"));  // Redundant code.
274*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x00100000, 4U), run("80 80 C0 00"));
275*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x00200000, 4U), run("80 80 80 01"));
276*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-static_cast<int32_t>(0x08000000), 4U), run("80 80 80 40"));
277*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x001FC07F, 4U), run("FF 80 FF 00"));
278*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0, 5U), run("80 80 80 80 00"));  // Redundant code.
279*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x10000000, 5U), run("80 80 80 80 01"));
280*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x10204081, 5U), run("81 81 81 81 01"));
281*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x7FFFFFFF, 5U), run("FF FF FF FF 07"));
282*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-static_cast<int32_t>(0x80000000), 5U), run("80 80 80 80 08"));
283*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-0x1, 5U), run("FF FF FF FF 0F"));  // Redundant code.
284*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("FF FF FF FF 80"));            // Too long / out of data.
285*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x0FFFFFFF, 5U), run("FF FF FF FF 10"));   // "1" discarded.
286*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(0x00000000, 5U), run("80 80 80 80 20"));   // "2" discarded.
287*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(-0x5AB56AD6, 5U), run("AA AA AA AA 7A"));  // "7" discarded.
288*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("FF FF FF FF FF 00"));                // Too long.
289*a03ca8b9SKrzysztof Kosiński }
290*a03ca8b9SKrzysztof Kosiński 
TEST_F(BufferSourceTest,SkipLeb128)291*a03ca8b9SKrzysztof Kosiński TEST_F(BufferSourceTest, SkipLeb128) {
292*a03ca8b9SKrzysztof Kosiński   using size_type = BufferSource::size_type;
293*a03ca8b9SKrzysztof Kosiński   // Result = {success, value, bytes_consumed}.
294*a03ca8b9SKrzysztof Kosiński   using Result = std::tuple<bool, size_type>;
295*a03ca8b9SKrzysztof Kosiński 
296*a03ca8b9SKrzysztof Kosiński   constexpr Result kBad{false, 0U};
297*a03ca8b9SKrzysztof Kosiński 
298*a03ca8b9SKrzysztof Kosiński   auto run = [](const std::string hex_string) -> Result {
299*a03ca8b9SKrzysztof Kosiński     std::vector<uint8_t> bytes = ParseHexString(hex_string);
300*a03ca8b9SKrzysztof Kosiński     BufferSource source(ConstBufferView{bytes.data(), bytes.size()});
301*a03ca8b9SKrzysztof Kosiński     BufferSource::iterator base = source.begin();
302*a03ca8b9SKrzysztof Kosiński     bool success = source.SkipLeb128();
303*a03ca8b9SKrzysztof Kosiński     return {success, source.begin() - base};
304*a03ca8b9SKrzysztof Kosiński   };
305*a03ca8b9SKrzysztof Kosiński 
306*a03ca8b9SKrzysztof Kosiński   auto good = [](size_type bytes_consumed) -> Result {
307*a03ca8b9SKrzysztof Kosiński     return Result{true, bytes_consumed};
308*a03ca8b9SKrzysztof Kosiński   };
309*a03ca8b9SKrzysztof Kosiński 
310*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(1U), run("00"));
311*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(1U), run("20"));
312*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(1U), run("42"));
313*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(1U), run("7F"));
314*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80"));         // Out of data.
315*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(2U), run("80 00"));  // Redundant code.
316*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(2U), run("80 01"));
317*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(2U), run("FF 00"));  // Redundant (unsigned).
318*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(2U), run("FF 7F"));
319*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(1U), run("00 80"));     // Only reads byte 0.
320*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80 80"));         // Out of data.
321*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("F1 88"));         // Out of data.
322*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(3U), run("80 80 00"));  // Redundant code.
323*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(3U), run("80 80 01"));
324*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(3U), run("80 80 40"));
325*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(3U), run("FF FF 7F"));
326*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(1U), run("00 00 80"));     // Only reads byte 0.
327*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("80 80 80"));         // Out of data.
328*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("AB CD EF"));         // Out of data.
329*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(4U), run("80 80 80 00"));  // Redundant code.
330*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(4U), run("80 80 C0 00"));
331*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(4U), run("80 80 80 01"));
332*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(4U), run("80 80 80 40"));
333*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(4U), run("FF 80 FF 00"));
334*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("80 80 80 80 00"));  // Redundant code.
335*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("80 80 80 80 01"));
336*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("81 81 81 81 01"));
337*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("FF FF FF FF 07"));
338*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("80 80 80 80 08"));
339*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("FF FF FF FF 0F"));
340*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("FF FF FF FF 80"));      // Too long / out of data.
341*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("FF FF FF FF 10"));  // "1" discarded.
342*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("80 80 80 80 20"));  // "2" discarded.
343*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(good(5U), run("AA AA AA AA 7A"));  // "7" discarded.
344*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kBad, run("FF FF FF FF FF 00"));   // Too long.
345*a03ca8b9SKrzysztof Kosiński }
346*a03ca8b9SKrzysztof Kosiński 
347*a03ca8b9SKrzysztof Kosiński }  // namespace zucchini
348