test_introspection.c [plain text]
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc/malloc.h>
#include <auto_zone.h>
struct BlockRecorderContext {
size_t blocks_in_use;
size_t size_in_use;
malloc_zone_t *zone;
};
typedef struct BlockRecorderContext BlockRecorderContext;
static void blockRecorder(task_t task, void *context, unsigned type, vm_range_t *ranges, unsigned count) {
BlockRecorderContext *blockContext = context;
while (count--) {
blockContext->blocks_in_use++;
if (ranges->address != (vm_address_t)blockContext->zone) blockContext->size_in_use += ranges->size;
++ranges;
}
}
void test_introspection(malloc_zone_t *zone, boolean_t exact) {
static void* pointers[1000];
BlockRecorderContext context = { 0, 0, zone };
malloc_statistics_t stats;
size_t i;
for (i = 0; i < 1000; ++i) {
size_t random_size = (random() & 0x1FFFF);
pointers[i] = malloc_zone_malloc(zone, random_size);
}
for (i = 0; i < 1000; ++i) {
if (random() & 0x1) {
malloc_zone_free(zone, pointers[i]);
pointers[i] = NULL;
}
}
zone->introspect->enumerator(mach_task_self(), &context, MALLOC_PTR_IN_USE_RANGE_TYPE, (vm_address_t)zone, NULL, blockRecorder);
malloc_zone_statistics(zone, &stats);
if (exact) {
assert(stats.blocks_in_use == context.blocks_in_use);
assert(stats.size_in_use == context.size_in_use);
} else {
assert(stats.blocks_in_use >= context.blocks_in_use);
assert(stats.size_in_use >= context.size_in_use);
}
}
int main() {
test_introspection(auto_zone_create("auto zone"), true);
test_introspection(malloc_default_zone(), false);
test_introspection(malloc_create_zone(8192, 0), false);
return 0;
}