| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/crash/core/common/crash_keys.h" | 5 #include "components/crash/core/common/crash_keys.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/debug/crash_logging.h" | 14 #include "base/debug/crash_logging.h" |
| 15 #include "base/format_macros.h" | 15 #include "base/format_macros.h" |
| 16 #include "base/strings/string_piece.h" | 16 #include "base/strings/string_piece.h" |
| 17 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 19 |
| 20 class CrashKeysTest : public testing::Test { | 20 class CrashKeysTest : public testing::Test { |
| 21 public: | 21 public: |
| 22 void SetUp() override { | 22 void SetUp() override { |
| 23 self_ = this; | 23 self_ = this; |
| 24 base::debug::SetCrashKeyReportingFunctions( | 24 base::debug::SetCrashKeyReportingFunctions( |
| 25 &SetCrashKeyValue, &ClearCrashKey); | 25 &SetCrashKeyValue, &ClearCrashKey); |
| 26 } |
| 26 | 27 |
| 28 bool InitSwitchesCrashKeys() { |
| 27 std::vector<base::debug::CrashKey> keys; | 29 std::vector<base::debug::CrashKey> keys; |
| 28 crash_keys::GetCrashKeysForCommandLineSwitches(&keys); | 30 crash_keys::GetCrashKeysForCommandLineSwitches(&keys); |
| 29 base::debug::InitCrashKeys(keys.data(), keys.size(), | 31 return InitCrashKeys(keys); |
| 30 crash_keys::kChunkMaxLength); | 32 } |
| 31 ASSERT_FALSE(keys.empty()); | 33 |
| 34 bool InitVariationsCrashKeys() { |
| 35 std::vector<base::debug::CrashKey> keys = { |
| 36 {crash_keys::kNumVariations, crash_keys::kSmallSize}, |
| 37 {crash_keys::kVariations, crash_keys::kHugeSize}}; |
| 38 return InitCrashKeys(keys); |
| 32 } | 39 } |
| 33 | 40 |
| 34 void TearDown() override { | 41 void TearDown() override { |
| 35 base::debug::ResetCrashLoggingForTesting(); | 42 base::debug::ResetCrashLoggingForTesting(); |
| 36 self_ = NULL; | 43 self_ = NULL; |
| 37 } | 44 } |
| 38 | 45 |
| 39 bool HasCrashKey(const std::string& key) { | 46 bool HasCrashKey(const std::string& key) { |
| 40 return keys_.find(key) != keys_.end(); | 47 return keys_.find(key) != keys_.end(); |
| 41 } | 48 } |
| 42 | 49 |
| 43 std::string GetKeyValue(const std::string& key) { | 50 std::string GetKeyValue(const std::string& key) { |
| 44 std::map<std::string, std::string>::const_iterator it = keys_.find(key); | 51 std::map<std::string, std::string>::const_iterator it = keys_.find(key); |
| 45 if (it == keys_.end()) | 52 if (it == keys_.end()) |
| 46 return std::string(); | 53 return std::string(); |
| 47 return it->second; | 54 return it->second; |
| 48 } | 55 } |
| 49 | 56 |
| 50 private: | 57 private: |
| 58 bool InitCrashKeys(const std::vector<base::debug::CrashKey>& keys) { |
| 59 base::debug::InitCrashKeys(keys.data(), keys.size(), |
| 60 crash_keys::kChunkMaxLength); |
| 61 return !keys.empty(); |
| 62 } |
| 63 |
| 51 static void SetCrashKeyValue(const base::StringPiece& key, | 64 static void SetCrashKeyValue(const base::StringPiece& key, |
| 52 const base::StringPiece& value) { | 65 const base::StringPiece& value) { |
| 53 self_->keys_[key.as_string()] = value.as_string(); | 66 self_->keys_[key.as_string()] = value.as_string(); |
| 54 } | 67 } |
| 55 | 68 |
| 56 static void ClearCrashKey(const base::StringPiece& key) { | 69 static void ClearCrashKey(const base::StringPiece& key) { |
| 57 self_->keys_.erase(key.as_string()); | 70 self_->keys_.erase(key.as_string()); |
| 58 } | 71 } |
| 59 | 72 |
| 60 static CrashKeysTest* self_; | 73 static CrashKeysTest* self_; |
| 61 | 74 |
| 62 std::map<std::string, std::string> keys_; | 75 std::map<std::string, std::string> keys_; |
| 63 }; | 76 }; |
| 64 | 77 |
| 65 CrashKeysTest* CrashKeysTest::self_ = NULL; | 78 CrashKeysTest* CrashKeysTest::self_ = NULL; |
| 66 | 79 |
| 67 TEST_F(CrashKeysTest, Switches) { | 80 TEST_F(CrashKeysTest, Switches) { |
| 81 ASSERT_TRUE(InitSwitchesCrashKeys()); |
| 82 |
| 68 // Set three switches. | 83 // Set three switches. |
| 69 { | 84 { |
| 70 base::CommandLine command_line(base::CommandLine::NO_PROGRAM); | 85 base::CommandLine command_line(base::CommandLine::NO_PROGRAM); |
| 71 for (size_t i = 1; i <= 3; ++i) | 86 for (size_t i = 1; i <= 3; ++i) |
| 72 command_line.AppendSwitch(base::StringPrintf("--flag-%" PRIuS, i)); | 87 command_line.AppendSwitch(base::StringPrintf("--flag-%" PRIuS, i)); |
| 73 crash_keys::SetSwitchesFromCommandLine(command_line, nullptr); | 88 crash_keys::SetSwitchesFromCommandLine(command_line, nullptr); |
| 74 EXPECT_EQ("--flag-1", GetKeyValue("switch-1")); | 89 EXPECT_EQ("--flag-1", GetKeyValue("switch-1")); |
| 75 EXPECT_EQ("--flag-2", GetKeyValue("switch-2")); | 90 EXPECT_EQ("--flag-2", GetKeyValue("switch-2")); |
| 76 EXPECT_EQ("--flag-3", GetKeyValue("switch-3")); | 91 EXPECT_EQ("--flag-3", GetKeyValue("switch-3")); |
| 77 EXPECT_FALSE(HasCrashKey("switch-4")); | 92 EXPECT_FALSE(HasCrashKey("switch-4")); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 | 126 |
| 112 namespace { | 127 namespace { |
| 113 | 128 |
| 114 bool IsBoringFlag(const std::string& flag) { | 129 bool IsBoringFlag(const std::string& flag) { |
| 115 return flag.compare("--boring") == 0; | 130 return flag.compare("--boring") == 0; |
| 116 } | 131 } |
| 117 | 132 |
| 118 } // namespace | 133 } // namespace |
| 119 | 134 |
| 120 TEST_F(CrashKeysTest, FilterFlags) { | 135 TEST_F(CrashKeysTest, FilterFlags) { |
| 136 ASSERT_TRUE(InitSwitchesCrashKeys()); |
| 137 |
| 121 using crash_keys::kSwitchesMaxCount; | 138 using crash_keys::kSwitchesMaxCount; |
| 122 | 139 |
| 123 base::CommandLine command_line(base::CommandLine::NO_PROGRAM); | 140 base::CommandLine command_line(base::CommandLine::NO_PROGRAM); |
| 124 command_line.AppendSwitch("--not-boring-1"); | 141 command_line.AppendSwitch("--not-boring-1"); |
| 125 command_line.AppendSwitch("--boring"); | 142 command_line.AppendSwitch("--boring"); |
| 126 | 143 |
| 127 // Include the max number of non-boring switches, to make sure that only the | 144 // Include the max number of non-boring switches, to make sure that only the |
| 128 // switches actually included in the crash keys are counted. | 145 // switches actually included in the crash keys are counted. |
| 129 for (size_t i = 2; i <= kSwitchesMaxCount; ++i) | 146 for (size_t i = 2; i <= kSwitchesMaxCount; ++i) |
| 130 command_line.AppendSwitch(base::StringPrintf("--not-boring-%" PRIuS, i)); | 147 command_line.AppendSwitch(base::StringPrintf("--not-boring-%" PRIuS, i)); |
| 131 | 148 |
| 132 crash_keys::SetSwitchesFromCommandLine(command_line, &IsBoringFlag); | 149 crash_keys::SetSwitchesFromCommandLine(command_line, &IsBoringFlag); |
| 133 | 150 |
| 134 // If the boring keys are filtered out, every single key should now be | 151 // If the boring keys are filtered out, every single key should now be |
| 135 // not-boring. | 152 // not-boring. |
| 136 for (size_t i = 1; i <= kSwitchesMaxCount; ++i) { | 153 for (size_t i = 1; i <= kSwitchesMaxCount; ++i) { |
| 137 std::string switch_name = base::StringPrintf(crash_keys::kSwitchFormat, i); | 154 std::string switch_name = base::StringPrintf(crash_keys::kSwitchFormat, i); |
| 138 std::string switch_value = base::StringPrintf("--not-boring-%" PRIuS, i); | 155 std::string switch_value = base::StringPrintf("--not-boring-%" PRIuS, i); |
| 139 EXPECT_EQ(switch_value, GetKeyValue(switch_name)) << "switch_name is " << | 156 EXPECT_EQ(switch_value, GetKeyValue(switch_name)) << "switch_name is " << |
| 140 switch_name; | 157 switch_name; |
| 141 } | 158 } |
| 142 } | 159 } |
| 160 |
| 161 TEST_F(CrashKeysTest, VariationsCapacity) { |
| 162 ASSERT_TRUE(InitVariationsCrashKeys()); |
| 163 |
| 164 // Variation encoding: two 32bit numbers encorded as hex with a '-' separator. |
| 165 const char kSampleVariation[] = "12345678-12345678"; |
| 166 const size_t kVariationLen = std::strlen(kSampleVariation); |
| 167 const size_t kSeparatedVariationLen = kVariationLen + 1U; |
| 168 ASSERT_EQ(17U, kVariationLen); |
| 169 |
| 170 // The expected capacity factors in a separator (','). |
| 171 const size_t kExpectedCapacity = 112U; |
| 172 ASSERT_EQ(kExpectedCapacity, |
| 173 crash_keys::kHugeSize / (kSeparatedVariationLen)); |
| 174 |
| 175 // Create some variations and set the crash keys. |
| 176 std::vector<std::string> variations; |
| 177 for (size_t i = 0; i < kExpectedCapacity + 2; ++i) |
| 178 variations.push_back(kSampleVariation); |
| 179 crash_keys::SetVariationsList(variations); |
| 180 |
| 181 // Validate crash keys. |
| 182 ASSERT_TRUE(HasCrashKey(crash_keys::kNumVariations)); |
| 183 EXPECT_EQ("114", GetKeyValue(crash_keys::kNumVariations)); |
| 184 |
| 185 const size_t kExpectedChunks = (kSeparatedVariationLen * kExpectedCapacity) / |
| 186 crash_keys::kChunkMaxLength; |
| 187 for (size_t i = 0; i < kExpectedChunks; ++i) { |
| 188 ASSERT_TRUE(HasCrashKey( |
| 189 base::StringPrintf("%s-%" PRIuS, crash_keys::kVariations, i + 1))); |
| 190 } |
| 191 } |
| OLD | NEW |