]> git.wincent.com - WOTest.git/commitdiff
Import WOMalloc functions from WODebug
authorWincent Colaiuta <win@wincent.com>
Tue, 7 Apr 2009 11:09:25 +0000 (13:09 +0200)
committerWincent Colaiuta <win@wincent.com>
Tue, 7 Apr 2009 11:09:25 +0000 (13:09 +0200)
These functions and macros weren't really used in
WODebug, but they could definitely be of use here
in WOTest.

Signed-off-by: Wincent Colaiuta <win@wincent.com>
WOMalloc.c [new file with mode: 0644]
WOMalloc.h [new file with mode: 0644]

diff --git a/WOMalloc.c b/WOMalloc.c
new file mode 100644 (file)
index 0000000..fb80d7e
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ *  WOMalloc.c
+ *  WODebug
+ *
+ *  Created by Wincent Colaiuta on 07 February 2006.
+ *  Copyright 2006-2007 Wincent Colaiuta.
+ *
+ */
+
+#include "WOMalloc.h"
+
+#ifndef _STRING_H_
+#include <string.h>
+#endif
+
+#ifndef _SYS_ERRNO_H_
+#include <errno.h>
+#endif
+
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#if !defined(TRUE)
+#define TRUE    1
+#endif
+
+#if !defined(FALSE)
+#define FALSE   0
+#endif
+
+_Bool WOMallocShouldFail(void);
+
+_Bool WOMallocShouldFail()
+{
+    // check "always fail" environment variable
+    const char *alwaysFail = (const char *)getenv("WOMallocFailAlways");
+    if ((alwaysFail != NULL) && (strcmp(alwaysFail, "1") == 0))
+        return TRUE;
+
+    // check "fail randomly" environment variable
+    const char *randomly = (const char *)getenv("WOMallocFailRandomly");
+    if (randomly != NULL)
+    {
+        // try to extract double value between 0 and 1 from environment variable
+        double probability = strtod(randomly, (char **)NULL); // ignore errors
+
+        // impose range limits
+        if (probability <= 0) return FALSE;  // don't force failure
+        if (probability >= 1) return TRUE;   // do force failure
+
+        // given probability, decide whether or not to fail
+        // get value between 0 and 0xfffffffe (2 to the power of 31, minus 1)
+        if (random() < (probability * 0xfffffffe))
+            return TRUE;
+    }
+
+    return FALSE; // fallback case: don't force failure
+}
+
+#pragma mark -
+#pragma mark Base wrapper functions
+
+void * WOMalloc(size_t size)
+{
+    if (WOMallocShouldFail())
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return malloc(size);
+}
+
+void * WOCalloc(size_t count, size_t size)
+{
+    if (WOMallocShouldFail())
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return calloc(count, size);
+}
+
+void * WOValloc(size_t size)
+{
+    if (WOMallocShouldFail())
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return valloc(size);
+}
+
+void * WORealloc(void *ptr, size_t size)
+{
+    if (WOMallocShouldFail())
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return realloc(ptr, size);
+}
+
+void * WOReallocf(void *ptr, size_t size)
+{
+    if (WOMallocShouldFail())
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return reallocf(ptr, size);
+}
+
+#pragma mark -
+#pragma mark Wrapper functions with forced failure control
+
+void * WOMallocFail(size_t size, _Bool fail)
+{
+    if (fail)
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return malloc(size);
+}
+
+void * WOCallocFail(size_t count, size_t size, _Bool fail)
+{
+    if (fail)
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return calloc(count, size);
+}
+
+void * WOVallocFail(size_t size, _Bool fail)
+{
+    if (fail)
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return valloc(size);
+}
+
+void * WOReallocFail(void *ptr, size_t size, _Bool fail)
+{
+    if (fail)
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return realloc(ptr, size);
+}
+
+void * WOReallocfFail(void *ptr, size_t size, _Bool fail)
+{
+    if (fail)
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    return reallocf(ptr, size);
+}
+
+#pragma mark -
+#pragma mark Variadic helper functions
+
+void * WOMallocFailv(size_t size, ...)
+{
+    va_list args;
+    va_start(args, size);
+    int   fail            = FALSE;
+    void    *returnValue    = NULL;
+
+    // get optional failure flag, if present
+    if ((fail = va_arg(args, int)))
+        returnValue = WOMallocFail(size, fail); // use forced failure version
+    else
+        returnValue = WOMalloc(size);           // use standard version
+
+    va_end(args);
+    return returnValue;
+}
+
+void * WOCallocFailv(size_t count, size_t size, ...)
+{
+    va_list args;
+    va_start(args, size);
+    int   fail            = FALSE;
+    void    *returnValue    = NULL;
+
+    // get optional failure flag, if present
+    if ((fail = va_arg(args, int)))
+        returnValue = WOCallocFail(count, size, fail);
+    else
+        returnValue = WOCalloc(count, size);
+
+    va_end(args);
+    return returnValue;
+}
+
+void * WOVallocFailv(size_t size, ...)
+{
+    va_list args;
+    va_start(args, size);
+    int   fail            = FALSE;
+    void    *returnValue    = NULL;
+
+    // get optional failure flag, if present
+    if ((fail = va_arg(args, int)))
+        returnValue = WOVallocFail(size, fail);
+    else
+        returnValue = WOValloc(size);
+
+    va_end(args);
+    return returnValue;
+}
+
+void * WOReallocFailv(void *ptr, size_t size, ...)
+{
+    va_list args;
+    va_start(args, size);
+    int   fail            = FALSE;
+    void    *returnValue    = NULL;
+
+    // get optional failure flag, if present
+    if ((fail = va_arg(args, int)))
+        returnValue = WOReallocFail(ptr, size, fail);
+    else
+        returnValue = WORealloc(ptr, size);
+
+    va_end(args);
+    return returnValue;
+}
+
+void * WOReallocfFailv(void *ptr, size_t size, ...)
+{
+    va_list args;
+    va_start(args, size);
+    int   fail            = FALSE;
+    void    *returnValue    = NULL;
+
+    // get optional failure flag, if present
+    if ((fail = va_arg(args, int)))
+        returnValue = WOReallocfFail(ptr, size, fail);
+    else
+        returnValue = WOReallocf(ptr, size);
+
+    va_end(args);
+    return returnValue;
+}
diff --git a/WOMalloc.h b/WOMalloc.h
new file mode 100644 (file)
index 0000000..501e88e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * WOMalloc.h
+ * WODebug
+ *
+ * Copyright 2006-2009 Wincent Colaiuta.
+ *
+ */
+
+#ifndef _STDLIB_H_
+#include <stdlib.h>
+#endif
+
+/*! Wrappers for memory allocation functions which can be used to simulate out-of-memory conditions for testing purposes. There are two ways of simulating failures:
+
+1. set an environment variable to provoke failures (other vars can be used to control when: always, randomly etc)
+2. use macros to pass an extra "forced failure" parameter
+
+Environment variables:
+
+WOMallocFailAlways set to 1 to always fail, 0 to not force failure
+
+WOMallocFailRandomly (set to value between 0 and 1 indicating desired frequency of failures; 0 is equivalent to no forced failures, 1 is equivalent to "fail always")
+
+If set WOMallocFailAlways overrides WOMallocFailRandomly
+
+*/
+
+#pragma mark -
+#pragma mark Variadic macros
+
+/*!
+\name Variadic macros
+
+ These variadic macros wrap the wrapper functions in such a way that the caller can optionally specify an extra "true" or "false" parameter to force an allocation to fail for testing purposes. One way to do this would be to code in C++ or Objective-C++ and overload the functions so as to provide alternative versions with and without the forced failure flags. An alternative approach has been taken here and that is to use variadic macros and some helper functions which do not require function overloading and can therefore be used in normal C code.
+
+\startgroup
+*/
+
+#define WO_MALLOC(size, ...)            WOMallocFailv(size, ## __VAR_ARGS__)
+
+#define WO_CALLOC(count, size, ...)     WOCallocFailv\
+                                        (count, size, ## __VAR_ARGS__)
+
+#define WO_VALLOC(size, ...)            WOVallocFailv(size, ## __VAR_ARGS__)
+
+#define WO_REALLOC(ptr, size, ...)      WOReallocFailv\
+                                        (ptr, size, ## __VAR_ARGS__)
+
+#define WO_REALLOCF(ptr, size, ...)     WOReallocfFailv\
+                                        (ptr, size, ## __VAR_ARGS__)
+
+/*! \endgroup */
+
+#pragma mark -
+#pragma mark Base wrapper functions
+
+void * WOMalloc(size_t size);
+
+void * WOCalloc(size_t count, size_t size);
+
+void * WOValloc(size_t size);
+
+void * WORealloc(void *ptr, size_t size);
+
+void * WOReallocf(void *ptr, size_t size);
+
+#pragma mark -
+#pragma mark Wrapper functions with forced failure control
+
+void * WOMallocFail(size_t size, _Bool fail);
+
+void * WOCallocFail(size_t count, size_t size, _Bool fail);
+
+void * WOVallocFail(size_t size, _Bool fail);
+
+void * WOReallocFail(void *ptr, size_t size, _Bool fail);
+
+void * WOReallocfFail(void *ptr, size_t size, _Bool fail);
+
+#pragma mark -
+#pragma mark Variadic helper function prototypes
+
+void * WOMallocFailv(size_t size, ...);
+
+void * WOCallocFailv(size_t count, size_t size, ...);
+
+void * WOVallocFailv(size_t size, ...);
+
+void * WOReallocFailv(void *ptr, size_t size, ...);
+
+void * WOReallocfFailv(void *ptr, size_t size, ...);