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/patch_utils.h"
6*a03ca8b9SKrzysztof Kosiński
7*a03ca8b9SKrzysztof Kosiński #include <stdint.h>
8*a03ca8b9SKrzysztof Kosiński
9*a03ca8b9SKrzysztof Kosiński #include <iterator>
10*a03ca8b9SKrzysztof Kosiński #include <vector>
11*a03ca8b9SKrzysztof Kosiński
12*a03ca8b9SKrzysztof Kosiński #include "testing/gtest/include/gtest/gtest.h"
13*a03ca8b9SKrzysztof Kosiński
14*a03ca8b9SKrzysztof Kosiński namespace zucchini {
15*a03ca8b9SKrzysztof Kosiński
16*a03ca8b9SKrzysztof Kosiński template <class T>
TestEncodeDecodeVarUInt(const std::vector<T> & data)17*a03ca8b9SKrzysztof Kosiński void TestEncodeDecodeVarUInt(const std::vector<T>& data) {
18*a03ca8b9SKrzysztof Kosiński std::vector<uint8_t> buffer;
19*a03ca8b9SKrzysztof Kosiński
20*a03ca8b9SKrzysztof Kosiński std::vector<T> values;
21*a03ca8b9SKrzysztof Kosiński for (T basis : data) {
22*a03ca8b9SKrzysztof Kosiński // For variety, test the neighborhood values for each case in |data|. Some
23*a03ca8b9SKrzysztof Kosiński // test cases may result in overflow when computing |value|, but we don't
24*a03ca8b9SKrzysztof Kosiński // care about that.
25*a03ca8b9SKrzysztof Kosiński for (int delta = -4; delta <= 4; ++delta) {
26*a03ca8b9SKrzysztof Kosiński T value = delta + basis;
27*a03ca8b9SKrzysztof Kosiński EncodeVarUInt<T>(value, std::back_inserter(buffer));
28*a03ca8b9SKrzysztof Kosiński values.push_back(value);
29*a03ca8b9SKrzysztof Kosiński
30*a03ca8b9SKrzysztof Kosiński value = delta - basis;
31*a03ca8b9SKrzysztof Kosiński EncodeVarUInt<T>(value, std::back_inserter(buffer));
32*a03ca8b9SKrzysztof Kosiński values.push_back(value);
33*a03ca8b9SKrzysztof Kosiński }
34*a03ca8b9SKrzysztof Kosiński }
35*a03ca8b9SKrzysztof Kosiński
36*a03ca8b9SKrzysztof Kosiński auto it = buffer.begin();
37*a03ca8b9SKrzysztof Kosiński for (T expected : values) {
38*a03ca8b9SKrzysztof Kosiński T value = T(-1);
39*a03ca8b9SKrzysztof Kosiński auto res = DecodeVarUInt(it, buffer.end(), &value);
40*a03ca8b9SKrzysztof Kosiński EXPECT_NE(0, res);
41*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(expected, value);
42*a03ca8b9SKrzysztof Kosiński it += res;
43*a03ca8b9SKrzysztof Kosiński }
44*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(it, buffer.end());
45*a03ca8b9SKrzysztof Kosiński
46*a03ca8b9SKrzysztof Kosiński T value = T(-1);
47*a03ca8b9SKrzysztof Kosiński auto res = DecodeVarUInt(it, buffer.end(), &value);
48*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, res);
49*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(T(-1), value);
50*a03ca8b9SKrzysztof Kosiński }
51*a03ca8b9SKrzysztof Kosiński
52*a03ca8b9SKrzysztof Kosiński template <class T>
TestEncodeDecodeVarInt(const std::vector<T> & data)53*a03ca8b9SKrzysztof Kosiński void TestEncodeDecodeVarInt(const std::vector<T>& data) {
54*a03ca8b9SKrzysztof Kosiński std::vector<uint8_t> buffer;
55*a03ca8b9SKrzysztof Kosiński
56*a03ca8b9SKrzysztof Kosiński std::vector<T> values;
57*a03ca8b9SKrzysztof Kosiński for (T basis : data) {
58*a03ca8b9SKrzysztof Kosiński // For variety, test the neighborhood values for each case in |data|. Some
59*a03ca8b9SKrzysztof Kosiński // test cases may result in overflow when computing |value|, but we don't
60*a03ca8b9SKrzysztof Kosiński // care about that.
61*a03ca8b9SKrzysztof Kosiński for (int delta = -4; delta <= 4; ++delta) {
62*a03ca8b9SKrzysztof Kosiński T value = delta + basis;
63*a03ca8b9SKrzysztof Kosiński EncodeVarInt(value, std::back_inserter(buffer));
64*a03ca8b9SKrzysztof Kosiński values.push_back(value);
65*a03ca8b9SKrzysztof Kosiński
66*a03ca8b9SKrzysztof Kosiński value = delta - basis;
67*a03ca8b9SKrzysztof Kosiński EncodeVarInt(value, std::back_inserter(buffer));
68*a03ca8b9SKrzysztof Kosiński values.push_back(value);
69*a03ca8b9SKrzysztof Kosiński }
70*a03ca8b9SKrzysztof Kosiński }
71*a03ca8b9SKrzysztof Kosiński
72*a03ca8b9SKrzysztof Kosiński auto it = buffer.begin();
73*a03ca8b9SKrzysztof Kosiński for (T expected : values) {
74*a03ca8b9SKrzysztof Kosiński T value = T(-1);
75*a03ca8b9SKrzysztof Kosiński auto res = DecodeVarInt(it, buffer.end(), &value);
76*a03ca8b9SKrzysztof Kosiński EXPECT_NE(0, res);
77*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(expected, value);
78*a03ca8b9SKrzysztof Kosiński it += res;
79*a03ca8b9SKrzysztof Kosiński }
80*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(it, buffer.end());
81*a03ca8b9SKrzysztof Kosiński
82*a03ca8b9SKrzysztof Kosiński T value = T(-1);
83*a03ca8b9SKrzysztof Kosiński auto res = DecodeVarInt(it, buffer.end(), &value);
84*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, res);
85*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(T(-1), value);
86*a03ca8b9SKrzysztof Kosiński }
87*a03ca8b9SKrzysztof Kosiński
TEST(PatchUtilsTest,EncodeDecodeVarUInt32)88*a03ca8b9SKrzysztof Kosiński TEST(PatchUtilsTest, EncodeDecodeVarUInt32) {
89*a03ca8b9SKrzysztof Kosiński TestEncodeDecodeVarUInt<uint32_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
90*a03ca8b9SKrzysztof Kosiński 1 << 22, 1 << 27, 1 << 28, 0x7FFFFFFFU,
91*a03ca8b9SKrzysztof Kosiński UINT32_MAX});
92*a03ca8b9SKrzysztof Kosiński }
93*a03ca8b9SKrzysztof Kosiński
TEST(PatchUtilsTest,EncodeDecodeVarInt32)94*a03ca8b9SKrzysztof Kosiński TEST(PatchUtilsTest, EncodeDecodeVarInt32) {
95*a03ca8b9SKrzysztof Kosiński TestEncodeDecodeVarInt<int32_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
96*a03ca8b9SKrzysztof Kosiński 1 << 22, 1 << 27, 1 << 28, -1, INT32_MIN,
97*a03ca8b9SKrzysztof Kosiński INT32_MAX});
98*a03ca8b9SKrzysztof Kosiński }
99*a03ca8b9SKrzysztof Kosiński
TEST(PatchUtilsTest,EncodeDecodeVarUInt64)100*a03ca8b9SKrzysztof Kosiński TEST(PatchUtilsTest, EncodeDecodeVarUInt64) {
101*a03ca8b9SKrzysztof Kosiński TestEncodeDecodeVarUInt<uint64_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
102*a03ca8b9SKrzysztof Kosiński 1 << 22, 1ULL << 55, 1ULL << 56,
103*a03ca8b9SKrzysztof Kosiński 0x7FFFFFFFFFFFFFFFULL, UINT64_MAX});
104*a03ca8b9SKrzysztof Kosiński }
105*a03ca8b9SKrzysztof Kosiński
TEST(PatchUtilsTest,EncodeDecodeVarInt64)106*a03ca8b9SKrzysztof Kosiński TEST(PatchUtilsTest, EncodeDecodeVarInt64) {
107*a03ca8b9SKrzysztof Kosiński TestEncodeDecodeVarInt<int64_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
108*a03ca8b9SKrzysztof Kosiński 1 << 22, 1LL << 55, 1LL << 56, -1, INT64_MIN,
109*a03ca8b9SKrzysztof Kosiński INT64_MAX});
110*a03ca8b9SKrzysztof Kosiński }
111*a03ca8b9SKrzysztof Kosiński
TEST(PatchUtilsTest,DecodeVarUInt32Malformed)112*a03ca8b9SKrzysztof Kosiński TEST(PatchUtilsTest, DecodeVarUInt32Malformed) {
113*a03ca8b9SKrzysztof Kosiński constexpr uint32_t kUninit = static_cast<uint32_t>(-1LL);
114*a03ca8b9SKrzysztof Kosiński
115*a03ca8b9SKrzysztof Kosiński // Output variable to ensure that on failure, the output variable is not
116*a03ca8b9SKrzysztof Kosiński // written to.
117*a03ca8b9SKrzysztof Kosiński uint32_t value = uint32_t(-1);
118*a03ca8b9SKrzysztof Kosiński
119*a03ca8b9SKrzysztof Kosiński auto TestDecodeVarInt = [&value](const std::vector<uint8_t>& buffer) {
120*a03ca8b9SKrzysztof Kosiński value = kUninit;
121*a03ca8b9SKrzysztof Kosiński return DecodeVarUInt(buffer.begin(), buffer.end(), &value);
122*a03ca8b9SKrzysztof Kosiński };
123*a03ca8b9SKrzysztof Kosiński
124*a03ca8b9SKrzysztof Kosiński // Exhausted.
125*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>{}));
126*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
127*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(4, 128)));
128*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
129*a03ca8b9SKrzysztof Kosiński
130*a03ca8b9SKrzysztof Kosiński // Overflow.
131*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(6, 128)));
132*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
133*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt({128, 128, 128, 128, 128, 42}));
134*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
135*a03ca8b9SKrzysztof Kosiński
136*a03ca8b9SKrzysztof Kosiński // Following are pathological cases that are not handled for simplicity,
137*a03ca8b9SKrzysztof Kosiński // hence decoding is expected to be successful.
138*a03ca8b9SKrzysztof Kosiński EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 16}));
139*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(uint32_t(0), value);
140*a03ca8b9SKrzysztof Kosiński EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 32}));
141*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(uint32_t(0), value);
142*a03ca8b9SKrzysztof Kosiński EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 64}));
143*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(uint32_t(0), value);
144*a03ca8b9SKrzysztof Kosiński }
145*a03ca8b9SKrzysztof Kosiński
TEST(PatchUtilsTest,DecodeVarUInt64Malformed)146*a03ca8b9SKrzysztof Kosiński TEST(PatchUtilsTest, DecodeVarUInt64Malformed) {
147*a03ca8b9SKrzysztof Kosiński constexpr uint64_t kUninit = static_cast<uint64_t>(-1);
148*a03ca8b9SKrzysztof Kosiński
149*a03ca8b9SKrzysztof Kosiński uint64_t value = kUninit;
150*a03ca8b9SKrzysztof Kosiński auto TestDecodeVarInt = [&value](const std::vector<uint8_t>& buffer) {
151*a03ca8b9SKrzysztof Kosiński value = kUninit;
152*a03ca8b9SKrzysztof Kosiński return DecodeVarUInt(buffer.begin(), buffer.end(), &value);
153*a03ca8b9SKrzysztof Kosiński };
154*a03ca8b9SKrzysztof Kosiński
155*a03ca8b9SKrzysztof Kosiński // Exhausted.
156*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>{}));
157*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
158*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(9, 128)));
159*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
160*a03ca8b9SKrzysztof Kosiński
161*a03ca8b9SKrzysztof Kosiński // Overflow.
162*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(10, 128)));
163*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
164*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(0, TestDecodeVarInt(
165*a03ca8b9SKrzysztof Kosiński {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 42}));
166*a03ca8b9SKrzysztof Kosiński EXPECT_EQ(kUninit, value);
167*a03ca8b9SKrzysztof Kosiński }
168*a03ca8b9SKrzysztof Kosiński
169*a03ca8b9SKrzysztof Kosiński } // namespace zucchini
170