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