Context-aware pluggable malloc / free scaffolding Description ----- "context-alloc" is a C library intended to simplify writing unit tests for out-of-memory conditions. By introducing indirection, it grants the option to mock alloctation and deallocation in tests to ensure that code behaves as expected in out-of-memory situations. Usage ----- Copy the src/context-alloc.h and src/context-alloc.c directly into your project. Rename them and adjust them to fit in with your project's naming conventions. The "demo" directory contains an example of how to use context-alloc, but in short the idea is that by default the standard functions malloc and free are used, but alternatives may be plugged in, including a pointer to an object for context, thus allowing easier testing of memory exhaustion. In the code, rather than calling malloc and free directly, keep a function pointer to the allocation and freeing functions. Of course you can have these as global variables, or better by adding them to your struct, perhaps a little like this: typedef struct foo { context_malloc_func alloc; context_free_func free; void *mem_context; ... } foo_s; foo_s *foo_new_custom_allocator(context_malloc_func c_alloc, context_free_func c_free, void *mem_context) { if (!c_alloc || !c_free) { c_alloc = context_stdlib_malloc; c_free = context_stdlib_free; mem_context = NULL; } ... } foo_s *foo_new(void) { return foo_new_custom_allocator(NULL, NULL, NULL); } /* return 0 on success or 1 on memory allocation failure */ int foo_bar(foo_s *foo, int bar) { char *buf = foo->alloc(foo->mem_context, BUF_LEN); if (!buf) { return 1; } ... return 0; } The "util" directory in the project includes example allocators which allow easier testing of Out Of Memory conditions. In your tests, you can do something like: int test_foo_bar_oom(void) { foo_s *foo; context_malloc_func ctx_alloc; context_free_func ctx_free; oom_injecting_context_s mctx; int i, err; ctx_alloc = oom_injecting_malloc; ctx_free = oom_injecting_free; oom_injecting_context_init(&mctx); /* return NULL on the 4th call to malloc: */ mctx.attempts_to_fail_bitmask = 0x01 << 3; foo = foo_new_custom_allocator(ctx_malloc, ctx_free, &mctx); for(i = 0; i < 10; ++i) { err = foo_bar(foo, i); if (err) { /* malloc inside foo_bar() returned NULL */ /* maybe add more sanity checks here */ ... } } ... } In the "demo" directory you can see a more complete example as described above. To run the demo, simply type "make" in the root of the project, or to see more verbose output, build with DEBUG=1 like: make clean make DEBUG=1 check To get code coverage reporting, use: make clean make DEBUG=1 coverage License ------- LGPL-3.0-or-later This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.