Home | History | Annotate | Download | only in debug
      1 // Copyright (c) 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 "base/debug/crash_logging.h"
      6 
      7 #include <map>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 namespace {
     14 
     15 std::map<std::string, std::string>* key_values_ = NULL;
     16 
     17 }  // namespace
     18 
     19 class CrashLoggingTest : public testing::Test {
     20  public:
     21   virtual void SetUp() {
     22     key_values_ = new std::map<std::string, std::string>;
     23     base::debug::SetCrashKeyReportingFunctions(
     24         &CrashLoggingTest::SetKeyValue,
     25         &CrashLoggingTest::ClearKeyValue);
     26   }
     27 
     28   virtual void TearDown() {
     29     base::debug::ResetCrashLoggingForTesting();
     30 
     31     delete key_values_;
     32     key_values_ = NULL;
     33   }
     34 
     35  private:
     36   static void SetKeyValue(const base::StringPiece& key,
     37                           const base::StringPiece& value) {
     38     (*key_values_)[key.as_string()] = value.as_string();
     39   }
     40 
     41   static void ClearKeyValue(const base::StringPiece& key) {
     42     key_values_->erase(key.as_string());
     43   }
     44 };
     45 
     46 TEST_F(CrashLoggingTest, SetClearSingle) {
     47   const char* kTestKey = "test-key";
     48   base::debug::CrashKey keys[] = { { kTestKey, 255 } };
     49   base::debug::InitCrashKeys(keys, arraysize(keys), 255);
     50 
     51   base::debug::SetCrashKeyValue(kTestKey, "value");
     52   EXPECT_EQ("value", (*key_values_)[kTestKey]);
     53 
     54   base::debug::ClearCrashKey(kTestKey);
     55   EXPECT_TRUE(key_values_->end() == key_values_->find(kTestKey));
     56 }
     57 
     58 TEST_F(CrashLoggingTest, SetChunked) {
     59   const char* kTestKey = "chunky";
     60   const char* kChunk1 = "chunky-1";
     61   const char* kChunk2 = "chunky-2";
     62   const char* kChunk3 = "chunky-3";
     63   base::debug::CrashKey keys[] = { { kTestKey, 15 } };
     64   base::debug::InitCrashKeys(keys, arraysize(keys), 5);
     65 
     66   std::map<std::string, std::string>& values = *key_values_;
     67 
     68   // Fill only the first chunk.
     69   base::debug::SetCrashKeyValue(kTestKey, "foo");
     70   EXPECT_EQ(1u, values.size());
     71   EXPECT_EQ("foo", values[kChunk1]);
     72   EXPECT_TRUE(values.end() == values.find(kChunk2));
     73   EXPECT_TRUE(values.end() == values.find(kChunk3));
     74 
     75   // Fill three chunks with truncation (max length is 15, this string is 20).
     76   base::debug::SetCrashKeyValue(kTestKey, "five four three two");
     77   EXPECT_EQ(3u, values.size());
     78   EXPECT_EQ("five ", values[kChunk1]);
     79   EXPECT_EQ("four ", values[kChunk2]);
     80   EXPECT_EQ("three", values[kChunk3]);
     81 
     82   // Clear everything.
     83   base::debug::ClearCrashKey(kTestKey);
     84   EXPECT_EQ(0u, values.size());
     85   EXPECT_TRUE(values.end() == values.find(kChunk1));
     86   EXPECT_TRUE(values.end() == values.find(kChunk2));
     87   EXPECT_TRUE(values.end() == values.find(kChunk3));
     88 
     89   // Refill all three chunks with truncation, then test that setting a smaller
     90   // value clears the third chunk.
     91   base::debug::SetCrashKeyValue(kTestKey, "five four three two");
     92   base::debug::SetCrashKeyValue(kTestKey, "allays");
     93   EXPECT_EQ(2u, values.size());
     94   EXPECT_EQ("allay", values[kChunk1]);
     95   EXPECT_EQ("s", values[kChunk2]);
     96   EXPECT_TRUE(values.end() == values.find(kChunk3));
     97 
     98   // Clear everything.
     99   base::debug::ClearCrashKey(kTestKey);
    100   EXPECT_EQ(0u, values.size());
    101   EXPECT_TRUE(values.end() == values.find(kChunk1));
    102   EXPECT_TRUE(values.end() == values.find(kChunk2));
    103   EXPECT_TRUE(values.end() == values.find(kChunk3));
    104 }
    105 
    106 TEST_F(CrashLoggingTest, ScopedCrashKey) {
    107   const char* kTestKey = "test-key";
    108   base::debug::CrashKey keys[] = { { kTestKey, 255 } };
    109   base::debug::InitCrashKeys(keys, arraysize(keys), 255);
    110 
    111   EXPECT_EQ(0u, key_values_->size());
    112   EXPECT_TRUE(key_values_->end() == key_values_->find(kTestKey));
    113   {
    114     base::debug::ScopedCrashKey scoped_crash_key(kTestKey, "value");
    115     EXPECT_EQ("value", (*key_values_)[kTestKey]);
    116     EXPECT_EQ(1u, key_values_->size());
    117   }
    118   EXPECT_EQ(0u, key_values_->size());
    119   EXPECT_TRUE(key_values_->end() == key_values_->find(kTestKey));
    120 }
    121 
    122 TEST_F(CrashLoggingTest, InitSize) {
    123   base::debug::CrashKey keys[] = {
    124     { "chunked-3", 15 },
    125     { "single", 5 },
    126     { "chunked-6", 30 },
    127   };
    128 
    129   size_t num_keys = base::debug::InitCrashKeys(keys, arraysize(keys), 5);
    130 
    131   EXPECT_EQ(10u, num_keys);
    132 
    133   EXPECT_TRUE(base::debug::LookupCrashKey("chunked-3"));
    134   EXPECT_TRUE(base::debug::LookupCrashKey("single"));
    135   EXPECT_TRUE(base::debug::LookupCrashKey("chunked-6"));
    136   EXPECT_FALSE(base::debug::LookupCrashKey("chunked-6-4"));
    137 }
    138 
    139 TEST_F(CrashLoggingTest, ChunkValue) {
    140   using base::debug::ChunkCrashKeyValue;
    141 
    142   // Test truncation.
    143   base::debug::CrashKey key = { "chunky", 10 };
    144   std::vector<std::string> results =
    145       ChunkCrashKeyValue(key, "hello world", 64);
    146   ASSERT_EQ(1u, results.size());
    147   EXPECT_EQ("hello worl", results[0]);
    148 
    149   // Test short string.
    150   results = ChunkCrashKeyValue(key, "hi", 10);
    151   ASSERT_EQ(1u, results.size());
    152   EXPECT_EQ("hi", results[0]);
    153 
    154   // Test chunk pair.
    155   key.max_length = 6;
    156   results = ChunkCrashKeyValue(key, "foobar", 3);
    157   ASSERT_EQ(2u, results.size());
    158   EXPECT_EQ("foo", results[0]);
    159   EXPECT_EQ("bar", results[1]);
    160 
    161   // Test chunk pair truncation.
    162   results = ChunkCrashKeyValue(key, "foobared", 3);
    163   ASSERT_EQ(2u, results.size());
    164   EXPECT_EQ("foo", results[0]);
    165   EXPECT_EQ("bar", results[1]);
    166 
    167   // Test extra chunks.
    168   key.max_length = 100;
    169   results = ChunkCrashKeyValue(key, "hello world", 3);
    170   ASSERT_EQ(4u, results.size());
    171   EXPECT_EQ("hel", results[0]);
    172   EXPECT_EQ("lo ", results[1]);
    173   EXPECT_EQ("wor", results[2]);
    174   EXPECT_EQ("ld",  results[3]);
    175 }
    176 
    177 TEST_F(CrashLoggingTest, ChunkRounding) {
    178   // If max_length=12 and max_chunk_length=5, there should be 3 chunks,
    179   // not 2.
    180   base::debug::CrashKey key = { "round", 12 };
    181   EXPECT_EQ(3u, base::debug::InitCrashKeys(&key, 1, 5));
    182 }
    183