1// Copyright (c) 2009 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 "chrome/common/child_process_logging.h" 6 7#import <Foundation/Foundation.h> 8 9#include "base/logging.h" 10#include "testing/gtest/include/gtest/gtest.h" 11#include "testing/platform_test.h" 12 13typedef PlatformTest ChildProcessLoggingTest; 14 15namespace { 16 17// Class to mock breakpad's setkeyvalue/clearkeyvalue functions needed for 18// SetActiveRendererURLImpl. 19// The Keys are stored in a static dictionary and methods are provided to 20// verify correctness. 21class MockBreakpadKeyValueStore { 22 public: 23 MockBreakpadKeyValueStore() { 24 // Only one of these objects can be active at once. 25 DCHECK(dict == NULL); 26 dict = [[NSMutableDictionary alloc] init]; 27 } 28 29 ~MockBreakpadKeyValueStore() { 30 // Only one of these objects can be active at once. 31 DCHECK(dict != NULL); 32 [dict release]; 33 dict = NULL; 34 } 35 36 static void SetKeyValue(NSString* key, NSString* value) { 37 DCHECK(dict != NULL); 38 [dict setObject:value forKey:key]; 39 } 40 41 static void ClearKeyValue(NSString *key) { 42 DCHECK(dict != NULL); 43 [dict removeObjectForKey:key]; 44 } 45 46 int CountDictionaryEntries() { 47 return [dict count]; 48 } 49 50 bool VerifyDictionaryContents(const std::string &url) { 51 using child_process_logging::kMaxNumCrashURLChunks; 52 using child_process_logging::kMaxNumURLChunkValueLength; 53 using child_process_logging::kUrlChunkFormatStr; 54 55 int num_url_chunks = CountDictionaryEntries(); 56 EXPECT_TRUE(num_url_chunks <= kMaxNumCrashURLChunks); 57 58 NSString *kUrlChunkFormatStr_utf8 = [NSString 59 stringWithUTF8String:kUrlChunkFormatStr]; 60 61 NSString *accumulated_url = @""; 62 for (int i = 0; i < num_url_chunks; ++i) { 63 // URL chunk names are 1-based. 64 NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1]; 65 EXPECT_TRUE(key != NULL); 66 NSString *value = [dict objectForKey:key]; 67 EXPECT_TRUE([value length] > 0); 68 EXPECT_TRUE([value length] <= (unsigned)kMaxNumURLChunkValueLength); 69 accumulated_url = [accumulated_url stringByAppendingString:value]; 70 } 71 72 NSString *expected_url = [NSString stringWithUTF8String:url.c_str()]; 73 return([accumulated_url isEqualToString:expected_url]); 74 } 75 76 private: 77 static NSMutableDictionary* dict; 78 DISALLOW_COPY_AND_ASSIGN(MockBreakpadKeyValueStore); 79}; 80 81// static 82NSMutableDictionary* MockBreakpadKeyValueStore::dict; 83 84} // namespace 85 86// Call through to SetActiveURLImpl using the functions from 87// MockBreakpadKeyValueStore. 88void SetActiveURLWithMock(const GURL& url) { 89 using child_process_logging::SetActiveURLImpl; 90 91 SetCrashKeyValueFuncPtr setFunc = MockBreakpadKeyValueStore::SetKeyValue; 92 ClearCrashKeyValueFuncPtr clearFunc = 93 MockBreakpadKeyValueStore::ClearKeyValue; 94 95 SetActiveURLImpl(url, setFunc, clearFunc); 96} 97 98TEST_F(ChildProcessLoggingTest, TestUrlSplitting) { 99 using child_process_logging::kMaxNumCrashURLChunks; 100 using child_process_logging::kMaxNumURLChunkValueLength; 101 102 const std::string short_url("http://abc/"); 103 std::string long_url("http://"); 104 std::string overflow_url("http://"); 105 106 long_url += std::string(kMaxNumURLChunkValueLength * 2, 'a'); 107 long_url += "/"; 108 109 int max_num_chars_stored_in_dump = kMaxNumURLChunkValueLength * 110 kMaxNumCrashURLChunks; 111 overflow_url += std::string(max_num_chars_stored_in_dump + 1, 'a'); 112 overflow_url += "/"; 113 114 // Check that Clearing NULL URL works. 115 MockBreakpadKeyValueStore mock; 116 SetActiveURLWithMock(GURL()); 117 EXPECT_EQ(mock.CountDictionaryEntries(), 0); 118 119 // Check that we can set a URL. 120 SetActiveURLWithMock(GURL(short_url.c_str())); 121 EXPECT_TRUE(mock.VerifyDictionaryContents(short_url)); 122 EXPECT_EQ(mock.CountDictionaryEntries(), 1); 123 SetActiveURLWithMock(GURL()); 124 EXPECT_EQ(mock.CountDictionaryEntries(), 0); 125 126 // Check that we can replace a long url with a short url. 127 SetActiveURLWithMock(GURL(long_url.c_str())); 128 EXPECT_TRUE(mock.VerifyDictionaryContents(long_url)); 129 SetActiveURLWithMock(GURL(short_url.c_str())); 130 EXPECT_TRUE(mock.VerifyDictionaryContents(short_url)); 131 SetActiveURLWithMock(GURL()); 132 EXPECT_EQ(mock.CountDictionaryEntries(), 0); 133 134 135 // Check that overflow works correctly. 136 SetActiveURLWithMock(GURL(overflow_url.c_str())); 137 EXPECT_TRUE(mock.VerifyDictionaryContents( 138 overflow_url.substr(0, max_num_chars_stored_in_dump))); 139 SetActiveURLWithMock(GURL()); 140 EXPECT_EQ(mock.CountDictionaryEntries(), 0); 141} 142