提交 7943c766 编写于 作者: M Mark VanderVoord

Merge pull request #161 from jsalling/feature/fixture-remove-dependencies

Feature - remove dependencies from Fixture, add internal heap option (Wow! Thanks jsalling!)
......@@ -6,21 +6,19 @@
========================================== */
#include <string.h>
#include <stdio.h>
#include "unity_fixture.h"
#include "unity_internals.h"
UNITY_FIXTURE_T UnityFixture;
//If you decide to use the function pointer approach.
int (*outputChar)(int) = putchar;
//Build with -D UNITY_OUTPUT_CHAR=outputChar and include <stdio.h>
//int (*outputChar)(int) = putchar;
int verbose = 0;
void setUp(void);
void tearDown(void);
#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
void setUp(void) { /*does nothing*/ }
void tearDown(void) { /*does nothing*/ }
#endif
static void announceTestRun(unsigned int runNumber)
{
......@@ -50,7 +48,7 @@ int UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
return UnityFailureCount();
}
static int selected(const char * filter, const char * name)
static int selected(const char* filter, const char* name)
{
if (filter == 0)
return 1;
......@@ -67,18 +65,13 @@ static int groupSelected(const char* group)
return selected(UnityFixture.GroupFilter, group);
}
static void runTestCase(void)
{
}
void UnityTestRunner(unityfunction* setup,
unityfunction* testBody,
unityfunction* teardown,
const char * printableName,
const char * group,
const char * name,
const char * file, int line)
unityfunction* testBody,
unityfunction* teardown,
const char* printableName,
const char* group,
const char* name,
const char* file, int line)
{
if (testSelected(name) && groupSelected(group))
{
......@@ -95,7 +88,6 @@ void UnityTestRunner(unityfunction* setup,
UnityMalloc_StartTest();
UnityPointer_Init();
runTestCase();
if (TEST_PROTECT())
{
setup();
......@@ -115,7 +107,7 @@ void UnityTestRunner(unityfunction* setup,
}
}
void UnityIgnoreTest(const char * printableName, const char * group, const char * name)
void UnityIgnoreTest(const char* printableName, const char* group, const char* name)
{
if (testSelected(name) && groupSelected(group))
{
......@@ -157,24 +149,19 @@ void UnityMalloc_MakeMallocFailAfterCount(int countdown)
malloc_fail_countdown = countdown;
}
#ifdef malloc
// These definitions are always included from unity_fixture_malloc_overrides.h
// We undef to use them or avoid conflict with <stdlib.h> per the C standard
#undef malloc
#endif
#ifdef free
#undef free
#endif
#ifdef calloc
#undef calloc
#endif
#ifdef realloc
#undef realloc
#endif
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
static unsigned int heap_index;
#else
#include <stdlib.h>
#include <string.h>
#endif
typedef struct GuardBytes
{
......@@ -185,21 +172,35 @@ typedef struct GuardBytes
static const char end[] = "END";
void * unity_malloc(size_t size)
void* unity_malloc(size_t size)
{
char* mem;
Guard* guard;
size_t total_size = size + sizeof(Guard) + sizeof(end);
if (malloc_fail_countdown != MALLOC_DONT_FAIL)
{
if (malloc_fail_countdown == 0)
return 0;
return NULL;
malloc_fail_countdown--;
}
if (size == 0) return NULL;
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES)
{
guard = NULL;
}
else
{
guard = (Guard*) &unity_heap[heap_index];
heap_index += total_size;
}
#else
guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size);
#endif
if (guard == NULL) return NULL;
malloc_count++;
guard = (Guard*)UNITY_FIXTURE_MALLOC(size + sizeof(Guard) + sizeof(end));
guard->size = size;
mem = (char*)&(guard[1]);
memcpy(&mem[size], end, sizeof(end));
......@@ -207,7 +208,7 @@ void * unity_malloc(size_t size)
return (void*)mem;
}
static int isOverrun(void * mem)
static int isOverrun(void* mem)
{
Guard* guard = (Guard*)mem;
char* memAsChar = (char*)mem;
......@@ -216,16 +217,23 @@ static int isOverrun(void * mem)
return strcmp(&memAsChar[guard->size], end) != 0;
}
static void release_memory(void * mem)
static void release_memory(void* mem)
{
Guard* guard = (Guard*)mem;
guard--;
malloc_count--;
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
if (mem == unity_heap + heap_index - guard->size - sizeof(end))
{
heap_index -= (guard->size + sizeof(Guard) + sizeof(end));
}
#else
UNITY_FIXTURE_FREE(guard);
#endif
}
void unity_free(void * mem)
void unity_free(void* mem)
{
int overrun;
......@@ -234,7 +242,7 @@ void unity_free(void * mem)
return;
}
overrun = isOverrun(mem);//strcmp(&memAsChar[guard->size], end) != 0;
overrun = isOverrun(mem);
release_memory(mem);
if (overrun)
{
......@@ -245,18 +253,17 @@ void unity_free(void * mem)
void* unity_calloc(size_t num, size_t size)
{
void* mem = unity_malloc(num * size);
memset(mem, 0, num*size);
if (mem == NULL) return NULL;
memset(mem, 0, num * size);
return mem;
}
void* unity_realloc(void * oldMem, size_t size)
void* unity_realloc(void* oldMem, size_t size)
{
Guard* guard = (Guard*)oldMem;
// char* memAsChar = (char*)oldMem;
void* newMem;
if (oldMem == 0)
return unity_malloc(size);
if (oldMem == NULL) return unity_malloc(size);
guard--;
if (isOverrun(oldMem))
......@@ -268,15 +275,23 @@ void* unity_realloc(void * oldMem, size_t size)
if (size == 0)
{
release_memory(oldMem);
return 0;
return NULL;
}
if (guard->size >= size)
return oldMem;
if (guard->size >= size) return oldMem;
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC // Optimization if memory is expandable
if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) &&
heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES)
{
release_memory(oldMem); // Not thread-safe, like unity_heap generally
return unity_malloc(size); // No memcpy since data is in place
}
#endif
newMem = unity_malloc(size);
if (newMem == NULL) return NULL; // Do not release old memory
memcpy(newMem, oldMem, guard->size);
unity_free(oldMem);
release_memory(oldMem);
return newMem;
}
......@@ -285,9 +300,9 @@ void* unity_realloc(void * oldMem, size_t size)
//Automatic pointer restoration functions
typedef struct _PointerPair
{
struct _PointerPair * next;
void ** pointer;
void * old_value;
struct _PointerPair* next;
void** pointer;
void* old_value;
} PointerPair;
enum {MAX_POINTERS=50};
......@@ -299,7 +314,7 @@ void UnityPointer_Init(void)
pointer_index = 0;
}
void UnityPointer_Set(void ** pointer, void * newValue)
void UnityPointer_Set(void** pointer, void* newValue)
{
if (pointer_index >= MAX_POINTERS)
{
......@@ -320,8 +335,7 @@ void UnityPointer_UndoAllSets(void)
{
pointer_index--;
*(pointer_store[pointer_index].pointer) =
pointer_store[pointer_index].old_value;
pointer_store[pointer_index].old_value;
}
}
......@@ -382,7 +396,13 @@ int UnityGetCommandLineOptions(int argc, const char* argv[])
{
if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
{
UnityFixture.RepeatCount = atoi(argv[i]);
unsigned int digit = 0;
UnityFixture.RepeatCount = 0;
while (argv[i][digit] >= '0' && argv[i][digit] <= '9')
{
UnityFixture.RepeatCount *= 10;
UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0';
}
i++;
}
}
......
......@@ -17,15 +17,15 @@ typedef struct _UNITY_FIXTURE_T
} UNITY_FIXTURE_T;
typedef void unityfunction(void);
void UnityTestRunner(unityfunction * setup,
unityfunction * body,
unityfunction * teardown,
const char * printableName,
const char * group,
const char * name,
const char * file, int line);
void UnityTestRunner(unityfunction* setup,
unityfunction* body,
unityfunction* teardown,
const char* printableName,
const char* group,
const char* name,
const char* file, int line);
void UnityIgnoreTest(const char * printableName, const char * group, const char * name);
void UnityIgnoreTest(const char* printableName, const char* group, const char* name);
void UnityMalloc_StartTest(void);
void UnityMalloc_EndTest(void);
UNITY_COUNTER_TYPE UnityFailureCount(void);
......@@ -34,13 +34,8 @@ UNITY_COUNTER_TYPE UnityTestsCount(void);
int UnityGetCommandLineOptions(int argc, const char* argv[]);
void UnityConcludeFixtureTest(void);
void UnityPointer_Set(void ** ptr, void * newValue);
void UnityPointer_Set(void** ptr, void* newValue);
void UnityPointer_UndoAllSets(void);
void UnityPointer_Init(void);
void UnityAssertEqualPointer(const void * expected,
const void * actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber);
#endif /* UNITY_FIXTURE_INTERNALS_H_ */
......@@ -10,26 +10,27 @@
#include <stddef.h>
// This function is used by the Unity Fixture to allocate memory on
// the heap and can be overridden with platform-specific heap
// implementations. For example, when using FreeRTOS
// UNITY_FIXTURE_MALLOC becomes pvPortMalloc().
#ifndef UNITY_FIXTURE_MALLOC
#define UNITY_FIXTURE_MALLOC( SIZE ) malloc( ( SIZE ) )
#else
extern void * UNITY_FIXTURE_MALLOC(size_t size);
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
// Define this macro to remove the use of stdlib.h, malloc, and free.
// Many embedded systems do not have a heap or malloc/free by default.
// This internal unity_malloc() provides allocated memory deterministically from
// the end of an array only, unity_free() only releases from end-of-array,
// blocks are not coalesced, and memory not freed in LIFO order is stranded.
#ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES
#define UNITY_INTERNAL_HEAP_SIZE_BYTES 256
#endif
#endif
// This function is used by the Unity Fixture to release memory in the
// heap and can be overridden with platform-specific heap
// implementations. For example, when using FreeRTOS
// UNITY_FIXTURE_FREE becomes vPortFree().
#ifndef UNITY_FIXTURE_FREE
#define UNITY_FIXTURE_FREE( PTR ) free( ( PTR ) )
// These functions are used by the Unity Fixture to allocate and release memory
// on the heap and can be overridden with platform-specific implementations.
// For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc()
// and UNITY_FIXTURE_FREE becomes vPortFree().
#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE)
#define UNITY_FIXTURE_MALLOC(size) malloc(size)
#define UNITY_FIXTURE_FREE(ptr) free(ptr)
#else
extern void UNITY_FIXTURE_FREE(void *ptr);
extern void* UNITY_FIXTURE_MALLOC(size_t size);
extern void UNITY_FIXTURE_FREE(void* ptr);
#endif
#define malloc unity_malloc
......
......@@ -14,6 +14,22 @@ SRC = ../src/unity_fixture.c \
INC_DIR = -I../src -I../../../src/
TARGET = fixture_tests.exe
all:
all: default noStdlibMalloc 32bits
default:
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET)
@ echo "default build"
./$(TARGET)
32bits:
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -m32
@ echo "32bits build"
./$(TARGET)
noStdlibMalloc:
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC
@ echo "build with noStdlibMalloc"
./$(TARGET)
clangEverything:
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -m64 -Weverything # || true #prevents make from failing
......@@ -11,7 +11,8 @@ static void runAllTests(void)
{
RUN_TEST_GROUP(UnityFixture);
RUN_TEST_GROUP(UnityCommandOptions);
RUN_TEST_GROUP(LeakDetection)
RUN_TEST_GROUP(LeakDetection);
RUN_TEST_GROUP(InternalMalloc);
}
int main(int argc, const char* argv[])
......
......@@ -79,9 +79,10 @@ TEST(UnityFixture, ReallocLargerNeeded)
{
void* m1 = malloc(10);
void* m2;
CHECK(m1);
strcpy((char*)m1, "123456789");
m2 = realloc(m1, 15);
CHECK(m1 != m2);
// CHECK(m1 != m2); //Depends on implementation
STRCMP_EQUAL("123456789", m2);
free(m2);
}
......@@ -104,6 +105,7 @@ TEST(UnityFixture, CallocFillsWithZero)
{
void* m = calloc(3, sizeof(char));
char* s = (char*)m;
CHECK(m);
TEST_ASSERT_BYTES_EQUAL(0, s[0]);
TEST_ASSERT_BYTES_EQUAL(0, s[1]);
TEST_ASSERT_BYTES_EQUAL(0, s[2]);
......@@ -134,7 +136,7 @@ TEST(UnityFixture, PointerSet)
TEST(UnityFixture, FreeNULLSafety)
{
unity_free(NULL);
free(NULL);
}
//------------------------------------------------------------
......@@ -288,7 +290,11 @@ TEST_GROUP(LeakDetection);
TEST_SETUP(LeakDetection)
{
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
UnityOutputCharSpy_Create(200);
#else
UnityOutputCharSpy_Create(1000);
#endif
}
TEST_TEAR_DOWN(LeakDetection)
......@@ -323,6 +329,7 @@ TEST(LeakDetection, DetectsLeak)
TEST_IGNORE_MESSAGE("Build with '-D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar' to enable tests");
#else
void* m = malloc(10);
TEST_ASSERT_NOT_NULL(m);
UnityOutputCharSpy_Enable(1);
EXPECT_ABORT_BEGIN
UnityMalloc_EndTest();
......@@ -341,6 +348,7 @@ TEST(LeakDetection, BufferOverrunFoundDuringFree)
TEST_IGNORE();
#else
void* m = malloc(10);
TEST_ASSERT_NOT_NULL(m);
char* s = (char*)m;
s[10] = (char)0xFF;
UnityOutputCharSpy_Enable(1);
......@@ -360,6 +368,7 @@ TEST(LeakDetection, BufferOverrunFoundDuringRealloc)
TEST_IGNORE();
#else
void* m = malloc(10);
TEST_ASSERT_NOT_NULL(m);
char* s = (char*)m;
s[10] = (char)0xFF;
UnityOutputCharSpy_Enable(1);
......@@ -371,3 +380,57 @@ TEST(LeakDetection, BufferOverrunFoundDuringRealloc)
CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
#endif
}
TEST_GROUP(InternalMalloc);
TEST_SETUP(InternalMalloc) { }
TEST_TEAR_DOWN(InternalMalloc) { }
TEST(InternalMalloc, MallocPastBufferFails)
{
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
TEST_ASSERT_NOT_NULL(m);
void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
TEST_ASSERT_NULL(n);
free(m);
#endif
}
TEST(InternalMalloc, CallocPastBufferFails)
{
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
TEST_ASSERT_NOT_NULL(m);
void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
TEST_ASSERT_NULL(n);
free(m);
#endif
}
TEST(InternalMalloc, MallocThenReallocGrowsMemoryInPlace)
{
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
TEST_ASSERT_NOT_NULL(m);
void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9);
TEST_ASSERT_EQUAL(m, n);
free(n);
#endif
}
TEST(InternalMalloc, ReallocFailDoesNotFreeMem)
{
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
TEST_ASSERT_NOT_NULL(m);
void* n1 = malloc(10);
void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
TEST_ASSERT_NULL(out_of_mem);
void* n2 = malloc(10);
TEST_ASSERT_NOT_EQUAL(n2, n1);
free(n2);
free(n1);
free(m);
#endif
}
......@@ -41,3 +41,11 @@ TEST_GROUP_RUNNER(LeakDetection)
RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringFree);
RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringRealloc);
}
TEST_GROUP_RUNNER(InternalMalloc)
{
RUN_TEST_CASE(InternalMalloc, MallocPastBufferFails);
RUN_TEST_CASE(InternalMalloc, CallocPastBufferFails);
RUN_TEST_CASE(InternalMalloc, MallocThenReallocGrowsMemoryInPlace);
RUN_TEST_CASE(InternalMalloc, ReallocFailDoesNotFreeMem);
}
......@@ -22,14 +22,15 @@ void UnityOutputCharSpy_Create(int s)
size = s;
count = 0;
spy_enable = 0;
buffer = UNITY_FIXTURE_MALLOC(size);
buffer = malloc(size);
TEST_ASSERT_NOT_NULL_MESSAGE(buffer, "Internal malloc failed in Spy Create():" __FILE__);
memset(buffer, 0, size);
}
void UnityOutputCharSpy_Destroy(void)
{
size = 0;
UNITY_FIXTURE_FREE(buffer);
free(buffer);
}
int UnityOutputCharSpy_OutputChar(int c)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册