| // Copyright 2014 The Crashpad Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "minidump/minidump_thread_id_map.h" |
| |
| #include <sys/types.h> |
| |
| #include <vector> |
| |
| #include "base/macros.h" |
| #include "base/stl_util.h" |
| #include "gtest/gtest.h" |
| #include "snapshot/test/test_thread_snapshot.h" |
| |
| namespace crashpad { |
| namespace test { |
| namespace { |
| |
| class MinidumpThreadIDMapTest : public testing::Test { |
| public: |
| MinidumpThreadIDMapTest() |
| : Test(), |
| thread_snapshots_(), |
| test_thread_snapshots_() { |
| } |
| |
| ~MinidumpThreadIDMapTest() override {} |
| |
| // testing::Test: |
| void SetUp() override { |
| for (size_t index = 0; index < base::size(test_thread_snapshots_); |
| ++index) { |
| thread_snapshots_.push_back(&test_thread_snapshots_[index]); |
| } |
| } |
| |
| protected: |
| static bool MapHasKeyValue( |
| const MinidumpThreadIDMap* map, uint64_t key, uint32_t expected_value) { |
| auto iterator = map->find(key); |
| if (iterator == map->end()) { |
| EXPECT_NE(iterator, map->end()); |
| return false; |
| } |
| if (iterator->second != expected_value) { |
| EXPECT_EQ(iterator->second, expected_value); |
| return false; |
| } |
| return true; |
| } |
| |
| void SetThreadID(size_t index, uint64_t thread_id) { |
| ASSERT_LT(index, base::size(test_thread_snapshots_)); |
| test_thread_snapshots_[index].SetThreadID(thread_id); |
| } |
| |
| const std::vector<const ThreadSnapshot*>& thread_snapshots() const { |
| return thread_snapshots_; |
| } |
| |
| private: |
| std::vector<const ThreadSnapshot*> thread_snapshots_; |
| TestThreadSnapshot test_thread_snapshots_[5]; |
| |
| DISALLOW_COPY_AND_ASSIGN(MinidumpThreadIDMapTest); |
| }; |
| |
| TEST_F(MinidumpThreadIDMapTest, NoThreads) { |
| // Don’t use thread_snapshots(), because it’s got some threads in it, and the |
| // point of this test is to make sure that BuildMinidumpThreadIDMap() works |
| // with no threads. |
| std::vector<const ThreadSnapshot*> thread_snapshots; |
| MinidumpThreadIDMap thread_id_map; |
| BuildMinidumpThreadIDMap(thread_snapshots, &thread_id_map); |
| |
| EXPECT_TRUE(thread_id_map.empty()); |
| } |
| |
| TEST_F(MinidumpThreadIDMapTest, SimpleMapping) { |
| SetThreadID(0, 1); |
| SetThreadID(1, 3); |
| SetThreadID(2, 5); |
| SetThreadID(3, 7); |
| SetThreadID(4, 9); |
| |
| MinidumpThreadIDMap thread_id_map; |
| BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map); |
| |
| EXPECT_EQ(thread_id_map.size(), 5u); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 1, 1); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 3, 3); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 5, 5); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 7, 7); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 9, 9); |
| } |
| |
| TEST_F(MinidumpThreadIDMapTest, Truncation) { |
| SetThreadID(0, 0x0000000000000000); |
| SetThreadID(1, 0x9999999900000001); |
| SetThreadID(2, 0x9999999980000001); |
| SetThreadID(3, 0x99999999fffffffe); |
| SetThreadID(4, 0x99999999ffffffff); |
| |
| MinidumpThreadIDMap thread_id_map; |
| BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map); |
| |
| EXPECT_EQ(thread_id_map.size(), 5u); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000000, 0x00000000); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x9999999900000001, 0x00000001); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x9999999980000001, 0x80000001); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x99999999fffffffe, 0xfffffffe); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x99999999ffffffff, 0xffffffff); |
| } |
| |
| TEST_F(MinidumpThreadIDMapTest, DuplicateThreadID) { |
| SetThreadID(0, 2); |
| SetThreadID(1, 4); |
| SetThreadID(2, 4); |
| SetThreadID(3, 6); |
| SetThreadID(4, 8); |
| |
| MinidumpThreadIDMap thread_id_map; |
| BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map); |
| |
| EXPECT_EQ(thread_id_map.size(), 4u); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 2, 2); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 4, 4); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 6, 6); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 8, 8); |
| } |
| |
| TEST_F(MinidumpThreadIDMapTest, Collision) { |
| SetThreadID(0, 0x0000000000000010); |
| SetThreadID(1, 0x0000000000000020); |
| SetThreadID(2, 0x0000000000000030); |
| SetThreadID(3, 0x0000000000000040); |
| SetThreadID(4, 0x0000000100000010); |
| |
| MinidumpThreadIDMap thread_id_map; |
| BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map); |
| |
| EXPECT_EQ(thread_id_map.size(), 5u); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000010, 0); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000020, 1); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000030, 2); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000040, 3); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000100000010, 4); |
| } |
| |
| TEST_F(MinidumpThreadIDMapTest, DuplicateAndCollision) { |
| SetThreadID(0, 0x0000000100000010); |
| SetThreadID(1, 0x0000000000000010); |
| SetThreadID(2, 0x0000000000000020); |
| SetThreadID(3, 0x0000000000000030); |
| SetThreadID(4, 0x0000000000000020); |
| |
| MinidumpThreadIDMap thread_id_map; |
| BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map); |
| |
| EXPECT_EQ(thread_id_map.size(), 4u); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000100000010, 0); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000010, 1); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000020, 2); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 0x0000000000000030, 3); |
| } |
| |
| TEST_F(MinidumpThreadIDMapTest, AllDuplicates) { |
| SetThreadID(0, 6); |
| SetThreadID(1, 6); |
| SetThreadID(2, 6); |
| SetThreadID(3, 6); |
| SetThreadID(4, 6); |
| |
| MinidumpThreadIDMap thread_id_map; |
| BuildMinidumpThreadIDMap(thread_snapshots(), &thread_id_map); |
| |
| EXPECT_EQ(thread_id_map.size(), 1u); |
| EXPECT_PRED3(MapHasKeyValue, &thread_id_map, 6, 6); |
| } |
| |
| } // namespace |
| } // namespace test |
| } // namespace crashpad |