12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/crash_logging.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::map<std::string, std::string>* key_values_ = NULL;
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CrashLoggingTest : public testing::Test {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_values_ = new std::map<std::string, std::string>;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::debug::SetCrashKeyReportingFunctions(
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &CrashLoggingTest::SetKeyValue,
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &CrashLoggingTest::ClearKeyValue);
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::debug::ResetCrashLoggingForTesting();
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete key_values_;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_values_ = NULL;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void SetKeyValue(const base::StringPiece& key,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const base::StringPiece& value) {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*key_values_)[key.as_string()] = value.as_string();
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void ClearKeyValue(const base::StringPiece& key) {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_values_->erase(key.as_string());
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(CrashLoggingTest, SetClearSingle) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kTestKey = "test-key";
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::CrashKey keys[] = { { kTestKey, 255 } };
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::InitCrashKeys(keys, arraysize(keys), 255);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::SetCrashKeyValue(kTestKey, "value");
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("value", (*key_values_)[kTestKey]);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::ClearCrashKey(kTestKey);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(key_values_->end() == key_values_->find(kTestKey));
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(CrashLoggingTest, SetChunked) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kTestKey = "chunky";
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kChunk1 = "chunky-1";
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kChunk2 = "chunky-2";
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kChunk3 = "chunky-3";
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::CrashKey keys[] = { { kTestKey, 15 } };
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::InitCrashKeys(keys, arraysize(keys), 5);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<std::string, std::string>& values = *key_values_;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fill only the first chunk.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::SetCrashKeyValue(kTestKey, "foo");
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1u, values.size());
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("foo", values[kChunk1]);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk2));
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk3));
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fill three chunks with truncation (max length is 15, this string is 20).
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::SetCrashKeyValue(kTestKey, "five four three two");
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3u, values.size());
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("five ", values[kChunk1]);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("four ", values[kChunk2]);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("three", values[kChunk3]);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clear everything.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::ClearCrashKey(kTestKey);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, values.size());
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk1));
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk2));
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk3));
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Refill all three chunks with truncation, then test that setting a smaller
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // value clears the third chunk.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::SetCrashKeyValue(kTestKey, "five four three two");
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::SetCrashKeyValue(kTestKey, "allays");
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2u, values.size());
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("allay", values[kChunk1]);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("s", values[kChunk2]);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk3));
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clear everything.
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::ClearCrashKey(kTestKey);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, values.size());
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk1));
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk2));
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(values.end() == values.find(kChunk3));
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(CrashLoggingTest, ScopedCrashKey) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kTestKey = "test-key";
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::CrashKey keys[] = { { kTestKey, 255 } };
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::InitCrashKeys(keys, arraysize(keys), 255);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, key_values_->size());
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(key_values_->end() == key_values_->find(kTestKey));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::debug::ScopedCrashKey scoped_crash_key(kTestKey, "value");
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ("value", (*key_values_)[kTestKey]);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(1u, key_values_->size());
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, key_values_->size());
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(key_values_->end() == key_values_->find(kTestKey));
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(CrashLoggingTest, InitSize) {
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::CrashKey keys[] = {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "chunked-3", 15 },
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "single", 5 },
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { "chunked-6", 30 },
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t num_keys = base::debug::InitCrashKeys(keys, arraysize(keys), 5);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(10u, num_keys);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(base::debug::LookupCrashKey("chunked-3"));
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(base::debug::LookupCrashKey("single"));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(base::debug::LookupCrashKey("chunked-6"));
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(base::debug::LookupCrashKey("chunked-6-4"));
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(CrashLoggingTest, ChunkValue) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using base::debug::ChunkCrashKeyValue;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test truncation.
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::CrashKey key = { "chunky", 10 };
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> results =
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ChunkCrashKeyValue(key, "hello world", 64);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1u, results.size());
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("hello worl", results[0]);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test short string.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  results = ChunkCrashKeyValue(key, "hi", 10);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1u, results.size());
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("hi", results[0]);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test chunk pair.
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  key.max_length = 6;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  results = ChunkCrashKeyValue(key, "foobar", 3);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(2u, results.size());
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("foo", results[0]);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("bar", results[1]);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test chunk pair truncation.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  results = ChunkCrashKeyValue(key, "foobared", 3);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(2u, results.size());
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("foo", results[0]);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("bar", results[1]);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test extra chunks.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  key.max_length = 100;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  results = ChunkCrashKeyValue(key, "hello world", 3);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(4u, results.size());
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("hel", results[0]);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("lo ", results[1]);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("wor", results[2]);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("ld",  results[3]);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(CrashLoggingTest, ChunkRounding) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If max_length=12 and max_chunk_length=5, there should be 3 chunks,
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not 2.
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::debug::CrashKey key = { "round", 12 };
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3u, base::debug::InitCrashKeys(&key, 1, 5));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
183