/ src / tools / linux / md2core / minidump_memory_range_unittest.cc
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  }