blob: 2f62633d137826b6fbeed3792c776436dff52cec [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/child_process_logging.h"
#include <map>
#include <string>
#import <Foundation/Foundation.h>
#include "base/debug/crash_logging.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
typedef PlatformTest ChildProcessLoggingTest;
namespace {
// Class to mock breakpad's setkeyvalue/clearkeyvalue functions needed for
// SetActiveRendererURLImpl.
// The Keys are stored in a static dictionary and methods are provided to
// verify correctness.
class MockBreakpadKeyValueStore {
public:
MockBreakpadKeyValueStore() {
// Only one of these objects can be active at once.
DCHECK(dict == NULL);
dict = new std::map<std::string, std::string>;
}
~MockBreakpadKeyValueStore() {
// Only one of these objects can be active at once.
DCHECK(dict != NULL);
delete dict;
dict = NULL;
}
static void SetKeyValue(const base::StringPiece& key,
const base::StringPiece& value) {
DCHECK(dict != NULL);
(*dict)[key.as_string()] = value.as_string();
}
static void ClearKeyValue(const base::StringPiece& key) {
DCHECK(dict != NULL);
dict->erase(key.as_string());
}
size_t CountDictionaryEntries() {
return dict->size();
}
bool VerifyDictionaryContents(const std::string& url) {
using child_process_logging::kMaxNumCrashURLChunks;
using child_process_logging::kMaxNumURLChunkValueLength;
using child_process_logging::kUrlChunkFormatStr;
size_t num_url_chunks = CountDictionaryEntries();
EXPECT_LE(num_url_chunks, kMaxNumCrashURLChunks);
std::string accumulated_url;
for (size_t i = 0; i < num_url_chunks; ++i) {
// URL chunk names are 1-based.
std::string key = base::StringPrintf(kUrlChunkFormatStr, i + 1);
std::string value = (*dict)[key];
EXPECT_GT(value.length(), 0u);
EXPECT_LE(value.length(),
static_cast<size_t>(kMaxNumURLChunkValueLength));
accumulated_url += value;
}
return url == accumulated_url;
}
private:
static std::map<std::string, std::string>* dict;
DISALLOW_COPY_AND_ASSIGN(MockBreakpadKeyValueStore);
};
// static
std::map<std::string, std::string>* MockBreakpadKeyValueStore::dict;
} // namespace
// Call through to SetActiveURLImpl using the functions from
// MockBreakpadKeyValueStore.
void SetActiveURLWithMock(const GURL& url) {
using child_process_logging::SetActiveURLImpl;
base::debug::SetCrashKeyValueFuncT setFunc =
MockBreakpadKeyValueStore::SetKeyValue;
base::debug::ClearCrashKeyValueFuncT clearFunc =
MockBreakpadKeyValueStore::ClearKeyValue;
SetActiveURLImpl(url, setFunc, clearFunc);
}
TEST_F(ChildProcessLoggingTest, TestUrlSplitting) {
using child_process_logging::kMaxNumCrashURLChunks;
using child_process_logging::kMaxNumURLChunkValueLength;
const std::string short_url("http://abc/");
std::string long_url("http://");
std::string overflow_url("http://");
long_url += std::string(kMaxNumURLChunkValueLength * 2, 'a');
long_url += "/";
int max_num_chars_stored_in_dump = kMaxNumURLChunkValueLength *
kMaxNumCrashURLChunks;
overflow_url += std::string(max_num_chars_stored_in_dump + 1, 'a');
overflow_url += "/";
// Check that Clearing NULL URL works.
MockBreakpadKeyValueStore mock;
SetActiveURLWithMock(GURL());
EXPECT_EQ(0u, mock.CountDictionaryEntries());
// Check that we can set a URL.
SetActiveURLWithMock(GURL(short_url.c_str()));
EXPECT_TRUE(mock.VerifyDictionaryContents(short_url));
EXPECT_EQ(1u, mock.CountDictionaryEntries());
SetActiveURLWithMock(GURL());
EXPECT_EQ(0u, mock.CountDictionaryEntries());
// Check that we can replace a long url with a short url.
SetActiveURLWithMock(GURL(long_url.c_str()));
EXPECT_TRUE(mock.VerifyDictionaryContents(long_url));
SetActiveURLWithMock(GURL(short_url.c_str()));
EXPECT_TRUE(mock.VerifyDictionaryContents(short_url));
SetActiveURLWithMock(GURL());
EXPECT_EQ(0u, mock.CountDictionaryEntries());
// Check that overflow works correctly.
SetActiveURLWithMock(GURL(overflow_url.c_str()));
EXPECT_TRUE(mock.VerifyDictionaryContents(
overflow_url.substr(0, max_num_chars_stored_in_dump)));
SetActiveURLWithMock(GURL());
EXPECT_EQ(0u, mock.CountDictionaryEntries());
}