123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // 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
|