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