minidump_memory_range_unittest.cc
1 // Copyright 2011 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // minidump_memory_range_unittest.cc: 30 // Unit tests for google_breakpad::MinidumpMemoryRange. 31 32 #ifdef HAVE_CONFIG_H 33 #include <config.h> // Must come first 34 #endif 35 36 #include "breakpad_googletest_includes.h" 37 #include "tools/linux/md2core/minidump_memory_range.h" 38 39 using google_breakpad::MinidumpMemoryRange; 40 using testing::Message; 41 42 namespace { 43 44 const uint32_t kBuffer[10] = { 0 }; 45 const size_t kBufferSize = sizeof(kBuffer); 46 const uint8_t* kBufferPointer = reinterpret_cast<const uint8_t*>(kBuffer); 47 48 // Test vectors for verifying Covers, GetData, and Subrange. 49 const struct { 50 bool valid; 51 size_t offset; 52 size_t length; 53 } kSubranges[] = { 54 { true, 0, 0 }, 55 { true, 0, 2 }, 56 { true, 0, kBufferSize }, 57 { true, 2, 0 }, 58 { true, 2, 4 }, 59 { true, 2, kBufferSize - 2 }, 60 { true, kBufferSize - 1, 1 }, 61 { false, kBufferSize, 0 }, 62 { false, kBufferSize, static_cast<size_t>(-1) }, 63 { false, kBufferSize + 1, 0 }, 64 { false, static_cast<size_t>(-1), 2 }, 65 { false, 1, kBufferSize }, 66 { false, kBufferSize - 1, 2 }, 67 { false, 0, static_cast<size_t>(-1) }, 68 { false, 1, static_cast<size_t>(-1) }, 69 }; 70 const size_t kNumSubranges = sizeof(kSubranges) / sizeof(kSubranges[0]); 71 72 // Test vectors for verifying GetArrayElement. 73 const struct { 74 size_t offset; 75 size_t size; 76 size_t index; 77 const void* const pointer; 78 } kElements[] = { 79 // Valid array elemenets 80 { 0, 1, 0, kBufferPointer }, 81 { 0, 1, 1, kBufferPointer + 1 }, 82 { 0, 1, kBufferSize - 1, kBufferPointer + kBufferSize - 1 }, 83 { 0, 2, 1, kBufferPointer + 2 }, 84 { 0, 4, 2, kBufferPointer + 8 }, 85 { 0, 4, 9, kBufferPointer + 36 }, 86 { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 }, 87 // Invalid array elemenets 88 { 0, 1, kBufferSize, NULL }, 89 { 0, 4, 10, NULL }, 90 { kBufferSize - 1, 1, 1, NULL }, 91 { kBufferSize - 1, 2, 0, NULL }, 92 { kBufferSize, 1, 0, NULL }, 93 }; 94 const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); 95 96 } // namespace 97 98 TEST(MinidumpMemoryRangeTest, DefaultConstructor) { 99 MinidumpMemoryRange range; 100 EXPECT_EQ(NULL, range.data()); 101 EXPECT_EQ(0U, range.length()); 102 } 103 104 TEST(MinidumpMemoryRangeTest, ConstructorWithDataAndLength) { 105 MinidumpMemoryRange range(kBuffer, kBufferSize); 106 EXPECT_EQ(kBufferPointer, range.data()); 107 EXPECT_EQ(kBufferSize, range.length()); 108 } 109 110 TEST(MinidumpMemoryRangeTest, Reset) { 111 MinidumpMemoryRange range; 112 range.Reset(); 113 EXPECT_EQ(NULL, range.data()); 114 EXPECT_EQ(0U, range.length()); 115 116 range.Set(kBuffer, kBufferSize); 117 EXPECT_EQ(kBufferPointer, range.data()); 118 EXPECT_EQ(kBufferSize, range.length()); 119 120 range.Reset(); 121 EXPECT_EQ(NULL, range.data()); 122 EXPECT_EQ(0U, range.length()); 123 } 124 125 TEST(MinidumpMemoryRangeTest, Set) { 126 MinidumpMemoryRange range; 127 range.Set(kBuffer, kBufferSize); 128 EXPECT_EQ(kBufferPointer, range.data()); 129 EXPECT_EQ(kBufferSize, range.length()); 130 131 range.Set(NULL, 0); 132 EXPECT_EQ(NULL, range.data()); 133 EXPECT_EQ(0U, range.length()); 134 } 135 136 TEST(MinidumpMemoryRangeTest, SubrangeOfEmptyMemoryRange) { 137 MinidumpMemoryRange range; 138 MinidumpMemoryRange subrange = range.Subrange(0, 10); 139 EXPECT_EQ(NULL, subrange.data()); 140 EXPECT_EQ(0U, subrange.length()); 141 } 142 143 TEST(MinidumpMemoryRangeTest, SubrangeAndGetData) { 144 MinidumpMemoryRange range(kBuffer, kBufferSize); 145 for (size_t i = 0; i < kNumSubranges; ++i) { 146 bool valid = kSubranges[i].valid; 147 size_t sub_offset = kSubranges[i].offset; 148 size_t sub_length = kSubranges[i].length; 149 SCOPED_TRACE(Message() << "offset=" << sub_offset 150 << ", length=" << sub_length); 151 152 MinidumpMemoryRange subrange = range.Subrange(sub_offset, sub_length); 153 if (valid) { 154 EXPECT_TRUE(range.Covers(sub_offset, sub_length)); 155 EXPECT_EQ(kBufferPointer + sub_offset, 156 range.GetData(sub_offset, sub_length)); 157 EXPECT_EQ(kBufferPointer + sub_offset, subrange.data()); 158 EXPECT_EQ(sub_length, subrange.length()); 159 } else { 160 EXPECT_FALSE(range.Covers(sub_offset, sub_length)); 161 EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); 162 EXPECT_EQ(NULL, subrange.data()); 163 EXPECT_EQ(0U, subrange.length()); 164 } 165 } 166 } 167 168 TEST(MinidumpMemoryRangeTest, SubrangeWithMDLocationDescriptor) { 169 MinidumpMemoryRange range(kBuffer, kBufferSize); 170 for (size_t i = 0; i < kNumSubranges; ++i) { 171 bool valid = kSubranges[i].valid; 172 size_t sub_offset = kSubranges[i].offset; 173 size_t sub_length = kSubranges[i].length; 174 SCOPED_TRACE(Message() << "offset=" << sub_offset 175 << ", length=" << sub_length); 176 177 MDLocationDescriptor location; 178 location.rva = sub_offset; 179 location.data_size = sub_length; 180 MinidumpMemoryRange subrange = range.Subrange(location); 181 if (valid) { 182 EXPECT_TRUE(range.Covers(sub_offset, sub_length)); 183 EXPECT_EQ(kBufferPointer + sub_offset, 184 range.GetData(sub_offset, sub_length)); 185 EXPECT_EQ(kBufferPointer + sub_offset, subrange.data()); 186 EXPECT_EQ(sub_length, subrange.length()); 187 } else { 188 EXPECT_FALSE(range.Covers(sub_offset, sub_length)); 189 EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); 190 EXPECT_EQ(NULL, subrange.data()); 191 EXPECT_EQ(0U, subrange.length()); 192 } 193 } 194 } 195 196 TEST(MinidumpMemoryRangeTest, GetDataWithTemplateType) { 197 MinidumpMemoryRange range(kBuffer, kBufferSize); 198 const char* char_pointer = range.GetData<char>(0); 199 EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer); 200 const int* int_pointer = range.GetData<int>(0); 201 EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer); 202 } 203 204 TEST(MinidumpMemoryRangeTest, GetArrayElement) { 205 MinidumpMemoryRange range(kBuffer, kBufferSize); 206 for (size_t i = 0; i < kNumElements; ++i) { 207 size_t element_offset = kElements[i].offset; 208 size_t element_size = kElements[i].size; 209 unsigned element_index = kElements[i].index; 210 const void* const element_pointer = kElements[i].pointer; 211 SCOPED_TRACE(Message() << "offset=" << element_offset 212 << ", size=" << element_size 213 << ", index=" << element_index); 214 EXPECT_EQ(element_pointer, range.GetArrayElement( 215 element_offset, element_size, element_index)); 216 } 217 } 218 219 TEST(MinidumpMemoryRangeTest, GetArrayElmentWithTemplateType) { 220 MinidumpMemoryRange range(kBuffer, kBufferSize); 221 const char* char_pointer = range.GetArrayElement<char>(0, 0); 222 EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer); 223 const int* int_pointer = range.GetArrayElement<int>(0, 0); 224 EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer); 225 } 226 227 TEST(MinidumpMemoryRangeTest, GetAsciiMDString) { 228 uint8_t buffer[100] = { 0 }; 229 230 MDString* md_str = reinterpret_cast<MDString*>(buffer); 231 md_str->length = 4; 232 md_str->buffer[0] = 'T'; 233 md_str->buffer[1] = 'e'; 234 md_str->buffer[2] = 's'; 235 md_str->buffer[3] = 't'; 236 md_str->buffer[4] = '\0'; 237 238 size_t str2_offset = 239 sizeof(MDString) + (md_str->length + 1) * sizeof(uint16_t); 240 241 md_str = reinterpret_cast<MDString*>(buffer + str2_offset); 242 md_str->length = 9; // Test length larger than actual string 243 md_str->buffer[0] = 'S'; 244 md_str->buffer[1] = 't'; 245 md_str->buffer[2] = 'r'; 246 md_str->buffer[3] = 'i'; 247 md_str->buffer[4] = 'n'; 248 md_str->buffer[5] = 'g'; 249 md_str->buffer[6] = '\0'; 250 md_str->buffer[7] = '1'; 251 md_str->buffer[8] = '2'; 252 253 MinidumpMemoryRange range(buffer, sizeof(buffer)); 254 EXPECT_EQ("Test", range.GetAsciiMDString(0)); 255 EXPECT_EQ("String", range.GetAsciiMDString(str2_offset)); 256 257 // Test out-of-bounds cases. 258 EXPECT_EQ("", range.GetAsciiMDString( 259 sizeof(buffer) - sizeof(MDString) + 1)); 260 EXPECT_EQ("", range.GetAsciiMDString(sizeof(buffer))); 261 }