Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2007, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // ---
     31 // Author: Arun Sharma
     32 
     33 #include "config_for_unittests.h"
     34 #include "system-alloc.h"
     35 #include <stdio.h>
     36 #if defined HAVE_STDINT_H
     37 #include <stdint.h>             // to get uintptr_t
     38 #elif defined HAVE_INTTYPES_H
     39 #include <inttypes.h>           // another place uintptr_t might be defined
     40 #endif
     41 #include <sys/types.h>
     42 #include <algorithm>
     43 #include <limits>
     44 #include "base/logging.h"               // for Check_GEImpl, Check_LTImpl, etc
     45 #include <gperftools/malloc_extension.h>    // for MallocExtension::instance
     46 #include "common.h"                     // for kAddressBits
     47 
     48 class ArraySysAllocator : public SysAllocator {
     49 public:
     50   // Was this allocator invoked at least once?
     51   bool invoked_;
     52 
     53   ArraySysAllocator() : SysAllocator() {
     54     ptr_ = 0;
     55     invoked_ = false;
     56   }
     57 
     58   void* Alloc(size_t size, size_t *actual_size, size_t alignment) {
     59     invoked_ = true;
     60 
     61     if (size > kArraySize) {
     62       return NULL;
     63     }
     64 
     65     void *result = &array_[ptr_];
     66     uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
     67 
     68     if (actual_size) {
     69       *actual_size = size;
     70     }
     71 
     72     // Try to get more memory for alignment
     73     size_t extra = alignment - (ptr & (alignment-1));
     74     size += extra;
     75     CHECK_LT(ptr_ + size, kArraySize);
     76 
     77     if ((ptr & (alignment-1)) != 0) {
     78       ptr += alignment - (ptr & (alignment-1));
     79     }
     80 
     81     ptr_ += size;
     82     return reinterpret_cast<void *>(ptr);
     83   }
     84 
     85   void DumpStats() {
     86   }
     87 
     88 private:
     89   static const int kArraySize = 8 * 1024 * 1024;
     90   char array_[kArraySize];
     91   // We allocate the next chunk from here
     92   int ptr_;
     93 
     94 };
     95 const int ArraySysAllocator::kArraySize;
     96 ArraySysAllocator a;
     97 
     98 static void TestBasicInvoked() {
     99   MallocExtension::instance()->SetSystemAllocator(&a);
    100 
    101   // An allocation size that is likely to trigger the system allocator.
    102   // XXX: this is implementation specific.
    103   char *p = new char[1024 * 1024];
    104   delete [] p;
    105 
    106   // Make sure that our allocator was invoked.
    107   CHECK(a.invoked_);
    108 }
    109 
    110 #if 0  // could port this to various OSs, but won't bother for now
    111 TEST(AddressBits, CpuVirtualBits) {
    112   // Check that kAddressBits is as least as large as either the number of bits
    113   // in a pointer or as the number of virtual bits handled by the processor.
    114   // To be effective this test must be run on each processor model.
    115   const int kPointerBits = 8 * sizeof(void*);
    116   const int kImplementedVirtualBits = NumImplementedVirtualBits();
    117 
    118   CHECK_GE(kAddressBits, std::min(kImplementedVirtualBits, kPointerBits));
    119 }
    120 #endif
    121 
    122 static void TestBasicRetryFailTest() {
    123   // Check with the allocator still works after a failed allocation.
    124   //
    125   // There is no way to call malloc and guarantee it will fail.  malloc takes a
    126   // size_t parameter and the C++ standard does not constrain the size of
    127   // size_t.  For example, consider an implementation where size_t is 32 bits
    128   // and pointers are 64 bits.
    129   //
    130   // It is likely, though, that sizeof(size_t) == sizeof(void*).  In that case,
    131   // the first allocation here might succeed but the second allocation must
    132   // fail.
    133   //
    134   // If the second allocation succeeds, you will have to rewrite or
    135   // disable this test.
    136   // The weird parens are to avoid macro-expansion of 'max' on windows.
    137   const size_t kHugeSize = (std::numeric_limits<size_t>::max)() / 2;
    138   void* p1 = malloc(kHugeSize);
    139   void* p2 = malloc(kHugeSize);
    140   CHECK(p2 == NULL);
    141   if (p1 != NULL) free(p1);
    142 
    143   char* q = new char[1024];
    144   CHECK(q != NULL);
    145   delete [] q;
    146 }
    147 
    148 int main(int argc, char** argv) {
    149   TestBasicInvoked();
    150   TestBasicRetryFailTest();
    151 
    152   printf("PASS\n");
    153   return 0;
    154 }
    155