| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/crash/core/common/crash_key.h" |
| |
| #include "components/crash/core/common/crash_key_internal.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace crash_reporter { |
| |
| class CrashKeyBreakpadTest : public testing::Test { |
| public: |
| void SetUp() override { |
| InitializeCrashKeys(); |
| ASSERT_TRUE(internal::GetCrashKeyStorage()); |
| } |
| |
| void TearDown() override { internal::ResetCrashKeyStorageForTesting(); } |
| |
| internal::TransitionalCrashKeyStorage* storage() { |
| return internal::GetCrashKeyStorage(); |
| } |
| |
| size_t* GetIndexArray(internal::CrashKeyStringImpl* key) { |
| return key->index_array_; |
| } |
| size_t GetIndexArrayCount(internal::CrashKeyStringImpl* key) { |
| return key->index_array_count_; |
| } |
| }; |
| |
| TEST_F(CrashKeyBreakpadTest, ConstantAssertions) { |
| // Tests in this file generate and validate data based on constants |
| // having specific values. This test asserts those assumptions. |
| EXPECT_EQ(128u, internal::kCrashKeyStorageValueSize); |
| } |
| |
| TEST_F(CrashKeyBreakpadTest, Allocation) { |
| const size_t kSentinel = internal::kCrashKeyStorageNumEntries; |
| |
| static CrashKeyString<32> key1("short"); |
| ASSERT_EQ(1u, GetIndexArrayCount(&key1)); |
| auto* indexes = GetIndexArray(&key1); |
| EXPECT_EQ(kSentinel, indexes[0]); |
| |
| // An extra index slot is created for lengths equal to the value size. |
| static CrashKeyString<128> key2("extra"); |
| ASSERT_EQ(2u, GetIndexArrayCount(&key2)); |
| indexes = GetIndexArray(&key2); |
| EXPECT_EQ(kSentinel, indexes[0]); |
| EXPECT_EQ(kSentinel, indexes[1]); |
| |
| static CrashKeyString<395> key3("large"); |
| ASSERT_EQ(4u, GetIndexArrayCount(&key3)); |
| indexes = GetIndexArray(&key3); |
| EXPECT_EQ(kSentinel, indexes[0]); |
| EXPECT_EQ(kSentinel, indexes[1]); |
| EXPECT_EQ(kSentinel, indexes[2]); |
| EXPECT_EQ(kSentinel, indexes[3]); |
| } |
| |
| TEST_F(CrashKeyBreakpadTest, SetClearSingle) { |
| static CrashKeyString<32> key("test-key"); |
| |
| EXPECT_FALSE(storage()->GetValueForKey("test-key")); |
| EXPECT_EQ(0u, storage()->GetCount()); |
| |
| key.Set("value"); |
| |
| ASSERT_EQ(1u, storage()->GetCount()); |
| EXPECT_STREQ("value", storage()->GetValueForKey("test-key")); |
| |
| key.Set("value 2"); |
| |
| ASSERT_EQ(1u, storage()->GetCount()); |
| EXPECT_STREQ("value 2", storage()->GetValueForKey("test-key")); |
| |
| key.Clear(); |
| |
| EXPECT_FALSE(storage()->GetValueForKey("test-key")); |
| EXPECT_EQ(0u, storage()->GetCount()); |
| } |
| |
| TEST_F(CrashKeyBreakpadTest, SetChunked) { |
| std::string chunk1(128, 'A'); |
| std::string chunk2(128, 'B'); |
| std::string chunk3(128, 'C'); |
| |
| static CrashKeyString<400> key("chunky"); |
| |
| EXPECT_EQ(0u, storage()->GetCount()); |
| |
| key.Set((chunk1 + chunk2 + chunk3).c_str()); |
| |
| ASSERT_EQ(4u, storage()->GetCount()); |
| |
| // Since chunk1 through chunk3 are the same size as a storage slot, |
| // and the storage NUL-terminates the value, ensure no bytes are |
| // lost when chunking. |
| EXPECT_EQ(std::string(127, 'A'), storage()->GetValueForKey("chunky__1")); |
| EXPECT_EQ(std::string("A") + std::string(126, 'B'), |
| storage()->GetValueForKey("chunky__2")); |
| EXPECT_EQ(std::string(2, 'B') + std::string(125, 'C'), |
| storage()->GetValueForKey("chunky__3")); |
| EXPECT_EQ(std::string(3, 'C'), storage()->GetValueForKey("chunky__4")); |
| |
| std::string chunk4(240, 'D'); |
| |
| key.Set(chunk4.c_str()); |
| |
| ASSERT_EQ(2u, storage()->GetCount()); |
| |
| EXPECT_EQ(std::string(127, 'D'), storage()->GetValueForKey("chunky__1")); |
| EXPECT_EQ(std::string(240 - 127, 'D'), |
| storage()->GetValueForKey("chunky__2")); |
| EXPECT_FALSE(storage()->GetValueForKey("chunky__3")); |
| |
| key.Clear(); |
| |
| EXPECT_EQ(0u, storage()->GetCount()); |
| } |
| |
| TEST_F(CrashKeyBreakpadTest, SetTwoChunked) { |
| static CrashKeyString<600> key1("big"); |
| static CrashKeyString<256> key2("small"); |
| |
| EXPECT_EQ(0u, storage()->GetCount()); |
| |
| key1.Set(std::string(200, '1').c_str()); |
| |
| ASSERT_EQ(2u, storage()->GetCount()); |
| |
| EXPECT_EQ(std::string(127, '1'), storage()->GetValueForKey("big__1")); |
| EXPECT_EQ(std::string(73, '1'), storage()->GetValueForKey("big__2")); |
| |
| key2.Set(std::string(256, '2').c_str()); |
| |
| ASSERT_EQ(5u, storage()->GetCount()); |
| |
| EXPECT_EQ(std::string(127, '1'), storage()->GetValueForKey("big__1")); |
| EXPECT_EQ(std::string(73, '1'), storage()->GetValueForKey("big__2")); |
| EXPECT_EQ(std::string(127, '2'), storage()->GetValueForKey("small__1")); |
| EXPECT_EQ(std::string(127, '2'), storage()->GetValueForKey("small__2")); |
| EXPECT_EQ(std::string(2, '2'), storage()->GetValueForKey("small__3")); |
| |
| key1.Set(std::string(510, '3').c_str()); |
| |
| ASSERT_EQ(8u, storage()->GetCount()); |
| |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__1")); |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__2")); |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__3")); |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__4")); |
| EXPECT_EQ(std::string(2, '3'), storage()->GetValueForKey("big__5")); |
| EXPECT_EQ(std::string(127, '2'), storage()->GetValueForKey("small__1")); |
| EXPECT_EQ(std::string(127, '2'), storage()->GetValueForKey("small__2")); |
| EXPECT_EQ(std::string(2, '2'), storage()->GetValueForKey("small__3")); |
| |
| key2.Clear(); |
| |
| ASSERT_EQ(5u, storage()->GetCount()); |
| |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__1")); |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__2")); |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__3")); |
| EXPECT_EQ(std::string(127, '3'), storage()->GetValueForKey("big__4")); |
| EXPECT_EQ(std::string(2, '3'), storage()->GetValueForKey("big__5")); |
| } |
| |
| TEST_F(CrashKeyBreakpadTest, ChunkSingleEntry) { |
| static CrashKeyString<200> crash_key("split"); |
| |
| EXPECT_EQ(0u, storage()->GetCount()); |
| |
| crash_key.Set("test"); |
| |
| ASSERT_EQ(1u, storage()->GetCount()); |
| EXPECT_STREQ("test", storage()->GetValueForKey("split")); |
| |
| crash_key.Set(std::string(127, 'z') + "bloop"); |
| |
| ASSERT_EQ(2u, storage()->GetCount()); |
| EXPECT_EQ(std::string(127, 'z'), storage()->GetValueForKey("split__1")); |
| EXPECT_STREQ("bloop", storage()->GetValueForKey("split__2")); |
| |
| crash_key.Set("abcdefg"); |
| |
| ASSERT_EQ(1u, storage()->GetCount()); |
| EXPECT_STREQ("abcdefg", storage()->GetValueForKey("split")); |
| |
| crash_key.Set("hijklmnop"); |
| |
| ASSERT_EQ(1u, storage()->GetCount()); |
| EXPECT_STREQ("hijklmnop", storage()->GetValueForKey("split")); |
| } |
| |
| } // namespace crash_reporter |