| // Copyright 2022 The Crashpad Authors |
| // |
| // 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 |