low_level_alloc_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/base/internal/low_level_alloc.h"
00016 
00017 #include <stdint.h>
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <thread>  // NOLINT(build/c++11)
00021 #include <unordered_map>
00022 #include <utility>
00023 
00024 namespace absl {
00025 namespace base_internal {
00026 namespace {
00027 
00028 // This test doesn't use gtest since it needs to test that everything
00029 // works before main().
00030 #define TEST_ASSERT(x)                                           \
00031   if (!(x)) {                                                    \
00032     printf("TEST_ASSERT(%s) FAILED ON LINE %d\n", #x, __LINE__); \
00033     abort();                                                     \
00034   }
00035 
00036 // a block of memory obtained from the allocator
00037 struct BlockDesc {
00038   char *ptr;      // pointer to memory
00039   int len;        // number of bytes
00040   int fill;       // filled with data starting with this
00041 };
00042 
00043 // Check that the pattern placed in the block d
00044 // by RandomizeBlockDesc is still there.
00045 static void CheckBlockDesc(const BlockDesc &d) {
00046   for (int i = 0; i != d.len; i++) {
00047     TEST_ASSERT((d.ptr[i] & 0xff) == ((d.fill + i) & 0xff));
00048   }
00049 }
00050 
00051 // Fill the block "*d" with a pattern
00052 // starting with a random byte.
00053 static void RandomizeBlockDesc(BlockDesc *d) {
00054   d->fill = rand() & 0xff;
00055   for (int i = 0; i != d->len; i++) {
00056     d->ptr[i] = (d->fill + i) & 0xff;
00057   }
00058 }
00059 
00060 // Use to indicate to the malloc hooks that
00061 // this calls is from LowLevelAlloc.
00062 static bool using_low_level_alloc = false;
00063 
00064 // n times, toss a coin, and based on the outcome
00065 // either allocate a new block or deallocate an old block.
00066 // New blocks are placed in a std::unordered_map with a random key
00067 // and initialized with RandomizeBlockDesc().
00068 // If keys conflict, the older block is freed.
00069 // Old blocks are always checked with CheckBlockDesc()
00070 // before being freed.  At the end of the run,
00071 // all remaining allocated blocks are freed.
00072 // If use_new_arena is true, use a fresh arena, and then delete it.
00073 // If call_malloc_hook is true and user_arena is true,
00074 // allocations and deallocations are reported via the MallocHook
00075 // interface.
00076 static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
00077   typedef std::unordered_map<int, BlockDesc> AllocMap;
00078   AllocMap allocated;
00079   AllocMap::iterator it;
00080   BlockDesc block_desc;
00081   int rnd;
00082   LowLevelAlloc::Arena *arena = 0;
00083   if (use_new_arena) {
00084     int32_t flags = call_malloc_hook ? LowLevelAlloc::kCallMallocHook : 0;
00085     arena = LowLevelAlloc::NewArena(flags);
00086   }
00087   for (int i = 0; i != n; i++) {
00088     if (i != 0 && i % 10000 == 0) {
00089       printf(".");
00090       fflush(stdout);
00091     }
00092 
00093     switch (rand() & 1) {      // toss a coin
00094     case 0:     // coin came up heads: add a block
00095       using_low_level_alloc = true;
00096       block_desc.len = rand() & 0x3fff;
00097       block_desc.ptr =
00098         reinterpret_cast<char *>(
00099                         arena == 0
00100                         ? LowLevelAlloc::Alloc(block_desc.len)
00101                         : LowLevelAlloc::AllocWithArena(block_desc.len, arena));
00102       using_low_level_alloc = false;
00103       RandomizeBlockDesc(&block_desc);
00104       rnd = rand();
00105       it = allocated.find(rnd);
00106       if (it != allocated.end()) {
00107         CheckBlockDesc(it->second);
00108         using_low_level_alloc = true;
00109         LowLevelAlloc::Free(it->second.ptr);
00110         using_low_level_alloc = false;
00111         it->second = block_desc;
00112       } else {
00113         allocated[rnd] = block_desc;
00114       }
00115       break;
00116     case 1:     // coin came up tails: remove a block
00117       it = allocated.begin();
00118       if (it != allocated.end()) {
00119         CheckBlockDesc(it->second);
00120         using_low_level_alloc = true;
00121         LowLevelAlloc::Free(it->second.ptr);
00122         using_low_level_alloc = false;
00123         allocated.erase(it);
00124       }
00125       break;
00126     }
00127   }
00128   // remove all remaining blocks
00129   while ((it = allocated.begin()) != allocated.end()) {
00130     CheckBlockDesc(it->second);
00131     using_low_level_alloc = true;
00132     LowLevelAlloc::Free(it->second.ptr);
00133     using_low_level_alloc = false;
00134     allocated.erase(it);
00135   }
00136   if (use_new_arena) {
00137     TEST_ASSERT(LowLevelAlloc::DeleteArena(arena));
00138   }
00139 }
00140 
00141 // LowLevelAlloc is designed to be safe to call before main().
00142 static struct BeforeMain {
00143   BeforeMain() {
00144     Test(false, false, 50000);
00145     Test(true, false, 50000);
00146     Test(true, true, 50000);
00147   }
00148 } before_main;
00149 
00150 }  // namespace
00151 }  // namespace base_internal
00152 }  // namespace absl
00153 
00154 int main(int argc, char *argv[]) {
00155   // The actual test runs in the global constructor of `before_main`.
00156   printf("PASS\n");
00157   return 0;
00158 }


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15