Home | History | Annotate | Download | only in allocator
      1 // Copyright 2014 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 // This is a unittest set for type_profiler.  It is independent from other
      6 // tests and executed manually like allocator_unittests since type_profiler_map
      7 // used in type_profiler is a singleton (like TCMalloc's heap-profiler), and
      8 // it requires RTTI and different compiling/linking options from others
      9 //
     10 // It tests that the profiler doesn't fail in suspicous cases.  For example,
     11 // 'new' is not profiled, but 'delete' for the created object is profiled.
     12 
     13 #if defined(TYPE_PROFILING)
     14 
     15 #include "base/allocator/type_profiler.h"
     16 #include "base/allocator/type_profiler_control.h"
     17 #include "base/allocator/type_profiler_tcmalloc.h"
     18 #include "base/basictypes.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h"
     21 
     22 namespace base {
     23 namespace type_profiler {
     24 
     25 class TypeProfilerTest : public testing::Test {
     26  public:
     27   TypeProfilerTest() {}
     28 
     29   void SetInterceptFunctions() {
     30     InterceptFunctions::SetFunctions(NewInterceptForTCMalloc,
     31                                      DeleteInterceptForTCMalloc);
     32   }
     33 
     34   void ResetInterceptFunctions() {
     35     InterceptFunctions::ResetFunctions();
     36   }
     37 
     38   void SetUp() {
     39     SetInterceptFunctions();
     40   }
     41 
     42   void TearDown() {
     43     ResetInterceptFunctions();
     44   }
     45 
     46  protected:
     47   static const size_t kDummyArraySize;
     48   static const void* const kConstNull;
     49 
     50  private:
     51   DISALLOW_COPY_AND_ASSIGN(TypeProfilerTest);
     52 };
     53 
     54 const size_t TypeProfilerTest::kDummyArraySize = 10;
     55 const void* const TypeProfilerTest::kConstNull = static_cast<const void*>(NULL);
     56 
     57 TEST_F(TypeProfilerTest, TestNormalProfiling) {
     58   int* dummy = new int(48);
     59   const std::type_info* type;
     60 
     61   type = LookupType(dummy);
     62   ASSERT_NE(kConstNull, type);
     63   EXPECT_STREQ(typeid(int).name(), type->name());
     64   delete dummy;
     65 
     66   type = LookupType(dummy);
     67   EXPECT_EQ(kConstNull, type);
     68 }
     69 
     70 TEST_F(TypeProfilerTest, TestNormalArrayProfiling) {
     71   int* dummy = new int[kDummyArraySize];
     72   const std::type_info* type;
     73 
     74   type = LookupType(dummy);
     75   ASSERT_NE(kConstNull, type);
     76   // For an array, the profiler remembers its base type.
     77   EXPECT_STREQ(typeid(int).name(), type->name());
     78   delete[] dummy;
     79 
     80   type = LookupType(dummy);
     81   EXPECT_EQ(kConstNull, type);
     82 }
     83 
     84 TEST_F(TypeProfilerTest, TestRepeatedNewAndDelete) {
     85   int *dummy[kDummyArraySize];
     86   const std::type_info* type;
     87   for (int i = 0; i < kDummyArraySize; ++i)
     88     dummy[i] = new int(i);
     89 
     90   for (int i = 0; i < kDummyArraySize; ++i) {
     91     type = LookupType(dummy[i]);
     92     ASSERT_NE(kConstNull, type);
     93     EXPECT_STREQ(typeid(int).name(), type->name());
     94   }
     95 
     96   for (int i = 0; i < kDummyArraySize; ++i) {
     97     delete dummy[i];
     98     type = LookupType(dummy[i]);
     99     ASSERT_EQ(kConstNull, type);
    100   }
    101 }
    102 
    103 TEST_F(TypeProfilerTest, TestMultipleNewWithDroppingDelete) {
    104   static const size_t large_size = 256 * 1024;
    105 
    106   char* dummy_char = new char[large_size / sizeof(*dummy_char)];
    107   const std::type_info* type;
    108 
    109   type = LookupType(dummy_char);
    110   ASSERT_NE(kConstNull, type);
    111   EXPECT_STREQ(typeid(char).name(), type->name());
    112 
    113   // Call "::operator delete" directly to drop __op_delete_intercept__.
    114   ::operator delete[](dummy_char);
    115 
    116   type = LookupType(dummy_char);
    117   ASSERT_NE(kConstNull, type);
    118   EXPECT_STREQ(typeid(char).name(), type->name());
    119 
    120   // Allocates a little different size.
    121   int* dummy_int = new int[large_size / sizeof(*dummy_int) - 1];
    122 
    123   // We expect that tcmalloc returns the same address for these large (over 32k)
    124   // allocation calls.  It usually happens, but maybe probablistic.
    125   ASSERT_EQ(static_cast<void*>(dummy_char), static_cast<void*>(dummy_int)) <<
    126       "two new (malloc) calls didn't return the same address; retry it.";
    127 
    128   type = LookupType(dummy_int);
    129   ASSERT_NE(kConstNull, type);
    130   EXPECT_STREQ(typeid(int).name(), type->name());
    131 
    132   delete[] dummy_int;
    133 
    134   type = LookupType(dummy_int);
    135   EXPECT_EQ(kConstNull, type);
    136 }
    137 
    138 TEST_F(TypeProfilerTest, TestProfileDeleteWithoutProfiledNew) {
    139   // 'dummy' should be new'ed in this test before intercept functions are set.
    140   ResetInterceptFunctions();
    141 
    142   int* dummy = new int(48);
    143   const std::type_info* type;
    144 
    145   // Set intercept functions again after 'dummy' is new'ed.
    146   SetInterceptFunctions();
    147 
    148   delete dummy;
    149 
    150   type = LookupType(dummy);
    151   EXPECT_EQ(kConstNull, type);
    152 
    153   ResetInterceptFunctions();
    154 }
    155 
    156 TEST_F(TypeProfilerTest, TestProfileNewWithoutProfiledDelete) {
    157   int* dummy = new int(48);
    158   const std::type_info* type;
    159 
    160   EXPECT_TRUE(Controller::IsProfiling());
    161 
    162   // Stop profiling before deleting 'dummy'.
    163   Controller::Stop();
    164   EXPECT_FALSE(Controller::IsProfiling());
    165 
    166   delete dummy;
    167 
    168   // NOTE: We accept that a profile entry remains when a profiled object is
    169   // deleted after Controller::Stop().
    170   type = LookupType(dummy);
    171   ASSERT_NE(kConstNull, type);
    172   EXPECT_STREQ(typeid(int).name(), type->name());
    173 
    174   Controller::Restart();
    175   EXPECT_TRUE(Controller::IsProfiling());
    176 
    177   // Remove manually since 'dummy' is not removed from type_profiler_map.
    178   EraseType(dummy);
    179 }
    180 
    181 }  // namespace type_profiler
    182 }  // namespace base
    183 
    184 #endif  // defined(TYPE_PROFILING)
    185 
    186 int main(int argc, char** argv) {
    187   testing::InitGoogleTest(&argc, argv);
    188   return RUN_ALL_TESTS();
    189 }
    190