1/* Copyright (c) 2009, 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: Craig Silverstein 32 * 33 * This tests the c shims: malloc_extension_c.h and malloc_hook_c.h. 34 * Mostly, we'll just care that these shims compile under gcc 35 * (*not* g++!) 36 * 37 * NOTE: this is C code, not C++ code! 38 */ 39 40#include <stdio.h> 41#include <stdlib.h> 42#include <stddef.h> /* for size_t */ 43#include <gperftools/malloc_extension_c.h> 44#include <gperftools/malloc_hook_c.h> 45 46#define FAIL(msg) do { \ 47 fprintf(stderr, "FATAL ERROR: %s\n", msg); \ 48 exit(1); \ 49} while (0) 50 51static int g_new_hook_calls = 0; 52static int g_delete_hook_calls = 0; 53 54void TestNewHook(const void* ptr, size_t size) { 55 g_new_hook_calls++; 56} 57 58void TestDeleteHook(const void* ptr) { 59 g_delete_hook_calls++; 60} 61 62void TestMallocHook(void) { 63 /* TODO(csilvers): figure out why we get: 64 * E0100 00:00:00.000000 7383 malloc_hook.cc:244] RAW: google_malloc section is missing, thus InHookCaller is broken! 65 */ 66#if 0 67 void* result[5]; 68 69 if (MallocHook_GetCallerStackTrace(result, sizeof(result)/sizeof(*result), 70 0) < 2) { /* should have this and main */ 71 FAIL("GetCallerStackTrace failed"); 72 } 73#endif 74 75 if (!MallocHook_AddNewHook(&TestNewHook)) { 76 FAIL("Failed to add new hook"); 77 } 78 if (!MallocHook_AddDeleteHook(&TestDeleteHook)) { 79 FAIL("Failed to add delete hook"); 80 } 81 free(malloc(10)); 82 free(malloc(20)); 83 if (g_new_hook_calls != 2) { 84 FAIL("Wrong number of calls to the new hook"); 85 } 86 if (g_delete_hook_calls != 2) { 87 FAIL("Wrong number of calls to the delete hook"); 88 } 89 if (!MallocHook_RemoveNewHook(&TestNewHook)) { 90 FAIL("Failed to remove new hook"); 91 } 92 if (!MallocHook_RemoveDeleteHook(&TestDeleteHook)) { 93 FAIL("Failed to remove delete hook"); 94 } 95} 96 97void TestMallocExtension(void) { 98 int blocks; 99 size_t total; 100 int hist[64]; 101 char buffer[200]; 102 char* x = (char*)malloc(10); 103 104 MallocExtension_VerifyAllMemory(); 105 MallocExtension_VerifyMallocMemory(x); 106 MallocExtension_MallocMemoryStats(&blocks, &total, hist); 107 MallocExtension_GetStats(buffer, sizeof(buffer)); 108 if (!MallocExtension_GetNumericProperty("generic.current_allocated_bytes", 109 &total)) { 110 FAIL("GetNumericProperty failed for generic.current_allocated_bytes"); 111 } 112 if (total < 10) { 113 FAIL("GetNumericProperty had bad return for generic.current_allocated_bytes"); 114 } 115 if (!MallocExtension_GetNumericProperty("generic.current_allocated_bytes", 116 &total)) { 117 FAIL("GetNumericProperty failed for generic.current_allocated_bytes"); 118 } 119 MallocExtension_MarkThreadIdle(); 120 MallocExtension_MarkThreadBusy(); 121 MallocExtension_ReleaseToSystem(1); 122 MallocExtension_ReleaseFreeMemory(); 123 if (MallocExtension_GetEstimatedAllocatedSize(10) < 10) { 124 FAIL("GetEstimatedAllocatedSize returned a bad value (too small)"); 125 } 126 if (MallocExtension_GetAllocatedSize(x) < 10) { 127 FAIL("GetEstimatedAllocatedSize returned a bad value (too small)"); 128 } 129 if (MallocExtension_GetOwnership(x) != MallocExtension_kOwned) { 130 FAIL("DidAllocatePtr returned a bad value (kNotOwned)"); 131 } 132 /* TODO(csilvers): this relies on undocumented behavior that 133 GetOwnership works on stack-allocated variables. Use a better test. */ 134 if (MallocExtension_GetOwnership(hist) != MallocExtension_kNotOwned) { 135 FAIL("DidAllocatePtr returned a bad value (kOwned)"); 136 } 137 138 free(x); 139} 140 141int main(int argc, char** argv) { 142 TestMallocHook(); 143 TestMallocExtension(); 144 145 printf("PASS\n"); 146 return 0; 147} 148