Home | History | Annotate | Download | only in common
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/common/crash_keys.h"
      6 
      7 #include <map>
      8 #include <set>
      9 #include <string>
     10 
     11 #include "base/command_line.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/debug/crash_logging.h"
     14 #include "base/strings/string_piece.h"
     15 #include "base/strings/stringprintf.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 class CrashKeysTest : public testing::Test {
     19  public:
     20   virtual void SetUp() OVERRIDE {
     21     self_ = this;
     22     base::debug::SetCrashKeyReportingFunctions(
     23         &SetCrashKeyValue, &ClearCrashKey);
     24     crash_keys::RegisterChromeCrashKeys();
     25   }
     26 
     27   virtual void TearDown() OVERRIDE {
     28     base::debug::ResetCrashLoggingForTesting();
     29     self_ = NULL;
     30   }
     31 
     32   bool HasCrashKey(const std::string& key) {
     33     return keys_.find(key) != keys_.end();
     34   }
     35 
     36   std::string GetKeyValue(const std::string& key) {
     37     std::map<std::string, std::string>::const_iterator it = keys_.find(key);
     38     if (it == keys_.end())
     39       return std::string();
     40     return it->second;
     41   }
     42 
     43  private:
     44   static void SetCrashKeyValue(const base::StringPiece& key,
     45                                const base::StringPiece& value) {
     46     self_->keys_[key.as_string()] = value.as_string();
     47   }
     48 
     49   static void ClearCrashKey(const base::StringPiece& key) {
     50     self_->keys_.erase(key.as_string());
     51   }
     52 
     53   static CrashKeysTest* self_;
     54 
     55   std::map<std::string, std::string> keys_;
     56 };
     57 
     58 CrashKeysTest* CrashKeysTest::self_ = NULL;
     59 
     60 TEST_F(CrashKeysTest, Switches) {
     61   // Set three switches.
     62   {
     63     CommandLine command_line(CommandLine::NO_PROGRAM);
     64     for (int i = 1; i <= 3; ++i)
     65       command_line.AppendSwitch(base::StringPrintf("--flag-%d", i));
     66     crash_keys::SetSwitchesFromCommandLine(&command_line);
     67     EXPECT_EQ("--flag-1", GetKeyValue("switch-1"));
     68     EXPECT_EQ("--flag-2", GetKeyValue("switch-2"));
     69     EXPECT_EQ("--flag-3", GetKeyValue("switch-3"));
     70     EXPECT_FALSE(HasCrashKey("switch-4"));
     71   }
     72 
     73   // Set more than the max switches.
     74   {
     75     CommandLine command_line(CommandLine::NO_PROGRAM);
     76     const int kMax = crash_keys::kSwitchesMaxCount + 2;
     77     EXPECT_GT(kMax, 15);
     78     for (int i = 1; i <= kMax; ++i)
     79       command_line.AppendSwitch(base::StringPrintf("--many-%d", i));
     80     crash_keys::SetSwitchesFromCommandLine(&command_line);
     81     EXPECT_EQ("--many-1", GetKeyValue("switch-1"));
     82     EXPECT_EQ("--many-9", GetKeyValue("switch-9"));
     83     EXPECT_EQ("--many-15", GetKeyValue("switch-15"));
     84     EXPECT_FALSE(HasCrashKey("switch-16"));
     85     EXPECT_FALSE(HasCrashKey("switch-17"));
     86   }
     87 
     88   // Set fewer to ensure that old ones are erased.
     89   {
     90     CommandLine command_line(CommandLine::NO_PROGRAM);
     91     for (int i = 1; i <= 5; ++i)
     92       command_line.AppendSwitch(base::StringPrintf("--fewer-%d", i));
     93     crash_keys::SetSwitchesFromCommandLine(&command_line);
     94     EXPECT_EQ("--fewer-1", GetKeyValue("switch-1"));
     95     EXPECT_EQ("--fewer-2", GetKeyValue("switch-2"));
     96     EXPECT_EQ("--fewer-3", GetKeyValue("switch-3"));
     97     EXPECT_EQ("--fewer-4", GetKeyValue("switch-4"));
     98     EXPECT_EQ("--fewer-5", GetKeyValue("switch-5"));
     99     for (int i = 6; i < 20; ++i)
    100       EXPECT_FALSE(HasCrashKey(base::StringPrintf(crash_keys::kSwitch, i)));
    101   }
    102 }
    103 
    104 TEST_F(CrashKeysTest, Extensions) {
    105   // Set three extensions.
    106   {
    107     std::set<std::string> extensions;
    108     extensions.insert("ext.1");
    109     extensions.insert("ext.2");
    110     extensions.insert("ext.3");
    111 
    112     crash_keys::SetActiveExtensions(extensions);
    113 
    114     extensions.erase(GetKeyValue("extension-1"));
    115     extensions.erase(GetKeyValue("extension-2"));
    116     extensions.erase(GetKeyValue("extension-3"));
    117     EXPECT_EQ(0u, extensions.size());
    118 
    119     EXPECT_EQ("3", GetKeyValue("num-extensions"));
    120     EXPECT_FALSE(HasCrashKey("extension-4"));
    121   }
    122 
    123   // Set more than the max switches.
    124   {
    125     std::set<std::string> extensions;
    126     const int kMax = crash_keys::kExtensionIDMaxCount + 2;
    127     EXPECT_GT(kMax, 10);
    128     for (int i = 1; i <= kMax; ++i)
    129       extensions.insert(base::StringPrintf("ext.%d", i));
    130     crash_keys::SetActiveExtensions(extensions);
    131 
    132     for (int i = 1; i <= kMax; ++i) {
    133       extensions.erase(
    134           GetKeyValue(base::StringPrintf(crash_keys::kExtensionID, i)));
    135     }
    136     EXPECT_EQ(2u, extensions.size());
    137 
    138     EXPECT_EQ("12", GetKeyValue("num-extensions"));
    139     EXPECT_FALSE(HasCrashKey("extension-13"));
    140     EXPECT_FALSE(HasCrashKey("extension-14"));
    141   }
    142 
    143   // Set fewer to ensure that old ones are erased.
    144   {
    145     std::set<std::string> extensions;
    146     for (int i = 1; i <= 5; ++i)
    147       extensions.insert(base::StringPrintf("ext.%d", i));
    148     crash_keys::SetActiveExtensions(extensions);
    149 
    150     extensions.erase(GetKeyValue("extension-1"));
    151     extensions.erase(GetKeyValue("extension-2"));
    152     extensions.erase(GetKeyValue("extension-3"));
    153     extensions.erase(GetKeyValue("extension-4"));
    154     extensions.erase(GetKeyValue("extension-5"));
    155     EXPECT_EQ(0u, extensions.size());
    156 
    157     EXPECT_EQ("5", GetKeyValue("num-extensions"));
    158     for (int i = 6; i < 20; ++i) {
    159       std::string key = base::StringPrintf(crash_keys::kExtensionID, i);
    160       EXPECT_FALSE(HasCrashKey(key)) << key;
    161     }
    162   }
    163 }
    164 
    165 #if defined(OS_CHROMEOS)
    166 TEST_F(CrashKeysTest, IgnoreBoringFlags) {
    167   CommandLine command_line(CommandLine::NO_PROGRAM);
    168   command_line.AppendSwitch("--enable-logging");
    169   command_line.AppendSwitch("--user-data-dir=/tmp");
    170   command_line.AppendSwitch("--v=1");
    171   command_line.AppendSwitch("--ash-default-wallpaper-small=test.png");
    172 
    173   command_line.AppendSwitch("--vv=1");
    174   command_line.AppendSwitch("--vvv");
    175   command_line.AppendSwitch("--enable-multi-profiles");
    176   command_line.AppendSwitch("--device-management-url=https://foo/bar");
    177 
    178   crash_keys::SetSwitchesFromCommandLine(&command_line);
    179 
    180   EXPECT_EQ("--vv=1", GetKeyValue("switch-1"));
    181   EXPECT_EQ("--vvv", GetKeyValue("switch-2"));
    182   EXPECT_EQ("--enable-multi-profiles", GetKeyValue("switch-3"));
    183   EXPECT_EQ("--device-management-url=https://foo/bar", GetKeyValue("switch-4"));
    184   EXPECT_FALSE(HasCrashKey("switch-5"));
    185 }
    186 #endif
    187