blob: feedcbe640f1986f0c1003e682df036ff4b4725d [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"
#import <Foundation/Foundation.h>
#include "base/logging.h"
#include "base/mac/crash_logging.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 = [[NSMutableDictionary alloc] init];
}
~MockBreakpadKeyValueStore() {
// Only one of these objects can be active at once.
DCHECK(dict != NULL);
[dict release];
dict = NULL;
}
static void SetKeyValue(NSString* key, NSString* value) {
DCHECK(dict != NULL);
[dict setObject:value forKey:key];
}
static void ClearKeyValue(NSString *key) {
DCHECK(dict != NULL);
[dict removeObjectForKey:key];
}
int CountDictionaryEntries() {
return [dict count];
}
bool VerifyDictionaryContents(const std::string &url) {
using child_process_logging::kMaxNumCrashURLChunks;
using child_process_logging::kMaxNumURLChunkValueLength;
using child_process_logging::kUrlChunkFormatStr;
int num_url_chunks = CountDictionaryEntries();
EXPECT_TRUE(num_url_chunks <= kMaxNumCrashURLChunks);
NSString *kUrlChunkFormatStr_utf8 = [NSString
stringWithUTF8String:kUrlChunkFormatStr];
NSString *accumulated_url = @"";
for (int i = 0; i < num_url_chunks; ++i) {
// URL chunk names are 1-based.
NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1];
EXPECT_TRUE(key != NULL);
NSString *value = [dict objectForKey:key];
EXPECT_TRUE([value length] > 0);
EXPECT_TRUE([value length] <= (unsigned)kMaxNumURLChunkValueLength);
accumulated_url = [accumulated_url stringByAppendingString:value];
}
NSString *expected_url = [NSString stringWithUTF8String:url.c_str()];
return([accumulated_url isEqualToString:expected_url]);
}
private:
static NSMutableDictionary* dict;
DISALLOW_COPY_AND_ASSIGN(MockBreakpadKeyValueStore);
};
// static
NSMutableDictionary* MockBreakpadKeyValueStore::dict;
} // namespace
// Call through to SetActiveURLImpl using the functions from
// MockBreakpadKeyValueStore.
void SetActiveURLWithMock(const GURL& url) {
using child_process_logging::SetActiveURLImpl;
base::mac::SetCrashKeyValueFuncPtr setFunc =
MockBreakpadKeyValueStore::SetKeyValue;
base::mac::ClearCrashKeyValueFuncPtr 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(mock.CountDictionaryEntries(), 0);
// Check that we can set a URL.
SetActiveURLWithMock(GURL(short_url.c_str()));
EXPECT_TRUE(mock.VerifyDictionaryContents(short_url));
EXPECT_EQ(mock.CountDictionaryEntries(), 1);
SetActiveURLWithMock(GURL());
EXPECT_EQ(mock.CountDictionaryEntries(), 0);
// 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(mock.CountDictionaryEntries(), 0);
// 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(mock.CountDictionaryEntries(), 0);
}