1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
// Copyright 2013 The Chromium Authors
// 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_keys.h"
#include <string>
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/debug/crash_logging.h"
#include "base/format_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/crash/core/common/crash_key.h"
#include "testing/gtest/include/gtest/gtest.h"
using crash_reporter::GetCrashKeyValue;
// The number of switch-N keys declared in SetSwitchesFromCommandLine().
constexpr int kSwitchesMaxCount = 15;
class CrashKeysTest : public testing::Test {
public:
void SetUp() override {
ResetData();
crash_reporter::InitializeCrashKeysForTesting();
}
void TearDown() override {
ResetData();
}
private:
void ResetData() {
crash_keys::ResetCommandLineForTesting();
crash_reporter::ResetCrashKeysForTesting();
}
};
TEST_F(CrashKeysTest, Switches) {
// Set three switches.
{
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
for (size_t i = 1; i <= 3; ++i)
command_line.AppendSwitch(base::StringPrintf("--flag-%" PRIuS, i));
crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
EXPECT_EQ("--flag-1", GetCrashKeyValue("switch-1"));
EXPECT_EQ("--flag-2", GetCrashKeyValue("switch-2"));
EXPECT_EQ("--flag-3", GetCrashKeyValue("switch-3"));
EXPECT_TRUE(GetCrashKeyValue("switch-4").empty());
}
// Set more than 15 switches.
{
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
const size_t kMax = kSwitchesMaxCount + 2;
EXPECT_GT(kMax, static_cast<size_t>(15));
for (size_t i = 1; i <= kMax; ++i)
command_line.AppendSwitch(base::StringPrintf("--many-%" PRIuS, i));
crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
EXPECT_EQ("--many-1", GetCrashKeyValue("switch-1"));
EXPECT_EQ("--many-9", GetCrashKeyValue("switch-9"));
EXPECT_EQ("--many-15", GetCrashKeyValue("switch-15"));
EXPECT_FALSE(GetCrashKeyValue("switch-16").empty());
EXPECT_FALSE(GetCrashKeyValue("switch-17").empty());
}
// Set fewer to ensure that old ones are erased.
{
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
for (int i = 1; i <= 5; ++i)
command_line.AppendSwitch(base::StringPrintf("--fewer-%d", i));
crash_keys::SetSwitchesFromCommandLine(command_line, nullptr);
EXPECT_EQ("--fewer-1", GetCrashKeyValue("switch-1"));
EXPECT_EQ("--fewer-2", GetCrashKeyValue("switch-2"));
EXPECT_EQ("--fewer-3", GetCrashKeyValue("switch-3"));
EXPECT_EQ("--fewer-4", GetCrashKeyValue("switch-4"));
EXPECT_EQ("--fewer-5", GetCrashKeyValue("switch-5"));
for (int i = 6; i < 20; ++i)
EXPECT_TRUE(GetCrashKeyValue(base::StringPrintf("switch-%d", i)).empty());
}
}
namespace {
bool IsBoringFlag(const std::string& flag) {
return flag.compare("--boring") == 0;
}
} // namespace
TEST_F(CrashKeysTest, FilterFlags) {
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitch("--not-boring-1");
command_line.AppendSwitch("--boring");
// Include the max number of non-boring switches, to make sure that only the
// switches actually included in the crash keys are counted.
for (size_t i = 2; i <= kSwitchesMaxCount; ++i)
command_line.AppendSwitch(base::StringPrintf("--not-boring-%" PRIuS, i));
crash_keys::SetSwitchesFromCommandLine(command_line, &IsBoringFlag);
// If the boring keys are filtered out, every single key should now be
// not-boring.
for (int i = 1; i <= kSwitchesMaxCount; ++i) {
std::string switch_name = base::StringPrintf("switch-%d", i);
std::string switch_value = base::StringPrintf("--not-boring-%d", i);
EXPECT_EQ(switch_value, GetCrashKeyValue(switch_name))
<< "switch_name is " << switch_name;
}
}
TEST_F(CrashKeysTest, PrinterInfoReset) {
// After ScopedPrinterInfo goes out of scope, printer keys should be reset.
{
const std::vector<std::string> kPrinterInfoFull{"1", "2", "3", "4"};
crash_keys::ScopedPrinterInfo keys("dummy-printer", kPrinterInfoFull);
EXPECT_EQ(GetCrashKeyValue("prn-info-1"), "1");
EXPECT_EQ(GetCrashKeyValue("prn-info-2"), "2");
EXPECT_EQ(GetCrashKeyValue("prn-info-3"), "3");
EXPECT_EQ(GetCrashKeyValue("prn-info-4"), "4");
}
EXPECT_TRUE(GetCrashKeyValue("prn-info-1").empty());
EXPECT_TRUE(GetCrashKeyValue("prn-info-2").empty());
EXPECT_TRUE(GetCrashKeyValue("prn-info-3").empty());
EXPECT_TRUE(GetCrashKeyValue("prn-info-4").empty());
}
TEST_F(CrashKeysTest, PrinterInfoContainsSemicolon) {
// Provided data containing semicolons does not get split between keys.
constexpr char kWithoutSemicolon[] = "printer name";
constexpr char kWithSemicolon[] = "CUPS version 1.2; OS version 3.4";
const std::vector<std::string> kPrinterInfo{kWithoutSemicolon,
kWithSemicolon};
crash_keys::ScopedPrinterInfo keys("dummy-printer", kPrinterInfo);
EXPECT_EQ(GetCrashKeyValue("prn-info-1"), kWithoutSemicolon);
EXPECT_EQ(GetCrashKeyValue("prn-info-2"), kWithSemicolon);
EXPECT_TRUE(GetCrashKeyValue("prn-info-3").empty());
EXPECT_TRUE(GetCrashKeyValue("prn-info-4").empty());
}
TEST_F(CrashKeysTest, PrinterInfoNoData) {
// Provided data has no entries, so printer name is used for one key.
constexpr char kPrinterName[] = "dummy-printer";
crash_keys::ScopedPrinterInfo keys(kPrinterName, std::vector<std::string>());
EXPECT_EQ(GetCrashKeyValue("prn-info-1"), kPrinterName);
EXPECT_TRUE(GetCrashKeyValue("prn-info-2").empty());
EXPECT_TRUE(GetCrashKeyValue("prn-info-3").empty());
EXPECT_TRUE(GetCrashKeyValue("prn-info-4").empty());
}
|