| // Copyright 2018 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/console/format_memory.h" | |
| #include <limits> | |
| #include <gtest/gtest.h> | |
| #include "src/developer/debug/zxdb/client/memory_dump.h" | |
| namespace zxdb { | |
| TEST(MemoryFormat, Simple) { | |
| std::vector<debug_ipc::MemoryBlock> block; | |
| block.resize(1); | |
| block[0].address = 0x1000; | |
| block[0].valid = true; | |
| block[0].size = 0x1000; | |
| for (uint64_t i = 0; i < block[0].size; i++) { | |
| block[0].data.push_back(static_cast<uint8_t>(i % 0x100)); | |
| } | |
| MemoryDump dump(std::move(block)); | |
| MemoryFormatOptions opts; | |
| // Simple 2-line output with no addresses or ascii. | |
| OutputBuffer output = FormatMemory(dump, 0x1000, 0x20, opts); | |
| char expected1[] = | |
| "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n" | |
| "10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f\n"; | |
| EXPECT_EQ(expected1, output.AsString()); | |
| // 1 and a half lines with ascii, separator every 8. | |
| opts.show_ascii = true; | |
| opts.separator_every = 8; | |
| output = FormatMemory(dump, 0x1000, 0x18, opts); | |
| char expected2[] = | |
| "00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f | \n" | |
| "10 11 12 13 14 15 16 17 | \n"; | |
| EXPECT_EQ(expected2, output.AsString()); | |
| // With addresses and printable ASCII. | |
| opts.address_mode = MemoryFormatOptions::kAddresses; | |
| output = FormatMemory(dump, 0x1010, 0x20, opts); | |
| char expected3[] = | |
| "0x1010: 10 11 12 13 14 15 16 17-18 19 1a 1b 1c 1d 1e 1f | \n" | |
| "0x1020: 20 21 22 23 24 25 26 27-28 29 2a 2b 2c 2d 2e 2f | !\"#$%&'()*+,-./\n"; | |
| EXPECT_EQ(expected3, output.AsString()); | |
| // With offsets instead of addresses. | |
| opts.address_mode = MemoryFormatOptions::kOffsets; | |
| output = FormatMemory(dump, 0x1010, 0x20, opts); | |
| char expected_offsets[] = | |
| "+0x10: 10 11 12 13 14 15 16 17-18 19 1a 1b 1c 1d 1e 1f | \n" | |
| "+0x20: 20 21 22 23 24 25 26 27-28 29 2a 2b 2c 2d 2e 2f | !\"#$%&'()*+,-./\n"; | |
| EXPECT_EQ(expected_offsets, output.AsString()); | |
| // Out-of-block bytes, addresses should be padded to the same length. | |
| opts.address_mode = MemoryFormatOptions::kAddresses; | |
| opts.show_ascii = false; | |
| output = FormatMemory(dump, 0xF0, 0x20, opts); | |
| char expected4[] = | |
| // Weird break in the middle to avoid a warning about a ??- trigraph. | |
| "0x0f0: ?? ?? ?? ?? ?? ?? ?? ??" | |
| "-?? ?? ?? ?? ?? ?? ?? ??\n" | |
| "0x100: ?? ?? ?? ?? ?? ?? ?? ??" | |
| "-?? ?? ?? ?? ?? ?? ?? ??\n"; | |
| EXPECT_EQ(expected4, output.AsString()); | |
| // Non-aligned start offset, crosses valid/invalid boundary, weird separator | |
| // width. | |
| opts.address_mode = MemoryFormatOptions::kAddresses; | |
| opts.show_ascii = true; | |
| opts.separator_every = 5; | |
| output = FormatMemory(dump, 0xFFA, 0x19, opts); | |
| char expected5[] = | |
| // Weird break in the middle to avoid a warning about a ??- trigraph. | |
| "0x0ffa: ?? ?? ?? ?? ??" | |
| "-?? 00 01 02 03-04 05 06 07 08-09 | \n" | |
| "0x100a: 0a 0b 0c 0d 0e-0f 10 11 12 | \n"; | |
| EXPECT_EQ(expected5, output.AsString()); | |
| // Weird column width, separator every time. | |
| opts.address_mode = MemoryFormatOptions::kAddresses; | |
| opts.show_ascii = true; | |
| opts.values_per_line = 3; | |
| opts.separator_every = 1; | |
| output = FormatMemory(dump, 0x1000, 10, opts); | |
| char expected6[] = | |
| "0x1000: 00-01-02 | \n" | |
| "0x1003: 03-04-05 | \n" | |
| "0x1006: 06-07-08 | \n" | |
| "0x1009: 09 | \n"; | |
| EXPECT_EQ(expected6, output.AsString()); | |
| } | |
| TEST(MemoryFormat, Limits) { | |
| uint64_t max = std::numeric_limits<uint64_t>::max(); | |
| // This block goes right up to the edge of the 64-bit address space. | |
| std::vector<debug_ipc::MemoryBlock> block; | |
| block.resize(1); | |
| block[0].size = 0x1000; | |
| block[0].address = max - block[0].size + 1; | |
| block[0].valid = true; | |
| // This one has the same data to make things simpler below. | |
| for (uint64_t i = 0; i < block[0].size; i++) { | |
| block[0].data.push_back(0x11); | |
| } | |
| MemoryDump dump(std::move(block)); | |
| MemoryFormatOptions opts; | |
| opts.address_mode = MemoryFormatOptions::kAddresses; | |
| // Simple 2-line output with no addresses or ascii against end of address | |
| // space. | |
| OutputBuffer output = FormatMemory(dump, max - 0x1F, 0x20, opts); | |
| char expected1[] = | |
| "0xffffffffffffffe0: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11\n" | |
| "0xfffffffffffffff0: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11\n"; | |
| EXPECT_EQ(expected1, output.AsString()); | |
| // Asking for data past the end of the address space should just stop output. | |
| output = FormatMemory(dump, max - 0xF, 0x20, opts); | |
| char expected2[] = "0xfffffffffffffff0: 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11\n"; | |
| EXPECT_EQ(expected2, output.AsString()); | |
| } | |
| TEST(MemoryFormat, Empty) { | |
| std::vector<debug_ipc::MemoryBlock> block; | |
| block.resize(1); | |
| block[0].size = 0; | |
| block[0].address = 0; | |
| block[0].valid = false; | |
| MemoryDump dump(std::move(block)); | |
| MemoryFormatOptions opts; | |
| opts.address_mode = MemoryFormatOptions::kAddresses; | |
| OutputBuffer output = FormatMemory(dump, 0, 0, opts); | |
| EXPECT_EQ("0x0: \n", output.AsString()); | |
| // Try a 0-sized one at a different address. | |
| block.resize(1); | |
| block[0].size = 0x10; | |
| block[0].address = 0x100; | |
| for (uint32_t i = 0; i < block[0].size; i++) | |
| block[0].data.push_back(static_cast<uint8_t>(i)); | |
| block[0].valid = true; | |
| dump = MemoryDump(std::move(block)); | |
| output = FormatMemory(dump, 0x100, 0, opts); | |
| EXPECT_EQ("0x100: \n", output.AsString()); | |
| // Try the same thing with no addresses. | |
| opts.address_mode = MemoryFormatOptions::kNoAddresses; | |
| output = FormatMemory(dump, 0x100, 0, opts); | |
| EXPECT_EQ("\n", output.AsString()); | |
| } | |
| } // namespace zxdb |