// 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 #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); }