Home | History | Annotate | Download | only in common
      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 
     13 typedef PlatformTest ChildProcessLoggingTest;
     14 
     15 namespace {
     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.
     21 class 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
     82 NSMutableDictionary* MockBreakpadKeyValueStore::dict;
     83 
     84 }  // namespace
     85 
     86 // Call through to SetActiveURLImpl using the functions from
     87 // MockBreakpadKeyValueStore.
     88 void 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 
     98 TEST_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