This source file includes following definitions.
- CheckBlockDesc
- RandomizeBlockDesc
- Test
- AllocHook
- FreeHook
- main
#include <stdio.h>
#include <map>
#include "base/low_level_alloc.h"
#include "base/logging.h"
#include <gperftools/malloc_hook.h>
using std::map;
struct BlockDesc {
char *ptr;
int len;
int fill;
};
static void CheckBlockDesc(const BlockDesc &d) {
for (int i = 0; i != d.len; i++) {
CHECK((d.ptr[i] & 0xff) == ((d.fill + i) & 0xff));
}
}
static void RandomizeBlockDesc(BlockDesc *d) {
d->fill = rand() & 0xff;
for (int i = 0; i != d->len; i++) {
d->ptr[i] = (d->fill + i) & 0xff;
}
}
static bool using_low_level_alloc = false;
static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
typedef map<int, BlockDesc> AllocMap;
AllocMap allocated;
AllocMap::iterator it;
BlockDesc block_desc;
int rnd;
LowLevelAlloc::Arena *arena = 0;
if (use_new_arena) {
int32 flags = call_malloc_hook? LowLevelAlloc::kCallMallocHook : 0;
arena = LowLevelAlloc::NewArena(flags, LowLevelAlloc::DefaultArena());
}
for (int i = 0; i != n; i++) {
if (i != 0 && i % 10000 == 0) {
printf(".");
fflush(stdout);
}
switch(rand() & 1) {
case 0:
using_low_level_alloc = true;
block_desc.len = rand() & 0x3fff;
block_desc.ptr =
reinterpret_cast<char *>(
arena == 0
? LowLevelAlloc::Alloc(block_desc.len)
: LowLevelAlloc::AllocWithArena(block_desc.len, arena));
using_low_level_alloc = false;
RandomizeBlockDesc(&block_desc);
rnd = rand();
it = allocated.find(rnd);
if (it != allocated.end()) {
CheckBlockDesc(it->second);
using_low_level_alloc = true;
LowLevelAlloc::Free(it->second.ptr);
using_low_level_alloc = false;
it->second = block_desc;
} else {
allocated[rnd] = block_desc;
}
break;
case 1:
it = allocated.begin();
if (it != allocated.end()) {
CheckBlockDesc(it->second);
using_low_level_alloc = true;
LowLevelAlloc::Free(it->second.ptr);
using_low_level_alloc = false;
allocated.erase(it);
}
break;
}
}
while ((it = allocated.begin()) != allocated.end()) {
CheckBlockDesc(it->second);
using_low_level_alloc = true;
LowLevelAlloc::Free(it->second.ptr);
using_low_level_alloc = false;
allocated.erase(it);
}
if (use_new_arena) {
CHECK(LowLevelAlloc::DeleteArena(arena));
}
}
static int32 allocates;
static int32 frees;
static void AllocHook(const void *p, size_t size) {
if (using_low_level_alloc) {
allocates++;
}
}
static void FreeHook(const void *p) {
if (using_low_level_alloc) {
frees++;
}
}
int main(int argc, char *argv[]) {
if (argc != 1) {
fprintf(stderr, "USAGE: %s\n", argv[0]);
return 1;
}
CHECK(MallocHook::AddNewHook(&AllocHook));
CHECK(MallocHook::AddDeleteHook(&FreeHook));
CHECK_EQ(allocates, 0);
CHECK_EQ(frees, 0);
Test(false, false, 50000);
CHECK_NE(allocates, 0);
CHECK_NE(frees, 0);
for (int i = 0; i != 16; i++) {
bool call_hooks = ((i & 1) == 1);
allocates = 0;
frees = 0;
Test(true, call_hooks, 15000);
if (call_hooks) {
CHECK_GT(allocates, 5000);
CHECK_GT(frees, 5000);
} else {
CHECK_EQ(allocates, 0);
CHECK_EQ(frees, 0);
}
}
printf("\nPASS\n");
CHECK(MallocHook::RemoveNewHook(&AllocHook));
CHECK(MallocHook::RemoveDeleteHook(&FreeHook));
return 0;
}