michael@0: // Copyright (c) 2011, Google Inc. michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: // memory_range_unittest.cc: Unit tests for google_breakpad::MemoryRange. michael@0: michael@0: #include "breakpad_googletest_includes.h" michael@0: #include "common/memory_range.h" michael@0: michael@0: using google_breakpad::MemoryRange; michael@0: using testing::Message; michael@0: michael@0: namespace { michael@0: michael@0: const uint32_t kBuffer[10] = { 0 }; michael@0: const size_t kBufferSize = sizeof(kBuffer); michael@0: const uint8_t* kBufferPointer = reinterpret_cast(kBuffer); michael@0: michael@0: // Test vectors for verifying Covers, GetData, and Subrange. michael@0: const struct { michael@0: bool valid; michael@0: size_t offset; michael@0: size_t length; michael@0: } kSubranges[] = { michael@0: { true, 0, 0 }, michael@0: { true, 0, 2 }, michael@0: { true, 0, kBufferSize }, michael@0: { true, 2, 0 }, michael@0: { true, 2, 4 }, michael@0: { true, 2, kBufferSize - 2 }, michael@0: { true, kBufferSize - 1, 1 }, michael@0: { false, kBufferSize, 0 }, michael@0: { false, kBufferSize, static_cast(-1) }, michael@0: { false, kBufferSize + 1, 0 }, michael@0: { false, static_cast(-1), 2 }, michael@0: { false, 1, kBufferSize }, michael@0: { false, kBufferSize - 1, 2 }, michael@0: { false, 0, static_cast(-1) }, michael@0: { false, 1, static_cast(-1) }, michael@0: }; michael@0: const size_t kNumSubranges = sizeof(kSubranges) / sizeof(kSubranges[0]); michael@0: michael@0: // Test vectors for verifying GetArrayElement. michael@0: const struct { michael@0: size_t offset; michael@0: size_t size; michael@0: size_t index; michael@0: const void* const pointer; michael@0: } kElements[] = { michael@0: // Valid array elemenets michael@0: { 0, 1, 0, kBufferPointer }, michael@0: { 0, 1, 1, kBufferPointer + 1 }, michael@0: { 0, 1, kBufferSize - 1, kBufferPointer + kBufferSize - 1 }, michael@0: { 0, 2, 1, kBufferPointer + 2 }, michael@0: { 0, 4, 2, kBufferPointer + 8 }, michael@0: { 0, 4, 9, kBufferPointer + 36 }, michael@0: { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 }, michael@0: // Invalid array elemenets michael@0: { 0, 1, kBufferSize, NULL }, michael@0: { 0, 4, 10, NULL }, michael@0: { kBufferSize - 1, 1, 1, NULL }, michael@0: { kBufferSize - 1, 2, 0, NULL }, michael@0: { kBufferSize, 1, 0, NULL }, michael@0: }; michael@0: const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); michael@0: michael@0: } // namespace michael@0: michael@0: TEST(MemoryRangeTest, DefaultConstructor) { michael@0: MemoryRange range; michael@0: EXPECT_EQ(NULL, range.data()); michael@0: EXPECT_EQ(0U, range.length()); michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, ConstructorWithDataAndLength) { michael@0: MemoryRange range(kBuffer, kBufferSize); michael@0: EXPECT_EQ(kBufferPointer, range.data()); michael@0: EXPECT_EQ(kBufferSize, range.length()); michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, Reset) { michael@0: MemoryRange range; michael@0: range.Reset(); michael@0: EXPECT_EQ(NULL, range.data()); michael@0: EXPECT_EQ(0U, range.length()); michael@0: michael@0: range.Set(kBuffer, kBufferSize); michael@0: EXPECT_EQ(kBufferPointer, range.data()); michael@0: EXPECT_EQ(kBufferSize, range.length()); michael@0: michael@0: range.Reset(); michael@0: EXPECT_EQ(NULL, range.data()); michael@0: EXPECT_EQ(0U, range.length()); michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, Set) { michael@0: MemoryRange range; michael@0: range.Set(kBuffer, kBufferSize); michael@0: EXPECT_EQ(kBufferPointer, range.data()); michael@0: EXPECT_EQ(kBufferSize, range.length()); michael@0: michael@0: range.Set(NULL, 0); michael@0: EXPECT_EQ(NULL, range.data()); michael@0: EXPECT_EQ(0U, range.length()); michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, SubrangeOfEmptyMemoryRange) { michael@0: MemoryRange range; michael@0: MemoryRange subrange = range.Subrange(0, 10); michael@0: EXPECT_EQ(NULL, subrange.data()); michael@0: EXPECT_EQ(0U, subrange.length()); michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, SubrangeAndGetData) { michael@0: MemoryRange range(kBuffer, kBufferSize); michael@0: for (size_t i = 0; i < kNumSubranges; ++i) { michael@0: bool valid = kSubranges[i].valid; michael@0: size_t sub_offset = kSubranges[i].offset; michael@0: size_t sub_length = kSubranges[i].length; michael@0: SCOPED_TRACE(Message() << "offset=" << sub_offset michael@0: << ", length=" << sub_length); michael@0: michael@0: MemoryRange subrange = range.Subrange(sub_offset, sub_length); michael@0: if (valid) { michael@0: EXPECT_TRUE(range.Covers(sub_offset, sub_length)); michael@0: EXPECT_EQ(kBufferPointer + sub_offset, michael@0: range.GetData(sub_offset, sub_length)); michael@0: EXPECT_EQ(kBufferPointer + sub_offset, subrange.data()); michael@0: EXPECT_EQ(sub_length, subrange.length()); michael@0: } else { michael@0: EXPECT_FALSE(range.Covers(sub_offset, sub_length)); michael@0: EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); michael@0: EXPECT_EQ(NULL, subrange.data()); michael@0: EXPECT_EQ(0U, subrange.length()); michael@0: } michael@0: } michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, GetDataWithTemplateType) { michael@0: MemoryRange range(kBuffer, kBufferSize); michael@0: const char* char_pointer = range.GetData(0); michael@0: EXPECT_EQ(reinterpret_cast(kBufferPointer), char_pointer); michael@0: const int* int_pointer = range.GetData(0); michael@0: EXPECT_EQ(reinterpret_cast(kBufferPointer), int_pointer); michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, GetArrayElement) { michael@0: MemoryRange range(kBuffer, kBufferSize); michael@0: for (size_t i = 0; i < kNumElements; ++i) { michael@0: size_t element_offset = kElements[i].offset; michael@0: size_t element_size = kElements[i].size; michael@0: unsigned element_index = kElements[i].index; michael@0: const void* const element_pointer = kElements[i].pointer; michael@0: SCOPED_TRACE(Message() << "offset=" << element_offset michael@0: << ", size=" << element_size michael@0: << ", index=" << element_index); michael@0: EXPECT_EQ(element_pointer, range.GetArrayElement( michael@0: element_offset, element_size, element_index)); michael@0: } michael@0: } michael@0: michael@0: TEST(MemoryRangeTest, GetArrayElmentWithTemplateType) { michael@0: MemoryRange range(kBuffer, kBufferSize); michael@0: const char* char_pointer = range.GetArrayElement(0, 0); michael@0: EXPECT_EQ(reinterpret_cast(kBufferPointer), char_pointer); michael@0: const int* int_pointer = range.GetArrayElement(0, 0); michael@0: EXPECT_EQ(reinterpret_cast(kBufferPointer), int_pointer); michael@0: }