aboutsummaryrefslogtreecommitdiff
path: root/patch_utils_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'patch_utils_unittest.cc')
-rw-r--r--patch_utils_unittest.cc169
1 files changed, 169 insertions, 0 deletions
diff --git a/patch_utils_unittest.cc b/patch_utils_unittest.cc
new file mode 100644
index 0000000..81e4e38
--- /dev/null
+++ b/patch_utils_unittest.cc
@@ -0,0 +1,169 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/zucchini/patch_utils.h"
+
+#include <stdint.h>
+
+#include <iterator>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace zucchini {
+
+template <class T>
+void TestEncodeDecodeVarUInt(const std::vector<T>& data) {
+ std::vector<uint8_t> buffer;
+
+ std::vector<T> values;
+ for (T basis : data) {
+ // For variety, test the neighborhood values for each case in |data|. Some
+ // test cases may result in overflow when computing |value|, but we don't
+ // care about that.
+ for (int delta = -4; delta <= 4; ++delta) {
+ T value = delta + basis;
+ EncodeVarUInt<T>(value, std::back_inserter(buffer));
+ values.push_back(value);
+
+ value = delta - basis;
+ EncodeVarUInt<T>(value, std::back_inserter(buffer));
+ values.push_back(value);
+ }
+ }
+
+ auto it = buffer.begin();
+ for (T expected : values) {
+ T value = T(-1);
+ auto res = DecodeVarUInt(it, buffer.end(), &value);
+ EXPECT_NE(0, res);
+ EXPECT_EQ(expected, value);
+ it += res;
+ }
+ EXPECT_EQ(it, buffer.end());
+
+ T value = T(-1);
+ auto res = DecodeVarUInt(it, buffer.end(), &value);
+ EXPECT_EQ(0, res);
+ EXPECT_EQ(T(-1), value);
+}
+
+template <class T>
+void TestEncodeDecodeVarInt(const std::vector<T>& data) {
+ std::vector<uint8_t> buffer;
+
+ std::vector<T> values;
+ for (T basis : data) {
+ // For variety, test the neighborhood values for each case in |data|. Some
+ // test cases may result in overflow when computing |value|, but we don't
+ // care about that.
+ for (int delta = -4; delta <= 4; ++delta) {
+ T value = delta + basis;
+ EncodeVarInt(value, std::back_inserter(buffer));
+ values.push_back(value);
+
+ value = delta - basis;
+ EncodeVarInt(value, std::back_inserter(buffer));
+ values.push_back(value);
+ }
+ }
+
+ auto it = buffer.begin();
+ for (T expected : values) {
+ T value = T(-1);
+ auto res = DecodeVarInt(it, buffer.end(), &value);
+ EXPECT_NE(0, res);
+ EXPECT_EQ(expected, value);
+ it += res;
+ }
+ EXPECT_EQ(it, buffer.end());
+
+ T value = T(-1);
+ auto res = DecodeVarInt(it, buffer.end(), &value);
+ EXPECT_EQ(0, res);
+ EXPECT_EQ(T(-1), value);
+}
+
+TEST(PatchUtilsTest, EncodeDecodeVarUInt32) {
+ TestEncodeDecodeVarUInt<uint32_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
+ 1 << 22, 1 << 27, 1 << 28, 0x7FFFFFFFU,
+ UINT32_MAX});
+}
+
+TEST(PatchUtilsTest, EncodeDecodeVarInt32) {
+ TestEncodeDecodeVarInt<int32_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
+ 1 << 22, 1 << 27, 1 << 28, -1, INT32_MIN,
+ INT32_MAX});
+}
+
+TEST(PatchUtilsTest, EncodeDecodeVarUInt64) {
+ TestEncodeDecodeVarUInt<uint64_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
+ 1 << 22, 1ULL << 55, 1ULL << 56,
+ 0x7FFFFFFFFFFFFFFFULL, UINT64_MAX});
+}
+
+TEST(PatchUtilsTest, EncodeDecodeVarInt64) {
+ TestEncodeDecodeVarInt<int64_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21,
+ 1 << 22, 1LL << 55, 1LL << 56, -1, INT64_MIN,
+ INT64_MAX});
+}
+
+TEST(PatchUtilsTest, DecodeVarUInt32Malformed) {
+ constexpr uint32_t kUninit = static_cast<uint32_t>(-1LL);
+
+ // Output variable to ensure that on failure, the output variable is not
+ // written to.
+ uint32_t value = uint32_t(-1);
+
+ auto TestDecodeVarInt = [&value](const std::vector<uint8_t>& buffer) {
+ value = kUninit;
+ return DecodeVarUInt(buffer.begin(), buffer.end(), &value);
+ };
+
+ // Exhausted.
+ EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>{}));
+ EXPECT_EQ(kUninit, value);
+ EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(4, 128)));
+ EXPECT_EQ(kUninit, value);
+
+ // Overflow.
+ EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(6, 128)));
+ EXPECT_EQ(kUninit, value);
+ EXPECT_EQ(0, TestDecodeVarInt({128, 128, 128, 128, 128, 42}));
+ EXPECT_EQ(kUninit, value);
+
+ // Following are pathological cases that are not handled for simplicity,
+ // hence decoding is expected to be successful.
+ EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 16}));
+ EXPECT_EQ(uint32_t(0), value);
+ EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 32}));
+ EXPECT_EQ(uint32_t(0), value);
+ EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 64}));
+ EXPECT_EQ(uint32_t(0), value);
+}
+
+TEST(PatchUtilsTest, DecodeVarUInt64Malformed) {
+ constexpr uint64_t kUninit = static_cast<uint64_t>(-1);
+
+ uint64_t value = kUninit;
+ auto TestDecodeVarInt = [&value](const std::vector<uint8_t>& buffer) {
+ value = kUninit;
+ return DecodeVarUInt(buffer.begin(), buffer.end(), &value);
+ };
+
+ // Exhausted.
+ EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>{}));
+ EXPECT_EQ(kUninit, value);
+ EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(9, 128)));
+ EXPECT_EQ(kUninit, value);
+
+ // Overflow.
+ EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(10, 128)));
+ EXPECT_EQ(kUninit, value);
+ EXPECT_EQ(0, TestDecodeVarInt(
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 42}));
+ EXPECT_EQ(kUninit, value);
+}
+
+} // namespace zucchini