xref: /aosp_15_r20/external/zucchini/patch_utils_unittest.cc (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
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