blob: 81e4e389ef6f19768c4409346c0c39185c7d16b8 [file] [log] [blame]
Samuel Huang06f1ae92018-03-13 18:19:34 +00001// 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
14namespace zucchini {
15
16template <class T>
17void 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
52template <class T>
53void 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
88TEST(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
94TEST(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
100TEST(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
106TEST(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
112TEST(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
Takuto Ikutad60fe382018-10-18 10:46:07 +0000119 auto TestDecodeVarInt = [&value](const std::vector<uint8_t>& buffer) {
Samuel Huang06f1ae92018-03-13 18:19:34 +0000120 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
146TEST(PatchUtilsTest, DecodeVarUInt64Malformed) {
147 constexpr uint64_t kUninit = static_cast<uint64_t>(-1);
148
149 uint64_t value = kUninit;
Takuto Ikutad60fe382018-10-18 10:46:07 +0000150 auto TestDecodeVarInt = [&value](const std::vector<uint8_t>& buffer) {
Samuel Huang06f1ae92018-03-13 18:19:34 +0000151 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