blob: 15f70c1c021ec175aad67bbfd700b98eefb17b57 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "src/developer/debug/zxdb/common/data_extractor.h"
#include <limits>
#include <gtest/gtest.h>
namespace zxdb {
TEST(DataExtractor, Empty) {
DataExtractor ext;
EXPECT_TRUE(ext.done());
EXPECT_EQ(0u, ext.cur());
ext.Advance(1);
EXPECT_EQ(0u, ext.cur());
ext.Seek(1);
EXPECT_EQ(0u, ext.cur());
EXPECT_FALSE(ext.Read<uint8_t>());
}
TEST(DataExtractor, SeekAdvance) {
std::vector<uint8_t> buffer{0x01, 0x02, 0x03, 0x04};
DataExtractor ext(buffer);
EXPECT_EQ(0u, ext.cur());
ext.Advance(2);
EXPECT_EQ(2u, ext.cur());
ext.Advance(2);
EXPECT_EQ(4u, ext.cur());
// Should stop at the end.
ext.Advance(2);
EXPECT_EQ(4u, ext.cur());
// Seek back tot he beginning.
ext.Seek(0);
EXPECT_EQ(0u, ext.cur());
// Advance and Seek clamps to the end.
ext.Advance(2000);
EXPECT_EQ(4u, ext.cur());
ext.Seek(2000);
EXPECT_EQ(4u, ext.cur());
}
TEST(DataExtractor, Numbers) {
// clang-format off
std::vector<uint8_t> buffer{
0x10,
0x20, 0x21,
0x30, 0x31, 0x32, 0x33,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 };
// clang-format on
// Signed integers (little-endian).
DataExtractor ext(buffer);
EXPECT_FALSE(ext.done());
EXPECT_EQ(std::optional<int8_t>(0x10), ext.Read<int8_t>());
EXPECT_EQ(std::optional<int16_t>(0x2120), ext.Read<int16_t>());
EXPECT_EQ(std::optional<int32_t>(0x33323130), ext.Read<int32_t>());
EXPECT_EQ(std::optional<int64_t>(0x4746454443424140), ext.Read<int64_t>());
EXPECT_EQ(std::optional<int8_t>(), ext.Read<int8_t>()); // Read past end fails.
EXPECT_TRUE(ext.done());
// Unsigned integers (little-endian).
ext = DataExtractor(buffer);
EXPECT_EQ(std::optional<uint8_t>(0x10), ext.Read<uint8_t>());
EXPECT_EQ(std::optional<uint16_t>(0x2120), ext.Read<uint16_t>());
EXPECT_EQ(std::optional<uint32_t>(0x33323130), ext.Read<uint32_t>());
EXPECT_EQ(std::optional<uint64_t>(0x4746454443424140), ext.Read<uint64_t>());
// Reading past the end should leave the position unchanged (buffer is 15 bytes long).
ext = DataExtractor(buffer);
ext.Read<uint64_t>();
EXPECT_EQ(8u, ext.cur());
EXPECT_FALSE(ext.Read<uint64_t>()); // Read fails.
EXPECT_EQ(8u, ext.cur()); // Position is unchanged.
}
TEST(DataExtractor, Manual) {
std::vector<uint8_t> buffer{0x01, 0x02, 0x03, 0x04};
DataExtractor ext(buffer);
EXPECT_EQ(0u, ext.cur());
EXPECT_TRUE(ext.CanRead(1));
EXPECT_TRUE(ext.CanRead(4));
EXPECT_FALSE(ext.CanRead(5));
EXPECT_EQ(0u, ext.cur());
ext.Advance(2);
EXPECT_EQ(2u, ext.cur());
ext.Advance(0);
EXPECT_EQ(2u, ext.cur());
EXPECT_TRUE(ext.CanRead(2));
EXPECT_FALSE(ext.CanRead(3));
// Advances one-past-the end. Should stop at the end.
ext.Advance(3);
EXPECT_EQ(4u, ext.cur());
EXPECT_TRUE(ext.CanRead(0));
EXPECT_FALSE(ext.CanRead(1));
// Test overflow of size variables. In this case size + read_size overflows.
size_t big_read = std::numeric_limits<size_t>::max() - 1;
ext = DataExtractor(buffer);
EXPECT_FALSE(ext.CanRead(big_read));
// Here cur + read_size overflows.
ext.Advance(2);
EXPECT_FALSE(ext.CanRead(big_read));
}
// Test a long encoded number with the high bit not set.
TEST(DataExtractor, ReadLeb128_NoHighBit) {
// |--- First ----| |- Following
std::vector<uint8_t> buffer{0xe5, 0x8e, 0x26, 0x04};
// Read unsigned value.
DataExtractor ext(buffer);
std::optional<uint64_t> result_u = ext.ReadUleb128();
ASSERT_TRUE(result_u);
EXPECT_EQ(624485ul, *result_u);
// Read following value.
result_u = ext.ReadUleb128();
ASSERT_TRUE(result_u);
EXPECT_EQ(4ul, *result_u);
// Read signed value. The high bit on this is not set so the result should be the same.
ext = DataExtractor(buffer);
std::optional<int64_t> result_s = ext.ReadSleb128();
ASSERT_TRUE(result_s);
EXPECT_EQ(624485l, *result_s);
// Read following value.
result_s = ext.ReadSleb128();
ASSERT_TRUE(result_s);
EXPECT_EQ(4l, *result_s);
// Reached the end of the data, can't read any more.
result_u = ext.ReadUleb128();
EXPECT_FALSE(result_u);
result_s = ext.ReadSleb128();
EXPECT_FALSE(result_s);
}
// The high bit is set on this one so that the signed one should be sign-extended.
TEST(DataExtractor, ReadLeb128_HighBit) {
// |--- First ----| |- Following
std::vector<uint8_t> buffer{0xc0, 0xbb, 0x78, 0x7f};
// Read unsigned value.
DataExtractor ext(buffer);
std::optional<uint64_t> result_u = ext.ReadUleb128();
ASSERT_TRUE(result_u);
EXPECT_EQ(1973696ul, *result_u);
// Read following value.
result_u = ext.ReadUleb128();
ASSERT_TRUE(result_u);
EXPECT_EQ(0x7ful, *result_u);
// Read signed value, should be sign-extended to negative.
ext = DataExtractor(buffer);
std::optional<int64_t> result_s = ext.ReadSleb128();
ASSERT_TRUE(result_s);
EXPECT_EQ(-123456l, *result_s);
// Read following value.
result_s = ext.ReadSleb128();
ASSERT_TRUE(result_s);
EXPECT_EQ(-1l, *result_s);
}
TEST(DataExtractor, ReadLeb128_Error) {
// Empty buffer.
std::vector<uint8_t> empty;
DataExtractor ext(empty);
EXPECT_FALSE(ext.ReadSleb128());
EXPECT_FALSE(ext.ReadUleb128());
// This buffer has no value without the high bit set so the number won't terminate.
std::vector<uint8_t> buffer{0xc0, 0xbb};
ext = DataExtractor(buffer);
EXPECT_FALSE(ext.ReadSleb128());
EXPECT_FALSE(ext.ReadUleb128());
}
} // namespace zxdb