// Copyright 2010 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // map_serializers_unittest.cc: Unit tests for std::map serializer and // std::map wrapper serializers. // // Author: Siyang Xie (lambxsy@google.com) #ifdef HAVE_CONFIG_H #include // Must come first #endif #include #include #include #include #include #include #include "breakpad_googletest_includes.h" #include "map_serializers-inl.h" #include "processor/address_map-inl.h" #include "processor/range_map-inl.h" #include "processor/contained_range_map-inl.h" typedef int32_t AddrType; typedef int32_t EntryType; class TestStdMapSerializer : public ::testing::Test { protected: void SetUp() { serialized_size_ = 0; serialized_data_ = NULL; } void TearDown() { delete [] serialized_data_; } std::map std_map_; google_breakpad::StdMapSerializer serializer_; uint32_t serialized_size_; char* serialized_data_; }; TEST_F(TestStdMapSerializer, EmptyMapTestCase) { const int32_t correct_data[] = { 0 }; uint32_t correct_size = sizeof(correct_data); // std_map_ is empty. serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestStdMapSerializer, MapWithTwoElementsTestCase) { const int32_t correct_data[] = { // # of nodes 2, // Offsets 20, 24, // Keys 1, 3, // Values 2, 6 }; uint32_t correct_size = sizeof(correct_data); std_map_.insert(std::make_pair(1, 2)); std_map_.insert(std::make_pair(3, 6)); serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestStdMapSerializer, MapWithFiveElementsTestCase) { const int32_t correct_data[] = { // # of nodes 5, // Offsets 44, 48, 52, 56, 60, // Keys 1, 2, 3, 4, 5, // Values 11, 12, 13, 14, 15 }; uint32_t correct_size = sizeof(correct_data); for (int i = 1; i < 6; ++i) std_map_.insert(std::make_pair(i, 10 + i)); serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } class TestAddressMapSerializer : public ::testing::Test { protected: void SetUp() { serialized_size_ = 0; serialized_data_ = 0; } void TearDown() { delete [] serialized_data_; } google_breakpad::AddressMap address_map_; google_breakpad::AddressMapSerializer serializer_; uint32_t serialized_size_; char* serialized_data_; }; TEST_F(TestAddressMapSerializer, EmptyMapTestCase) { const int32_t correct_data[] = { 0 }; uint32_t correct_size = sizeof(correct_data); // std_map_ is empty. serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestAddressMapSerializer, MapWithTwoElementsTestCase) { const int32_t correct_data[] = { // # of nodes 2, // Offsets 20, 24, // Keys 1, 3, // Values 2, 6 }; uint32_t correct_size = sizeof(correct_data); address_map_.Store(1, 2); address_map_.Store(3, 6); serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestAddressMapSerializer, MapWithFourElementsTestCase) { const int32_t correct_data[] = { // # of nodes 4, // Offsets 36, 40, 44, 48, // Keys -6, -4, 8, 123, // Values 2, 3, 5, 8 }; uint32_t correct_size = sizeof(correct_data); address_map_.Store(-6, 2); address_map_.Store(-4, 3); address_map_.Store(8, 5); address_map_.Store(123, 8); serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } class TestRangeMapSerializer : public ::testing::Test { protected: void SetUp() { serialized_size_ = 0; serialized_data_ = 0; } void TearDown() { delete [] serialized_data_; } google_breakpad::RangeMap range_map_; google_breakpad::RangeMapSerializer serializer_; uint32_t serialized_size_; char* serialized_data_; }; TEST_F(TestRangeMapSerializer, EmptyMapTestCase) { const int32_t correct_data[] = { 0 }; uint32_t correct_size = sizeof(correct_data); // range_map_ is empty. serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestRangeMapSerializer, MapWithOneRangeTestCase) { const int32_t correct_data[] = { // # of nodes 1, // Offsets 12, // Keys: high address 10, // Values: (low address, entry) pairs 1, 6 }; uint32_t correct_size = sizeof(correct_data); range_map_.StoreRange(1, 10, 6); serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestRangeMapSerializer, MapWithThreeRangesTestCase) { const int32_t correct_data[] = { // # of nodes 3, // Offsets 28, 36, 44, // Keys: high address 5, 9, 20, // Values: (low address, entry) pairs 2, 1, 6, 2, 10, 3 }; uint32_t correct_size = sizeof(correct_data); ASSERT_TRUE(range_map_.StoreRange(2, 4, 1)); ASSERT_TRUE(range_map_.StoreRange(6, 4, 2)); ASSERT_TRUE(range_map_.StoreRange(10, 11, 3)); serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } class TestContainedRangeMapSerializer : public ::testing::Test { protected: void SetUp() { serialized_size_ = 0; serialized_data_ = 0; } void TearDown() { delete [] serialized_data_; } google_breakpad::ContainedRangeMap crm_map_; google_breakpad::ContainedRangeMapSerializer serializer_; uint32_t serialized_size_; char* serialized_data_; }; TEST_F(TestContainedRangeMapSerializer, EmptyMapTestCase) { const int32_t correct_data[] = { 0, // base address of root 4, // size of entry 0, // entry stored at root 0 // empty map stored at root }; uint32_t correct_size = sizeof(correct_data); // crm_map_ is empty. serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestContainedRangeMapSerializer, MapWithOneRangeTestCase) { const int32_t correct_data[] = { 0, // base address of root 4, // size of entry 0, // entry stored at root // Map stored at root node: 1, // # of nodes 12, // offset 9, // key // value: a child ContainedRangeMap 3, // base address of child CRM 4, // size of entry -1, // entry stored in child CRM 0 // empty sub-map stored in child CRM }; uint32_t correct_size = sizeof(correct_data); crm_map_.StoreRange(3, 7, -1); serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } TEST_F(TestContainedRangeMapSerializer, MapWithTwoLevelsTestCase) { // Tree structure of ranges: // root level 0 // | // map // / \ level 1: child1, child2 // 2~8 10~20 // | | // map map // / \ | // 3~4 6~7 16-20 level 2: grandchild1, grandchild2, grandchild3 const int32_t correct_data[] = { // root: base, entry_size, entry 0, 4, 0, // root's map: # of nodes, offset1, offset2, key1, key2 2, 20, 84, 8, 20, // child1: base, entry_size, entry: 2, 4, -1, // child1's map: # of nodes, offset1, offset2, key1, key2 2, 20, 36, 4, 7, // grandchild1: base, entry_size, entry, empty_map 3, 4, -1, 0, // grandchild2: base, entry_size, entry, empty_map 6, 4, -1, 0, // child2: base, entry_size, entry: 10, 4, -1, // child2's map: # of nodes, offset1, key1 1, 12, 20, // grandchild3: base, entry_size, entry, empty_map 16, 4, -1, 0 }; uint32_t correct_size = sizeof(correct_data); // Store child1. ASSERT_TRUE(crm_map_.StoreRange(2, 7, -1)); // Store child2. ASSERT_TRUE(crm_map_.StoreRange(10, 11, -1)); // Store grandchild1. ASSERT_TRUE(crm_map_.StoreRange(3, 2, -1)); // Store grandchild2. ASSERT_TRUE(crm_map_.StoreRange(6, 2, -1)); // Store grandchild3. ASSERT_TRUE(crm_map_.StoreRange(16, 5, -1)); serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_); EXPECT_EQ(correct_size, serialized_size_); EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); } int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }