// Copyright 2022 The Crashpad Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "snapshot/ios/memory_snapshot_ios_intermediate_dump.h" #include <string> #include <vector> #include "gtest/gtest.h" namespace crashpad { namespace test { namespace { using internal::MemorySnapshotIOSIntermediateDump; const vm_address_t kDefaultAddress = 0x1000; class ReadToString : public crashpad::MemorySnapshot::Delegate { public: const std::string& result() { return result_; } private: // MemorySnapshot::Delegate: bool MemorySnapshotDelegateRead(void* data, size_t size) override { result_ = std::string(reinterpret_cast<const char*>(data), size); return true; } std::string result_; }; std::unique_ptr<MemorySnapshotIOSIntermediateDump> CreateMemorySnapshot( vm_address_t address, std::vector<uint8_t>& data) { auto memory = std::make_unique<MemorySnapshotIOSIntermediateDump>(); memory->Initialize( address, reinterpret_cast<const vm_address_t>(data.data()), data.size()); return memory; } TEST(MemorySnapshotIOSIntermediateDumpTest, MergeSame) { std::vector<uint8_t> data(10, 'a'); auto memory = CreateMemorySnapshot(kDefaultAddress, data); std::unique_ptr<const MemorySnapshot> merged( memory->MergeWithOtherSnapshot(memory.get())); EXPECT_EQ(merged->Address(), kDefaultAddress); EXPECT_EQ(merged->Size(), data.size()); ReadToString delegate; merged->Read(&delegate); EXPECT_EQ(delegate.result(), "aaaaaaaaaa"); } TEST(MemorySnapshotIOSIntermediateDumpTest, MergeNoOverlap) { std::vector<uint8_t> data1(10, 'a'); auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); std::vector<uint8_t> data2(10, 'b'); auto memory2 = CreateMemorySnapshot(kDefaultAddress + 10, data2); std::unique_ptr<const MemorySnapshot> merged( memory1->MergeWithOtherSnapshot(memory2.get())); EXPECT_EQ(merged->Address(), kDefaultAddress); EXPECT_EQ(merged->Size(), 20u); ReadToString delegate; merged->Read(&delegate); EXPECT_EQ(delegate.result(), "aaaaaaaaaabbbbbbbbbb"); } TEST(MemorySnapshotIOSIntermediateDumpTest, MergePartial) { std::vector<uint8_t> data1(10, 'a'); auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); std::vector<uint8_t> data2(10, 'b'); auto memory2 = CreateMemorySnapshot(kDefaultAddress + 5, data2); std::unique_ptr<const MemorySnapshot> merged( memory1->MergeWithOtherSnapshot(memory2.get())); EXPECT_EQ(merged->Address(), kDefaultAddress); EXPECT_EQ(merged->Size(), 15u); ReadToString delegate; merged->Read(&delegate); EXPECT_EQ(delegate.result(), "aaaaabbbbbbbbbb"); } TEST(MemorySnapshotIOSIntermediateDumpTest, NoMerge) { std::vector<uint8_t> data1(10, 'a'); auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); std::vector<uint8_t> data2(10, 'b'); auto memory2 = CreateMemorySnapshot(kDefaultAddress + 20, data2); std::unique_ptr<const MemorySnapshot> merged( memory1->MergeWithOtherSnapshot(memory2.get())); EXPECT_EQ(merged.get(), nullptr); } TEST(MemorySnapshotIOSIntermediateDumpTest, EnvelopeBiggerFirst) { std::vector<uint8_t> data1(30, 'a'); auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); std::vector<uint8_t> data2(10, 'b'); auto memory2 = CreateMemorySnapshot(kDefaultAddress + 15, data2); std::unique_ptr<const MemorySnapshot> merged( memory1->MergeWithOtherSnapshot(memory2.get())); EXPECT_EQ(merged->Address(), kDefaultAddress); EXPECT_EQ(merged->Size(), data1.size()); ReadToString delegate; merged->Read(&delegate); EXPECT_EQ(delegate.result(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); } TEST(MemorySnapshotIOSIntermediateDumpTest, EnvelopeBiggerSecond) { std::vector<uint8_t> data1(10, 'a'); auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); std::vector<uint8_t> data2(20, 'b'); auto memory2 = CreateMemorySnapshot(kDefaultAddress, data2); std::unique_ptr<const MemorySnapshot> merged( memory1->MergeWithOtherSnapshot(memory2.get())); EXPECT_EQ(merged->Address(), kDefaultAddress); EXPECT_EQ(merged->Size(), data2.size()); ReadToString delegate; merged->Read(&delegate); EXPECT_EQ(delegate.result(), "bbbbbbbbbbbbbbbbbbbb"); } TEST(MemorySnapshotIOSIntermediateDumpTest, SmallerAddressSecond) { std::vector<uint8_t> data1(10, 'a'); auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); std::vector<uint8_t> data2(20, 'b'); auto memory2 = CreateMemorySnapshot(kDefaultAddress - 10, data2); std::unique_ptr<const MemorySnapshot> merged( memory1->MergeWithOtherSnapshot(memory2.get())); EXPECT_EQ(merged->Address(), kDefaultAddress - 10); EXPECT_EQ(merged->Size(), data2.size()); ReadToString delegate; merged->Read(&delegate); EXPECT_EQ(delegate.result(), "bbbbbbbbbbbbbbbbbbbb"); } } // namespace } // namespace test } // namespace crashpad