mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2026-01-23 08:25:58 +01:00
Split memory from fixtures and make it's own addon
This commit is contained in:
@@ -24,6 +24,9 @@ script:
|
|||||||
- cd ../extras/fixture/test && rake ci
|
- cd ../extras/fixture/test && rake ci
|
||||||
- make -s default noStdlibMalloc
|
- make -s default noStdlibMalloc
|
||||||
- make -s C89
|
- make -s C89
|
||||||
|
- cd ../extras/memory/test && rake ci
|
||||||
|
- make -s default noStdlibMalloc
|
||||||
|
- make -s C89
|
||||||
- cd ../../../examples/example_1 && make -s ci
|
- cd ../../../examples/example_1 && make -s ci
|
||||||
- cd ../example_2 && make -s ci
|
- cd ../example_2 && make -s ci
|
||||||
- cd ../example_3 && rake
|
- cd ../example_3 && rake
|
||||||
|
|||||||
@@ -55,12 +55,7 @@ def build_compiler_fields
|
|||||||
defines = if $cfg['compiler']['defines']['items'].nil?
|
defines = if $cfg['compiler']['defines']['items'].nil?
|
||||||
''
|
''
|
||||||
else
|
else
|
||||||
decl = if $is_windows
|
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'])
|
||||||
'UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar(int)'
|
|
||||||
else
|
|
||||||
'UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)'
|
|
||||||
end
|
|
||||||
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'] + [decl])
|
|
||||||
end
|
end
|
||||||
options = squash('', $cfg['compiler']['options'])
|
options = squash('', $cfg['compiler']['options'])
|
||||||
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
|
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
|
||||||
|
|||||||
17
extras/fixture/readme.md
Normal file
17
extras/fixture/readme.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Unity Fixtures
|
||||||
|
|
||||||
|
This Framework is an optional add-on to Unity. By including unity_framework.h in place of unity.h,
|
||||||
|
you may now work with Unity in a manner similar to CppUTest. This framework adds the concepts of
|
||||||
|
test groups and gives finer control of your tests over the command line.
|
||||||
|
|
||||||
|
This framework is primarily supplied for those working through James Grenning's book on Embedded
|
||||||
|
Test Driven Development, or those coming to Unity from CppUTest. We should note that using this
|
||||||
|
framework glosses over some of the features of Unity, and makes it more difficult
|
||||||
|
to integrate with other testing tools like Ceedling and CMock.
|
||||||
|
|
||||||
|
# Dependency Notification
|
||||||
|
|
||||||
|
Fixtures, by default, uses the Memory addon as well. This is to make it simple for those trying to
|
||||||
|
follow along with James' book. Using them together is completely optional. You may choose to use
|
||||||
|
Fixtures without Memory handling by defining `UNITY_FIXTURE_NO_EXTRAS`. It will then stop automatically
|
||||||
|
pulling in extras and leave you to do it as desired.
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
|
||||||
|
|
||||||
Unity Project - A Test Framework for C
|
|
||||||
Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
|
||||||
[Released under MIT License. Please refer to license.txt for details]
|
|
||||||
|
|
||||||
This Framework is an optional add-on to Unity. By including unity_framework.h in place of unity.h,
|
|
||||||
you may now work with Unity in a manner similar to CppUTest. This framework adds the concepts of
|
|
||||||
test groups and gives finer control of your tests over the command line.
|
|
||||||
@@ -94,7 +94,6 @@ void UnityTestRunner(unityfunction* setup,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Unity.NumberOfTests++;
|
Unity.NumberOfTests++;
|
||||||
UnityMalloc_StartTest();
|
|
||||||
UnityPointer_Init();
|
UnityPointer_Init();
|
||||||
|
|
||||||
UNITY_EXEC_TIME_START();
|
UNITY_EXEC_TIME_START();
|
||||||
@@ -111,8 +110,6 @@ void UnityTestRunner(unityfunction* setup,
|
|||||||
if (TEST_PROTECT())
|
if (TEST_PROTECT())
|
||||||
{
|
{
|
||||||
UnityPointer_UndoAllSets();
|
UnityPointer_UndoAllSets();
|
||||||
if (!Unity.CurrentTestFailed)
|
|
||||||
UnityMalloc_EndTest();
|
|
||||||
}
|
}
|
||||||
UnityConcludeFixtureTest();
|
UnityConcludeFixtureTest();
|
||||||
}
|
}
|
||||||
@@ -140,204 +137,6 @@ void UnityIgnoreTest(const char* printableName, const char* group, const char* n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------- */
|
|
||||||
/* Malloc and free stuff */
|
|
||||||
#define MALLOC_DONT_FAIL -1
|
|
||||||
static int malloc_count;
|
|
||||||
static int malloc_fail_countdown = MALLOC_DONT_FAIL;
|
|
||||||
|
|
||||||
void UnityMalloc_StartTest(void)
|
|
||||||
{
|
|
||||||
malloc_count = 0;
|
|
||||||
malloc_fail_countdown = MALLOC_DONT_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnityMalloc_EndTest(void)
|
|
||||||
{
|
|
||||||
malloc_fail_countdown = MALLOC_DONT_FAIL;
|
|
||||||
if (malloc_count != 0)
|
|
||||||
{
|
|
||||||
UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnityMalloc_MakeMallocFailAfterCount(int countdown)
|
|
||||||
{
|
|
||||||
malloc_fail_countdown = countdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
#undef free
|
|
||||||
#undef calloc
|
|
||||||
#undef realloc
|
|
||||||
|
|
||||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
|
||||||
static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
|
|
||||||
static size_t heap_index;
|
|
||||||
#else
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct GuardBytes
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
size_t guard_space;
|
|
||||||
} Guard;
|
|
||||||
|
|
||||||
|
|
||||||
#define UNITY_MALLOC_ALIGNMENT (UNITY_POINTER_WIDTH / 8)
|
|
||||||
static const char end[] = "END";
|
|
||||||
|
|
||||||
|
|
||||||
static size_t unity_size_round_up(size_t size)
|
|
||||||
{
|
|
||||||
size_t rounded_size;
|
|
||||||
|
|
||||||
rounded_size = ((size + UNITY_MALLOC_ALIGNMENT - 1) / UNITY_MALLOC_ALIGNMENT) * UNITY_MALLOC_ALIGNMENT;
|
|
||||||
|
|
||||||
return rounded_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* unity_malloc(size_t size)
|
|
||||||
{
|
|
||||||
char* mem;
|
|
||||||
Guard* guard;
|
|
||||||
size_t total_size;
|
|
||||||
|
|
||||||
total_size = sizeof(Guard) + unity_size_round_up(size + sizeof(end));
|
|
||||||
|
|
||||||
if (malloc_fail_countdown != MALLOC_DONT_FAIL)
|
|
||||||
{
|
|
||||||
if (malloc_fail_countdown == 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->size = size;
|
|
||||||
guard->guard_space = 0;
|
|
||||||
mem = (char*)&(guard[1]);
|
|
||||||
memcpy(&mem[size], end, sizeof(end));
|
|
||||||
|
|
||||||
return (void*)mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int isOverrun(void* mem)
|
|
||||||
{
|
|
||||||
Guard* guard = (Guard*)mem;
|
|
||||||
char* memAsChar = (char*)mem;
|
|
||||||
guard--;
|
|
||||||
|
|
||||||
return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void release_memory(void* mem)
|
|
||||||
{
|
|
||||||
Guard* guard = (Guard*)mem;
|
|
||||||
guard--;
|
|
||||||
|
|
||||||
malloc_count--;
|
|
||||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
|
||||||
{
|
|
||||||
size_t block_size;
|
|
||||||
|
|
||||||
block_size = unity_size_round_up(guard->size + sizeof(end));
|
|
||||||
|
|
||||||
if (mem == unity_heap + heap_index - block_size)
|
|
||||||
{
|
|
||||||
heap_index -= (sizeof(Guard) + block_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
UNITY_FIXTURE_FREE(guard);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void unity_free(void* mem)
|
|
||||||
{
|
|
||||||
int overrun;
|
|
||||||
|
|
||||||
if (mem == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
overrun = isOverrun(mem);
|
|
||||||
release_memory(mem);
|
|
||||||
if (overrun)
|
|
||||||
{
|
|
||||||
UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* unity_calloc(size_t num, size_t size)
|
|
||||||
{
|
|
||||||
void* mem = unity_malloc(num * size);
|
|
||||||
if (mem == NULL) return NULL;
|
|
||||||
memset(mem, 0, num * size);
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* unity_realloc(void* oldMem, size_t size)
|
|
||||||
{
|
|
||||||
Guard* guard = (Guard*)oldMem;
|
|
||||||
void* newMem;
|
|
||||||
|
|
||||||
if (oldMem == NULL) return unity_malloc(size);
|
|
||||||
|
|
||||||
guard--;
|
|
||||||
if (isOverrun(oldMem))
|
|
||||||
{
|
|
||||||
release_memory(oldMem);
|
|
||||||
UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
release_memory(oldMem);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guard->size >= size) return oldMem;
|
|
||||||
|
|
||||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */
|
|
||||||
{
|
|
||||||
size_t old_total_size = unity_size_round_up(guard->size + sizeof(end));
|
|
||||||
|
|
||||||
if ((oldMem == unity_heap + heap_index - old_total_size) &&
|
|
||||||
((heap_index - old_total_size + unity_size_round_up(size + sizeof(end))) <= 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);
|
|
||||||
release_memory(oldMem);
|
|
||||||
return newMem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------- */
|
/*-------------------------------------------------------- */
|
||||||
/*Automatic pointer restoration functions */
|
/*Automatic pointer restoration functions */
|
||||||
struct PointerPair
|
struct PointerPair
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "unity_internals.h"
|
#include "unity_internals.h"
|
||||||
#include "unity_fixture_malloc_overrides.h"
|
|
||||||
#include "unity_fixture_internals.h"
|
#include "unity_fixture_internals.h"
|
||||||
|
|
||||||
int UnityMain(int argc, const char* argv[], void (*runAllTests)(void));
|
int UnityMain(int argc, const char* argv[], void (*runAllTests)(void));
|
||||||
@@ -77,7 +76,4 @@ int UnityMain(int argc, const char* argv[], void (*runAllTests)(void));
|
|||||||
#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual))
|
#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */
|
|
||||||
void UnityMalloc_MakeMallocFailAfterCount(int countdown);
|
|
||||||
|
|
||||||
#endif /* UNITY_FIXTURE_H_ */
|
#endif /* UNITY_FIXTURE_H_ */
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ void UnityTestRunner(unityfunction* setup,
|
|||||||
const char* file, unsigned int line);
|
const char* file, unsigned 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);
|
|
||||||
int UnityGetCommandLineOptions(int argc, const char* argv[]);
|
int UnityGetCommandLineOptions(int argc, const char* argv[]);
|
||||||
void UnityConcludeFixtureTest(void);
|
void UnityConcludeFixtureTest(void);
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,10 @@ endif
|
|||||||
#DEBUG = -O0 -g
|
#DEBUG = -O0 -g
|
||||||
CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror
|
CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror
|
||||||
CFLAGS += $(DEBUG)
|
CFLAGS += $(DEBUG)
|
||||||
DEFINES = -D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar
|
|
||||||
ifeq ($(OS),Windows_NT)
|
|
||||||
DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar(int)
|
|
||||||
else
|
|
||||||
DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)
|
|
||||||
endif
|
|
||||||
SRC = ../src/unity_fixture.c \
|
SRC = ../src/unity_fixture.c \
|
||||||
../../../src/unity.c \
|
../../../src/unity.c \
|
||||||
unity_fixture_Test.c \
|
unity_fixture_Test.c \
|
||||||
unity_fixture_TestRunner.c \
|
unity_fixture_TestRunner.c \
|
||||||
unity_output_Spy.c \
|
|
||||||
main/AllTests.c
|
main/AllTests.c
|
||||||
|
|
||||||
INC_DIR = -I../src -I../../../src/
|
INC_DIR = -I../src -I../../../src/
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ static void runAllTests(void)
|
|||||||
{
|
{
|
||||||
RUN_TEST_GROUP(UnityFixture);
|
RUN_TEST_GROUP(UnityFixture);
|
||||||
RUN_TEST_GROUP(UnityCommandOptions);
|
RUN_TEST_GROUP(UnityCommandOptions);
|
||||||
RUN_TEST_GROUP(LeakDetection);
|
|
||||||
RUN_TEST_GROUP(InternalMalloc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
* ========================================== */
|
* ========================================== */
|
||||||
|
|
||||||
#include "unity_fixture.h"
|
#include "unity_fixture.h"
|
||||||
#include "unity_output_Spy.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -44,71 +43,6 @@ TEST(UnityFixture, PointerSetting)
|
|||||||
TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3);
|
TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UnityFixture, ForceMallocFail)
|
|
||||||
{
|
|
||||||
void* m;
|
|
||||||
void* mfails;
|
|
||||||
UnityMalloc_MakeMallocFailAfterCount(1);
|
|
||||||
m = malloc(10);
|
|
||||||
CHECK(m);
|
|
||||||
mfails = malloc(10);
|
|
||||||
TEST_ASSERT_POINTERS_EQUAL(0, mfails);
|
|
||||||
free(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnityFixture, ReallocSmallerIsUnchanged)
|
|
||||||
{
|
|
||||||
void* m1 = malloc(10);
|
|
||||||
void* m2 = realloc(m1, 5);
|
|
||||||
TEST_ASSERT_POINTERS_EQUAL(m1, m2);
|
|
||||||
free(m2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnityFixture, ReallocSameIsUnchanged)
|
|
||||||
{
|
|
||||||
void* m1 = malloc(10);
|
|
||||||
void* m2 = realloc(m1, 10);
|
|
||||||
TEST_ASSERT_POINTERS_EQUAL(m1, m2);
|
|
||||||
free(m2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnityFixture, ReallocLargerNeeded)
|
|
||||||
{
|
|
||||||
void* m1 = malloc(10);
|
|
||||||
void* m2;
|
|
||||||
CHECK(m1);
|
|
||||||
strcpy((char*)m1, "123456789");
|
|
||||||
m2 = realloc(m1, 15);
|
|
||||||
/* CHECK(m1 != m2); //Depends on implementation */
|
|
||||||
STRCMP_EQUAL("123456789", m2);
|
|
||||||
free(m2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnityFixture, ReallocNullPointerIsLikeMalloc)
|
|
||||||
{
|
|
||||||
void* m = realloc(0, 15);
|
|
||||||
CHECK(m != 0);
|
|
||||||
free(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer)
|
|
||||||
{
|
|
||||||
void* m1 = malloc(10);
|
|
||||||
void* m2 = realloc(m1, 0);
|
|
||||||
TEST_ASSERT_POINTERS_EQUAL(0, m2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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]);
|
|
||||||
free(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *p1;
|
static char *p1;
|
||||||
static char *p2;
|
static char *p2;
|
||||||
|
|
||||||
@@ -140,12 +74,10 @@ TEST(UnityFixture, ConcludeTestIncrementsFailCount)
|
|||||||
{
|
{
|
||||||
UNITY_UINT savedFails = Unity.TestFailures;
|
UNITY_UINT savedFails = Unity.TestFailures;
|
||||||
UNITY_UINT savedIgnores = Unity.TestIgnores;
|
UNITY_UINT savedIgnores = Unity.TestIgnores;
|
||||||
UnityOutputCharSpy_Enable(1);
|
|
||||||
Unity.CurrentTestFailed = 1;
|
Unity.CurrentTestFailed = 1;
|
||||||
UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */
|
UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */
|
||||||
Unity.CurrentTestIgnored = 1;
|
Unity.CurrentTestIgnored = 1;
|
||||||
UnityConcludeFixtureTest(); /* Resets TestIgnored */
|
UnityConcludeFixtureTest(); /* Resets TestIgnored */
|
||||||
UnityOutputCharSpy_Enable(0);
|
|
||||||
TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures);
|
TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures);
|
||||||
TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores);
|
TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores);
|
||||||
Unity.TestFailures = savedFails;
|
Unity.TestFailures = savedFails;
|
||||||
@@ -311,235 +243,3 @@ IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored)
|
|||||||
{
|
{
|
||||||
TEST_FAIL_MESSAGE("This test should not run!");
|
TEST_FAIL_MESSAGE("This test should not run!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------ */
|
|
||||||
|
|
||||||
TEST_GROUP(LeakDetection);
|
|
||||||
|
|
||||||
TEST_SETUP(LeakDetection)
|
|
||||||
{
|
|
||||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
|
||||||
UnityOutputCharSpy_Create(200);
|
|
||||||
#else
|
|
||||||
UnityOutputCharSpy_Create(1000);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_TEAR_DOWN(LeakDetection)
|
|
||||||
{
|
|
||||||
UnityOutputCharSpy_Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EXPECT_ABORT_BEGIN \
|
|
||||||
{ \
|
|
||||||
jmp_buf TestAbortFrame; \
|
|
||||||
memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \
|
|
||||||
if (TEST_PROTECT()) \
|
|
||||||
{
|
|
||||||
|
|
||||||
#define EXPECT_ABORT_END \
|
|
||||||
} \
|
|
||||||
memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */
|
|
||||||
#ifdef __STDC_VERSION__
|
|
||||||
|
|
||||||
#ifdef UNITY_SUPPORT_VARIADIC_MACROS
|
|
||||||
#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
|
|
||||||
#define ASSIGN_VALUE(a) VAL_##a
|
|
||||||
#define VAL_UnityOutputCharSpy_OutputChar 0, 1
|
|
||||||
#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway)
|
|
||||||
#define SECOND_PARAM(a, b, ...) b
|
|
||||||
#if USING_SPY_AS(UNITY_OUTPUT_CHAR)
|
|
||||||
#define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */
|
|
||||||
#endif
|
|
||||||
#endif /* UNITY_SUPPORT_VARIADIC_MACROS */
|
|
||||||
|
|
||||||
#else /* __STDC_VERSION__ else */
|
|
||||||
|
|
||||||
#define UnityOutputCharSpy_OutputChar 42
|
|
||||||
#if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */
|
|
||||||
#define USING_OUTPUT_SPY
|
|
||||||
#endif
|
|
||||||
#undef UnityOutputCharSpy_OutputChar
|
|
||||||
|
|
||||||
#endif /* __STDC_VERSION__ */
|
|
||||||
|
|
||||||
TEST(LeakDetection, DetectsLeak)
|
|
||||||
{
|
|
||||||
#ifndef USING_OUTPUT_SPY
|
|
||||||
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();
|
|
||||||
EXPECT_ABORT_END
|
|
||||||
UnityOutputCharSpy_Enable(0);
|
|
||||||
Unity.CurrentTestFailed = 0;
|
|
||||||
CHECK(strstr(UnityOutputCharSpy_Get(), "This test leaks!"));
|
|
||||||
free(m);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LeakDetection, BufferOverrunFoundDuringFree)
|
|
||||||
{
|
|
||||||
#ifndef USING_OUTPUT_SPY
|
|
||||||
TEST_IGNORE();
|
|
||||||
#else
|
|
||||||
void* m = malloc(10);
|
|
||||||
char* s = (char*)m;
|
|
||||||
TEST_ASSERT_NOT_NULL(m);
|
|
||||||
s[10] = (char)0xFF;
|
|
||||||
UnityOutputCharSpy_Enable(1);
|
|
||||||
EXPECT_ABORT_BEGIN
|
|
||||||
free(m);
|
|
||||||
EXPECT_ABORT_END
|
|
||||||
UnityOutputCharSpy_Enable(0);
|
|
||||||
Unity.CurrentTestFailed = 0;
|
|
||||||
CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LeakDetection, BufferOverrunFoundDuringRealloc)
|
|
||||||
{
|
|
||||||
#ifndef USING_OUTPUT_SPY
|
|
||||||
TEST_IGNORE();
|
|
||||||
#else
|
|
||||||
void* m = malloc(10);
|
|
||||||
char* s = (char*)m;
|
|
||||||
TEST_ASSERT_NOT_NULL(m);
|
|
||||||
s[10] = (char)0xFF;
|
|
||||||
UnityOutputCharSpy_Enable(1);
|
|
||||||
EXPECT_ABORT_BEGIN
|
|
||||||
m = realloc(m, 100);
|
|
||||||
EXPECT_ABORT_END
|
|
||||||
UnityOutputCharSpy_Enable(0);
|
|
||||||
Unity.CurrentTestFailed = 0;
|
|
||||||
CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LeakDetection, BufferGuardWriteFoundDuringFree)
|
|
||||||
{
|
|
||||||
#ifndef USING_OUTPUT_SPY
|
|
||||||
TEST_IGNORE();
|
|
||||||
#else
|
|
||||||
void* m = malloc(10);
|
|
||||||
char* s = (char*)m;
|
|
||||||
TEST_ASSERT_NOT_NULL(m);
|
|
||||||
s[-1] = (char)0x00; /* Will not detect 0 */
|
|
||||||
s[-2] = (char)0x01;
|
|
||||||
UnityOutputCharSpy_Enable(1);
|
|
||||||
EXPECT_ABORT_BEGIN
|
|
||||||
free(m);
|
|
||||||
EXPECT_ABORT_END
|
|
||||||
UnityOutputCharSpy_Enable(0);
|
|
||||||
Unity.CurrentTestFailed = 0;
|
|
||||||
CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LeakDetection, BufferGuardWriteFoundDuringRealloc)
|
|
||||||
{
|
|
||||||
#ifndef USING_OUTPUT_SPY
|
|
||||||
TEST_IGNORE();
|
|
||||||
#else
|
|
||||||
void* m = malloc(10);
|
|
||||||
char* s = (char*)m;
|
|
||||||
TEST_ASSERT_NOT_NULL(m);
|
|
||||||
s[-1] = (char)0x0A;
|
|
||||||
UnityOutputCharSpy_Enable(1);
|
|
||||||
EXPECT_ABORT_BEGIN
|
|
||||||
m = realloc(m, 100);
|
|
||||||
EXPECT_ABORT_END
|
|
||||||
UnityOutputCharSpy_Enable(0);
|
|
||||||
Unity.CurrentTestFailed = 0;
|
|
||||||
CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LeakDetection, PointerSettingMax)
|
|
||||||
{
|
|
||||||
#ifndef USING_OUTPUT_SPY
|
|
||||||
TEST_IGNORE();
|
|
||||||
#else
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < UNITY_MAX_POINTERS; i++) UT_PTR_SET(pointer1, &int1);
|
|
||||||
UnityOutputCharSpy_Enable(1);
|
|
||||||
EXPECT_ABORT_BEGIN
|
|
||||||
UT_PTR_SET(pointer1, &int1);
|
|
||||||
EXPECT_ABORT_END
|
|
||||||
UnityOutputCharSpy_Enable(0);
|
|
||||||
Unity.CurrentTestFailed = 0;
|
|
||||||
CHECK(strstr(UnityOutputCharSpy_Get(), "Too many pointers set"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*------------------------------------------------------------ */
|
|
||||||
|
|
||||||
TEST_GROUP(InternalMalloc);
|
|
||||||
#define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \
|
|
||||||
ptr = malloc(10); free(ptr); \
|
|
||||||
TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order");
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
|
|
||||||
free(m);
|
|
||||||
TEST_ASSERT_NOT_NULL(m);
|
|
||||||
TEST_ASSERT_NULL(n);
|
|
||||||
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(InternalMalloc, CallocPastBufferFails)
|
|
||||||
{
|
|
||||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
|
||||||
void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
|
|
||||||
void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
|
|
||||||
free(m);
|
|
||||||
TEST_ASSERT_NOT_NULL(m);
|
|
||||||
TEST_ASSERT_NULL(n);
|
|
||||||
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(InternalMalloc, MallocThenReallocGrowsMemoryInPlace)
|
|
||||||
{
|
|
||||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
|
||||||
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
|
|
||||||
void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9);
|
|
||||||
free(n);
|
|
||||||
TEST_ASSERT_NOT_NULL(m);
|
|
||||||
TEST_ASSERT_EQUAL(m, n);
|
|
||||||
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(InternalMalloc, ReallocFailDoesNotFreeMem)
|
|
||||||
{
|
|
||||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
|
||||||
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
|
|
||||||
void* n1 = malloc(10);
|
|
||||||
void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
|
|
||||||
void* n2 = malloc(10);
|
|
||||||
|
|
||||||
free(n2);
|
|
||||||
if (out_of_mem == NULL) free(n1);
|
|
||||||
free(m);
|
|
||||||
|
|
||||||
TEST_ASSERT_NOT_NULL(m); /* Got a real memory location */
|
|
||||||
TEST_ASSERT_NULL(out_of_mem); /* The realloc should have failed */
|
|
||||||
TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */
|
|
||||||
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,13 +10,6 @@
|
|||||||
TEST_GROUP_RUNNER(UnityFixture)
|
TEST_GROUP_RUNNER(UnityFixture)
|
||||||
{
|
{
|
||||||
RUN_TEST_CASE(UnityFixture, PointerSetting);
|
RUN_TEST_CASE(UnityFixture, PointerSetting);
|
||||||
RUN_TEST_CASE(UnityFixture, ForceMallocFail);
|
|
||||||
RUN_TEST_CASE(UnityFixture, ReallocSmallerIsUnchanged);
|
|
||||||
RUN_TEST_CASE(UnityFixture, ReallocSameIsUnchanged);
|
|
||||||
RUN_TEST_CASE(UnityFixture, ReallocLargerNeeded);
|
|
||||||
RUN_TEST_CASE(UnityFixture, ReallocNullPointerIsLikeMalloc);
|
|
||||||
RUN_TEST_CASE(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer);
|
|
||||||
RUN_TEST_CASE(UnityFixture, CallocFillsWithZero);
|
|
||||||
RUN_TEST_CASE(UnityFixture, PointerSet);
|
RUN_TEST_CASE(UnityFixture, PointerSet);
|
||||||
RUN_TEST_CASE(UnityFixture, FreeNULLSafety);
|
RUN_TEST_CASE(UnityFixture, FreeNULLSafety);
|
||||||
RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount);
|
RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount);
|
||||||
@@ -37,21 +30,3 @@ TEST_GROUP_RUNNER(UnityCommandOptions)
|
|||||||
RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters);
|
RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters);
|
||||||
RUN_TEST_CASE(UnityCommandOptions, TestShouldBeIgnored);
|
RUN_TEST_CASE(UnityCommandOptions, TestShouldBeIgnored);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_GROUP_RUNNER(LeakDetection)
|
|
||||||
{
|
|
||||||
RUN_TEST_CASE(LeakDetection, DetectsLeak);
|
|
||||||
RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringFree);
|
|
||||||
RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringRealloc);
|
|
||||||
RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringFree);
|
|
||||||
RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringRealloc);
|
|
||||||
RUN_TEST_CASE(LeakDetection, PointerSettingMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_GROUP_RUNNER(InternalMalloc)
|
|
||||||
{
|
|
||||||
RUN_TEST_CASE(InternalMalloc, MallocPastBufferFails);
|
|
||||||
RUN_TEST_CASE(InternalMalloc, CallocPastBufferFails);
|
|
||||||
RUN_TEST_CASE(InternalMalloc, MallocThenReallocGrowsMemoryInPlace);
|
|
||||||
RUN_TEST_CASE(InternalMalloc, ReallocFailDoesNotFreeMem);
|
|
||||||
}
|
|
||||||
|
|||||||
45
extras/memory/rakefile.rb
Normal file
45
extras/memory/rakefile.rb
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# ==========================================
|
||||||
|
# Unity Project - A Test Framework for C
|
||||||
|
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
|
# [Released under MIT License. Please refer to license.txt for details]
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
require 'rake'
|
||||||
|
require 'rake/clean'
|
||||||
|
require 'rake/testtask'
|
||||||
|
require_relative 'rakefile_helper'
|
||||||
|
|
||||||
|
TEMP_DIRS = [
|
||||||
|
File.join(__dir__, 'build')
|
||||||
|
].freeze
|
||||||
|
|
||||||
|
TEMP_DIRS.each do |dir|
|
||||||
|
directory(dir)
|
||||||
|
CLOBBER.include(dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
task prepare_for_tests: TEMP_DIRS
|
||||||
|
|
||||||
|
# Load default configuration, for now
|
||||||
|
DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'.freeze
|
||||||
|
configure_toolchain(DEFAULT_CONFIG_FILE)
|
||||||
|
|
||||||
|
task unit: [:prepare_for_tests] do
|
||||||
|
run_tests(false)
|
||||||
|
run_tests(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Build and test Unity Framework'
|
||||||
|
task all: %i[clean unit]
|
||||||
|
task default: %i[clobber all]
|
||||||
|
task ci: %i[no_color default]
|
||||||
|
task cruise: %i[no_color default]
|
||||||
|
|
||||||
|
desc 'Load configuration'
|
||||||
|
task :config, :config_file do |_t, args|
|
||||||
|
configure_toolchain(args[:config_file])
|
||||||
|
end
|
||||||
|
|
||||||
|
task :no_color do
|
||||||
|
$colour_output = false
|
||||||
|
end
|
||||||
187
extras/memory/rakefile_helper.rb
Normal file
187
extras/memory/rakefile_helper.rb
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
# ==========================================
|
||||||
|
# Unity Project - A Test Framework for C
|
||||||
|
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
|
# [Released under MIT License. Please refer to license.txt for details]
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
require 'fileutils'
|
||||||
|
require 'rbconfig'
|
||||||
|
require_relative '../../auto/unity_test_summary'
|
||||||
|
require_relative '../../auto/generate_test_runner'
|
||||||
|
require_relative '../../auto/colour_reporter'
|
||||||
|
|
||||||
|
$is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
||||||
|
|
||||||
|
C_EXTENSION = '.c'.freeze
|
||||||
|
|
||||||
|
def load_configuration(config_file)
|
||||||
|
return if $configured
|
||||||
|
|
||||||
|
$cfg_file = "#{__dir__}/../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/
|
||||||
|
$cfg = YAML.load(File.read($cfg_file))
|
||||||
|
$colour_output = false unless $cfg['colour']
|
||||||
|
$configured = true if config_file != DEFAULT_CONFIG_FILE
|
||||||
|
end
|
||||||
|
|
||||||
|
def configure_clean
|
||||||
|
CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
|
||||||
|
config_file += '.yml' unless config_file =~ /\.yml$/
|
||||||
|
config_file = config_file unless config_file =~ /[\\|\/]/
|
||||||
|
load_configuration(config_file)
|
||||||
|
configure_clean
|
||||||
|
end
|
||||||
|
|
||||||
|
def tackit(strings)
|
||||||
|
result = if strings.is_a?(Array)
|
||||||
|
"\"#{strings.join}\""
|
||||||
|
else
|
||||||
|
strings
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def squash(prefix, items)
|
||||||
|
result = ''
|
||||||
|
items.each { |item| result += " #{prefix}#{tackit(item)}" }
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_compiler_fields
|
||||||
|
command = tackit($cfg['compiler']['path'])
|
||||||
|
defines = if $cfg['compiler']['defines']['items'].nil?
|
||||||
|
''
|
||||||
|
else
|
||||||
|
decl = if $is_windows
|
||||||
|
'UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar(int)'
|
||||||
|
else
|
||||||
|
'UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)'
|
||||||
|
end
|
||||||
|
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'] + [decl])
|
||||||
|
end
|
||||||
|
options = squash('', $cfg['compiler']['options'])
|
||||||
|
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
|
||||||
|
includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
|
||||||
|
|
||||||
|
{ command: command, defines: defines, options: options, includes: includes }
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile(file, _defines = [])
|
||||||
|
compiler = build_compiler_fields
|
||||||
|
unity_include = $cfg['compiler']['includes']['prefix'] + '../../src'
|
||||||
|
cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{file} " \
|
||||||
|
"#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" \
|
||||||
|
"#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
|
||||||
|
|
||||||
|
execute(cmd_str)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_linker_fields
|
||||||
|
command = tackit($cfg['linker']['path'])
|
||||||
|
options = if $cfg['linker']['options'].nil?
|
||||||
|
''
|
||||||
|
else
|
||||||
|
squash('', $cfg['linker']['options'])
|
||||||
|
end
|
||||||
|
includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?
|
||||||
|
''
|
||||||
|
else
|
||||||
|
squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
|
||||||
|
end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
|
||||||
|
|
||||||
|
{ command: command, options: options, includes: includes }
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_it(exe_name, obj_list)
|
||||||
|
linker = build_linker_fields
|
||||||
|
cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " +
|
||||||
|
(obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join +
|
||||||
|
$cfg['linker']['bin_files']['prefix'] + ' ' +
|
||||||
|
$cfg['linker']['bin_files']['destination'] +
|
||||||
|
exe_name + $cfg['linker']['bin_files']['extension']
|
||||||
|
execute(cmd_str)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_simulator_fields
|
||||||
|
return nil if $cfg['simulator'].nil?
|
||||||
|
|
||||||
|
command = if $cfg['simulator']['path'].nil?
|
||||||
|
''
|
||||||
|
else
|
||||||
|
(tackit($cfg['simulator']['path']) + ' ')
|
||||||
|
end
|
||||||
|
pre_support = if $cfg['simulator']['pre_support'].nil?
|
||||||
|
''
|
||||||
|
else
|
||||||
|
squash('', $cfg['simulator']['pre_support'])
|
||||||
|
end
|
||||||
|
post_support = if $cfg['simulator']['post_support'].nil?
|
||||||
|
''
|
||||||
|
else
|
||||||
|
squash('', $cfg['simulator']['post_support'])
|
||||||
|
end
|
||||||
|
{ command: command, pre_support: pre_support, post_support: post_support }
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(command_string, verbose = true)
|
||||||
|
report command_string
|
||||||
|
output = `#{command_string}`.chomp
|
||||||
|
report(output) if verbose && !output.nil? && !output.empty?
|
||||||
|
|
||||||
|
raise "Command failed. (Returned #{$?.exitstatus})" if $?.exitstatus != 0
|
||||||
|
|
||||||
|
output
|
||||||
|
end
|
||||||
|
|
||||||
|
def report_summary
|
||||||
|
summary = UnityTestSummary.new
|
||||||
|
summary.root = __dir__
|
||||||
|
results_glob = "#{$cfg['compiler']['build_path']}*.test*"
|
||||||
|
results_glob.tr!('\\', '/')
|
||||||
|
results = Dir[results_glob]
|
||||||
|
summary.targets = results
|
||||||
|
summary.run
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_tests(exclude_stdlib=false)
|
||||||
|
report 'Running Unity system tests...'
|
||||||
|
|
||||||
|
# Tack on TEST define for compiling unit tests
|
||||||
|
load_configuration($cfg_file)
|
||||||
|
test_defines = ['TEST']
|
||||||
|
$cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
|
||||||
|
$cfg['compiler']['defines']['items'] << 'UNITY_EXCLUDE_STDLIB_MALLOC' if exclude_stdlib
|
||||||
|
|
||||||
|
# Get a list of all source files needed
|
||||||
|
src_files = Dir["#{__dir__}/src/*.c"]
|
||||||
|
src_files += Dir["#{__dir__}/test/*.c"]
|
||||||
|
src_files << '../../src/unity.c'
|
||||||
|
|
||||||
|
# Build object files
|
||||||
|
src_files.each { |f| compile(f, test_defines) }
|
||||||
|
obj_list = src_files.map { |f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) }
|
||||||
|
|
||||||
|
# Link the test executable
|
||||||
|
test_base = 'framework_test'
|
||||||
|
link_it(test_base, obj_list)
|
||||||
|
|
||||||
|
# Execute unit test and generate results file
|
||||||
|
simulator = build_simulator_fields
|
||||||
|
executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
|
||||||
|
cmd_str = if simulator.nil?
|
||||||
|
executable + ' -v -r'
|
||||||
|
else
|
||||||
|
"#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
|
||||||
|
end
|
||||||
|
output = execute(cmd_str)
|
||||||
|
test_results = $cfg['compiler']['build_path'] + test_base
|
||||||
|
test_results += if output.match(/OK$/m).nil?
|
||||||
|
'.testfail'
|
||||||
|
else
|
||||||
|
'.testpass'
|
||||||
|
end
|
||||||
|
File.open(test_results, 'w') { |f| f.print output }
|
||||||
|
end
|
||||||
49
extras/memory/readme.md
Normal file
49
extras/memory/readme.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Unity Memory
|
||||||
|
|
||||||
|
This Framework is an optional add-on to Unity. By including unity.h and then
|
||||||
|
unity_memory.h, you have the added ability to track malloc and free calls. This
|
||||||
|
addon requires that the stdlib functions be overridden by its own defines. These
|
||||||
|
defines will still malloc / realloc / free etc, but will also track the calls
|
||||||
|
in order to ensure that you don't have any memory leaks in your programs.
|
||||||
|
|
||||||
|
Note that this is only useful in situations where a unit is in charge of both
|
||||||
|
the allocation and deallocation of memory. When it is not symmetric, unit testing
|
||||||
|
can report a number of false failures. A more advanced runtime tool is required to
|
||||||
|
track complete system memory handling.
|
||||||
|
|
||||||
|
# Module API
|
||||||
|
|
||||||
|
## `UnityMalloc_StartTest` and `UnityMalloc_EndTest`
|
||||||
|
|
||||||
|
These must be called at the beginning and end of each test. For simplicity, they can
|
||||||
|
be added to `setUp` and `tearDown` in order to do their job. When using the test
|
||||||
|
runner generator scripts, these will be automatically added to the runner whenever
|
||||||
|
unity_memory.h is included.
|
||||||
|
|
||||||
|
## `UnityMalloc_MakeMallocFailAfterCount`
|
||||||
|
|
||||||
|
This can be called from the tests themselves. Passing this function a number will
|
||||||
|
force the reference counter to start keeping track of malloc calls. During that test,
|
||||||
|
if the number of malloc calls exceeds the number given, malloc will immediately
|
||||||
|
start returning `NULL`. This allows you to test error conditions. Think of it as a
|
||||||
|
simplified mock.
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
## `UNITY_MALLOC` and `UNITY_FREE`
|
||||||
|
|
||||||
|
By default, this module tries to use the real stdlib `malloc` and `free` internally.
|
||||||
|
If you would prefer it to use something else, like FreeRTOS's `pvPortMalloc` and
|
||||||
|
`pvPortFree`, then you can use these defines to make it so.
|
||||||
|
|
||||||
|
## `UNITY_EXCLUDE_STDLIB_MALLOC`
|
||||||
|
|
||||||
|
If you would like this library to ignore stdlib or other heap engines completely, and
|
||||||
|
manage the memory on its own, then define this. All memory will be handled internally
|
||||||
|
(and at likely lower overhead). Note that this is not a very featureful memory manager,
|
||||||
|
but is sufficient for most testing purposes.
|
||||||
|
|
||||||
|
## `UNITY_INTERNAL_HEAP_SIZE_BYTES`
|
||||||
|
|
||||||
|
When using the built-in memory manager (see `UNITY_EXCLUDE_STDLIB_MALLOC`) this define
|
||||||
|
allows you to set the heap size this library will use to manage the memory.
|
||||||
201
extras/memory/src/unity_memory.c
Normal file
201
extras/memory/src/unity_memory.c
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/* ==========================================
|
||||||
|
* Unity Project - A Test Framework for C
|
||||||
|
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
|
* [Released under MIT License. Please refer to license.txt for details]
|
||||||
|
* ========================================== */
|
||||||
|
|
||||||
|
#include "unity.h"
|
||||||
|
#include "unity_memory.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MALLOC_DONT_FAIL -1
|
||||||
|
static int malloc_count;
|
||||||
|
static int malloc_fail_countdown = MALLOC_DONT_FAIL;
|
||||||
|
|
||||||
|
void UnityMalloc_StartTest(void)
|
||||||
|
{
|
||||||
|
malloc_count = 0;
|
||||||
|
malloc_fail_countdown = MALLOC_DONT_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnityMalloc_EndTest(void)
|
||||||
|
{
|
||||||
|
malloc_fail_countdown = MALLOC_DONT_FAIL;
|
||||||
|
if (malloc_count != 0)
|
||||||
|
{
|
||||||
|
UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnityMalloc_MakeMallocFailAfterCount(int countdown)
|
||||||
|
{
|
||||||
|
malloc_fail_countdown = countdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#undef free
|
||||||
|
#undef calloc
|
||||||
|
#undef realloc
|
||||||
|
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
|
||||||
|
static size_t heap_index;
|
||||||
|
#else
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct GuardBytes
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
size_t guard_space;
|
||||||
|
} Guard;
|
||||||
|
|
||||||
|
#define UNITY_MALLOC_ALIGNMENT (UNITY_POINTER_WIDTH / 8)
|
||||||
|
static const char end[] = "END";
|
||||||
|
|
||||||
|
static size_t unity_size_round_up(size_t size)
|
||||||
|
{
|
||||||
|
size_t rounded_size;
|
||||||
|
|
||||||
|
rounded_size = ((size + UNITY_MALLOC_ALIGNMENT - 1) / UNITY_MALLOC_ALIGNMENT) * UNITY_MALLOC_ALIGNMENT;
|
||||||
|
|
||||||
|
return rounded_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* unity_malloc(size_t size)
|
||||||
|
{
|
||||||
|
char* mem;
|
||||||
|
Guard* guard;
|
||||||
|
size_t total_size;
|
||||||
|
|
||||||
|
total_size = sizeof(Guard) + unity_size_round_up(size + sizeof(end));
|
||||||
|
|
||||||
|
if (malloc_fail_countdown != MALLOC_DONT_FAIL)
|
||||||
|
{
|
||||||
|
if (malloc_fail_countdown == 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_MALLOC(total_size);
|
||||||
|
#endif
|
||||||
|
if (guard == NULL) return NULL;
|
||||||
|
malloc_count++;
|
||||||
|
guard->size = size;
|
||||||
|
guard->guard_space = 0;
|
||||||
|
mem = (char*)&(guard[1]);
|
||||||
|
memcpy(&mem[size], end, sizeof(end));
|
||||||
|
|
||||||
|
return (void*)mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isOverrun(void* mem)
|
||||||
|
{
|
||||||
|
Guard* guard = (Guard*)mem;
|
||||||
|
char* memAsChar = (char*)mem;
|
||||||
|
guard--;
|
||||||
|
|
||||||
|
return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void release_memory(void* mem)
|
||||||
|
{
|
||||||
|
Guard* guard = (Guard*)mem;
|
||||||
|
guard--;
|
||||||
|
|
||||||
|
malloc_count--;
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
{
|
||||||
|
size_t block_size;
|
||||||
|
|
||||||
|
block_size = unity_size_round_up(guard->size + sizeof(end));
|
||||||
|
|
||||||
|
if (mem == unity_heap + heap_index - block_size)
|
||||||
|
{
|
||||||
|
heap_index -= (sizeof(Guard) + block_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
UNITY_FREE(guard);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void unity_free(void* mem)
|
||||||
|
{
|
||||||
|
int overrun;
|
||||||
|
|
||||||
|
if (mem == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
overrun = isOverrun(mem);
|
||||||
|
release_memory(mem);
|
||||||
|
if (overrun)
|
||||||
|
{
|
||||||
|
UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* unity_calloc(size_t num, size_t size)
|
||||||
|
{
|
||||||
|
void* mem = unity_malloc(num * size);
|
||||||
|
if (mem == NULL) return NULL;
|
||||||
|
memset(mem, 0, num * size);
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* unity_realloc(void* oldMem, size_t size)
|
||||||
|
{
|
||||||
|
Guard* guard = (Guard*)oldMem;
|
||||||
|
void* newMem;
|
||||||
|
|
||||||
|
if (oldMem == NULL) return unity_malloc(size);
|
||||||
|
|
||||||
|
guard--;
|
||||||
|
if (isOverrun(oldMem))
|
||||||
|
{
|
||||||
|
release_memory(oldMem);
|
||||||
|
UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
release_memory(oldMem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guard->size >= size) return oldMem;
|
||||||
|
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */
|
||||||
|
{
|
||||||
|
size_t old_total_size = unity_size_round_up(guard->size + sizeof(end));
|
||||||
|
|
||||||
|
if ((oldMem == unity_heap + heap_index - old_total_size) &&
|
||||||
|
((heap_index - old_total_size + unity_size_round_up(size + sizeof(end))) <= 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);
|
||||||
|
release_memory(oldMem);
|
||||||
|
return newMem;
|
||||||
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
/* ==========================================
|
||||||
* ==========================================
|
|
||||||
* Unity Project - A Test Framework for C
|
* Unity Project - A Test Framework for C
|
||||||
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
* [Released under MIT License. Please refer to license.txt for details]
|
* [Released under MIT License. Please refer to license.txt for details]
|
||||||
* ========================================== */
|
* ========================================== */
|
||||||
|
|
||||||
#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_
|
#ifndef UNITY_MEMORY_OVERRIDES_H_
|
||||||
#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_
|
#define UNITY_MEMORY_OVERRIDES_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -21,17 +25,17 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* These functions are used by the Unity Fixture to allocate and release memory
|
/* These functions are used by Unity to allocate and release memory
|
||||||
* on the heap and can be overridden with platform-specific implementations.
|
* on the heap and can be overridden with platform-specific implementations.
|
||||||
* For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc()
|
* For example, when using FreeRTOS UNITY_MALLOC becomes pvPortMalloc()
|
||||||
* and UNITY_FIXTURE_FREE becomes vPortFree(). */
|
* and UNITY_FREE becomes vPortFree(). */
|
||||||
#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE)
|
#if !defined(UNITY_MALLOC) || !defined(UNITY_FREE)
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#define UNITY_FIXTURE_MALLOC(size) malloc(size)
|
#define UNITY_MALLOC(size) malloc(size)
|
||||||
#define UNITY_FIXTURE_FREE(ptr) free(ptr)
|
#define UNITY_FREE(ptr) free(ptr)
|
||||||
#else
|
#else
|
||||||
extern void* UNITY_FIXTURE_MALLOC(size_t size);
|
extern void* UNITY_MALLOC(size_t size);
|
||||||
extern void UNITY_FIXTURE_FREE(void* ptr);
|
extern void UNITY_FREE(void* ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define malloc unity_malloc
|
#define malloc unity_malloc
|
||||||
@@ -44,4 +48,13 @@ void* unity_calloc(size_t num, size_t size);
|
|||||||
void* unity_realloc(void * oldMem, size_t size);
|
void* unity_realloc(void * oldMem, size_t size);
|
||||||
void unity_free(void * mem);
|
void unity_free(void * mem);
|
||||||
|
|
||||||
#endif /* UNITY_FIXTURE_MALLOC_OVERRIDES_H_ */
|
/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */
|
||||||
|
void UnityMalloc_StartTest(void);
|
||||||
|
void UnityMalloc_EndTest(void);
|
||||||
|
void UnityMalloc_MakeMallocFailAfterCount(int countdown);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
78
extras/memory/test/Makefile
Normal file
78
extras/memory/test/Makefile
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
CC = gcc
|
||||||
|
ifeq ($(shell uname -s), Darwin)
|
||||||
|
CC = clang
|
||||||
|
endif
|
||||||
|
#DEBUG = -O0 -g
|
||||||
|
CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror
|
||||||
|
CFLAGS += $(DEBUG)
|
||||||
|
DEFINES = -D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar(int)
|
||||||
|
else
|
||||||
|
DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)
|
||||||
|
endif
|
||||||
|
SRC = ../src/unity_memory.c \
|
||||||
|
../../../src/unity.c \
|
||||||
|
unity_memory_Test.c \
|
||||||
|
unity_memory_TestRunner.c \
|
||||||
|
unity_output_Spy.c \
|
||||||
|
|
||||||
|
INC_DIR = -I../src -I../../../src/
|
||||||
|
BUILD_DIR = ../build
|
||||||
|
TARGET = ../build/memory_tests.exe
|
||||||
|
|
||||||
|
all: default noStdlibMalloc 32bits
|
||||||
|
|
||||||
|
default: $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_SUPPORT_64
|
||||||
|
@ echo "default build"
|
||||||
|
./$(TARGET)
|
||||||
|
|
||||||
|
32bits: $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -m32
|
||||||
|
@ echo "32bits build"
|
||||||
|
./$(TARGET)
|
||||||
|
|
||||||
|
noStdlibMalloc: $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
@ echo "build with noStdlibMalloc"
|
||||||
|
./$(TARGET)
|
||||||
|
|
||||||
|
C89: CFLAGS += -D UNITY_EXCLUDE_STDINT_H # C89 did not have type 'long long', <stdint.h>
|
||||||
|
C89: $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -std=c89 && ./$(TARGET)
|
||||||
|
$(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC -std=c89
|
||||||
|
./$(TARGET)
|
||||||
|
|
||||||
|
$(BUILD_DIR):
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET) $(BUILD_DIR)/*.gc*
|
||||||
|
|
||||||
|
cov: $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) && \
|
||||||
|
$(CC) $(DEFINES) $(foreach i, $(SRC), ../test/$(i)) $(INC_DIR) -o $(TARGET) -fprofile-arcs -ftest-coverage
|
||||||
|
rm -f $(BUILD_DIR)/*.gcda
|
||||||
|
./$(TARGET) > /dev/null ; ./$(TARGET) -v > /dev/null
|
||||||
|
cd $(BUILD_DIR) && \
|
||||||
|
gcov unity_memory.c | head -3
|
||||||
|
grep '###' $(BUILD_DIR)/unity_memory.c.gcov -C2 || true # Show uncovered lines
|
||||||
|
|
||||||
|
# These extended flags DO get included before any target build runs
|
||||||
|
CFLAGS += -Wbad-function-cast
|
||||||
|
CFLAGS += -Wcast-qual
|
||||||
|
CFLAGS += -Wconversion
|
||||||
|
CFLAGS += -Wformat=2
|
||||||
|
CFLAGS += -Wmissing-prototypes
|
||||||
|
CFLAGS += -Wold-style-definition
|
||||||
|
CFLAGS += -Wpointer-arith
|
||||||
|
CFLAGS += -Wshadow
|
||||||
|
CFLAGS += -Wstrict-overflow=5
|
||||||
|
CFLAGS += -Wstrict-prototypes
|
||||||
|
CFLAGS += -Wswitch-default
|
||||||
|
CFLAGS += -Wundef
|
||||||
|
CFLAGS += -Wno-error=undef # Warning only, this should not stop the build
|
||||||
|
CFLAGS += -Wunreachable-code
|
||||||
|
CFLAGS += -Wunused
|
||||||
|
CFLAGS += -fstrict-aliasing
|
||||||
300
extras/memory/test/unity_memory_Test.c
Normal file
300
extras/memory/test/unity_memory_Test.c
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
/* ==========================================
|
||||||
|
* Unity Project - A Test Framework for C
|
||||||
|
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
|
* [Released under MIT License. Please refer to license.txt for details]
|
||||||
|
* ========================================== */
|
||||||
|
|
||||||
|
#include "unity.h"
|
||||||
|
#include "unity_memory.h"
|
||||||
|
#include "unity_output_Spy.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void setUp(void)
|
||||||
|
{
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
UnityOutputCharSpy_Create(200);
|
||||||
|
#else
|
||||||
|
UnityOutputCharSpy_Create(1000);
|
||||||
|
#endif
|
||||||
|
UnityMalloc_StartTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void)
|
||||||
|
{
|
||||||
|
UnityMalloc_EndTest();
|
||||||
|
UnityOutputCharSpy_Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ForceMallocFail(void)
|
||||||
|
{
|
||||||
|
void* m;
|
||||||
|
void* mfails;
|
||||||
|
UnityMalloc_MakeMallocFailAfterCount(1);
|
||||||
|
m = malloc(10);
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
mfails = malloc(10);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(0, mfails);
|
||||||
|
free(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ReallocSmallerIsUnchanged(void)
|
||||||
|
{
|
||||||
|
void* m1 = malloc(10);
|
||||||
|
void* m2 = realloc(m1, 5);
|
||||||
|
TEST_ASSERT_NOT_NULL(m1);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(m1, m2);
|
||||||
|
free(m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ReallocSameIsUnchanged(void)
|
||||||
|
{
|
||||||
|
void* m1 = malloc(10);
|
||||||
|
void* m2 = realloc(m1, 10);
|
||||||
|
TEST_ASSERT_NOT_NULL(m1);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(m1, m2);
|
||||||
|
free(m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ReallocLargerNeeded(void)
|
||||||
|
{
|
||||||
|
void* m2;
|
||||||
|
void* m1 = malloc(10);
|
||||||
|
TEST_ASSERT_NOT_NULL(m1);
|
||||||
|
strcpy((char*)m1, "123456789");
|
||||||
|
m2 = realloc(m1, 15);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("123456789", m2);
|
||||||
|
free(m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ReallocNullPointerIsLikeMalloc(void)
|
||||||
|
{
|
||||||
|
void* m = realloc(0, 15);
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
free(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void)
|
||||||
|
{
|
||||||
|
void* m1 = malloc(10);
|
||||||
|
void* m2 = realloc(m1, 0);
|
||||||
|
TEST_ASSERT_EQUAL_PTR(0, m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_CallocFillsWithZero(void)
|
||||||
|
{
|
||||||
|
void* m = calloc(3, sizeof(char));
|
||||||
|
char* s = (char*)m;
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8(0, s[0]);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8(0, s[1]);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8(0, s[2]);
|
||||||
|
free(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_FreeNULLSafety(void)
|
||||||
|
{
|
||||||
|
free(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#define EXPECT_ABORT_BEGIN \
|
||||||
|
{ \
|
||||||
|
jmp_buf TestAbortFrame; \
|
||||||
|
memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \
|
||||||
|
if (TEST_PROTECT()) \
|
||||||
|
{
|
||||||
|
|
||||||
|
#define EXPECT_ABORT_END \
|
||||||
|
} \
|
||||||
|
memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */
|
||||||
|
#ifdef __STDC_VERSION__
|
||||||
|
|
||||||
|
#ifdef UNITY_SUPPORT_VARIADIC_MACROS
|
||||||
|
#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
|
||||||
|
#define ASSIGN_VALUE(a) VAL_##a
|
||||||
|
#define VAL_UnityOutputCharSpy_OutputChar 0, 1
|
||||||
|
#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway)
|
||||||
|
#define SECOND_PARAM(a, b, ...) b
|
||||||
|
#if USING_SPY_AS(UNITY_OUTPUT_CHAR)
|
||||||
|
#define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */
|
||||||
|
#endif
|
||||||
|
#endif /* UNITY_SUPPORT_VARIADIC_MACROS */
|
||||||
|
|
||||||
|
#else /* __STDC_VERSION__ else */
|
||||||
|
|
||||||
|
#define UnityOutputCharSpy_OutputChar 42
|
||||||
|
#if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */
|
||||||
|
#define USING_OUTPUT_SPY
|
||||||
|
#endif
|
||||||
|
#undef UnityOutputCharSpy_OutputChar
|
||||||
|
|
||||||
|
#endif /* __STDC_VERSION__ */
|
||||||
|
|
||||||
|
void test_DetectsLeak(void)
|
||||||
|
{
|
||||||
|
#ifdef USING_OUTPUT_SPY
|
||||||
|
void* m = malloc(10);
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
UnityOutputCharSpy_Enable(1);
|
||||||
|
EXPECT_ABORT_BEGIN
|
||||||
|
UnityMalloc_EndTest();
|
||||||
|
EXPECT_ABORT_END
|
||||||
|
UnityOutputCharSpy_Enable(0);
|
||||||
|
Unity.CurrentTestFailed = 0;
|
||||||
|
TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "This test leaks!"));
|
||||||
|
free(m);
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_BufferOverrunFoundDuringFree(void)
|
||||||
|
{
|
||||||
|
#ifdef USING_OUTPUT_SPY
|
||||||
|
void* m = malloc(10);
|
||||||
|
char* s = (char*)m;
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
s[10] = (char)0xFF;
|
||||||
|
UnityOutputCharSpy_Enable(1);
|
||||||
|
EXPECT_ABORT_BEGIN
|
||||||
|
free(m);
|
||||||
|
EXPECT_ABORT_END
|
||||||
|
UnityOutputCharSpy_Enable(0);
|
||||||
|
Unity.CurrentTestFailed = 0;
|
||||||
|
TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_BufferOverrunFoundDuringRealloc(void)
|
||||||
|
{
|
||||||
|
#ifdef USING_OUTPUT_SPY
|
||||||
|
void* m = malloc(10);
|
||||||
|
char* s = (char*)m;
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
s[10] = (char)0xFF;
|
||||||
|
UnityOutputCharSpy_Enable(1);
|
||||||
|
EXPECT_ABORT_BEGIN
|
||||||
|
m = realloc(m, 100);
|
||||||
|
EXPECT_ABORT_END
|
||||||
|
UnityOutputCharSpy_Enable(0);
|
||||||
|
Unity.CurrentTestFailed = 0;
|
||||||
|
TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_BufferGuardWriteFoundDuringFree(void)
|
||||||
|
{
|
||||||
|
#ifdef USING_OUTPUT_SPY
|
||||||
|
void* m = malloc(10);
|
||||||
|
char* s = (char*)m;
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
s[-1] = (char)0x00; /* Will not detect 0 */
|
||||||
|
s[-2] = (char)0x01;
|
||||||
|
UnityOutputCharSpy_Enable(1);
|
||||||
|
EXPECT_ABORT_BEGIN
|
||||||
|
free(m);
|
||||||
|
EXPECT_ABORT_END
|
||||||
|
UnityOutputCharSpy_Enable(0);
|
||||||
|
Unity.CurrentTestFailed = 0;
|
||||||
|
TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_BufferGuardWriteFoundDuringRealloc(void)
|
||||||
|
{
|
||||||
|
#ifdef USING_OUTPUT_SPY
|
||||||
|
void* m = malloc(10);
|
||||||
|
char* s = (char*)m;
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
s[-1] = (char)0x0A;
|
||||||
|
UnityOutputCharSpy_Enable(1);
|
||||||
|
EXPECT_ABORT_BEGIN
|
||||||
|
m = realloc(m, 100);
|
||||||
|
EXPECT_ABORT_END
|
||||||
|
UnityOutputCharSpy_Enable(0);
|
||||||
|
Unity.CurrentTestFailed = 0;
|
||||||
|
TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \
|
||||||
|
ptr = malloc(10); free(ptr); \
|
||||||
|
TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order");
|
||||||
|
|
||||||
|
void test_MallocPastBufferFails(void)
|
||||||
|
{
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
|
||||||
|
void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
|
||||||
|
free(m);
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
TEST_ASSERT_NULL(n);
|
||||||
|
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_CallocPastBufferFails(void)
|
||||||
|
{
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
|
||||||
|
void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
|
||||||
|
free(m);
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
TEST_ASSERT_NULL(n);
|
||||||
|
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_MallocThenReallocGrowsMemoryInPlace(void)
|
||||||
|
{
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
|
||||||
|
void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9);
|
||||||
|
free(n);
|
||||||
|
TEST_ASSERT_NOT_NULL(m);
|
||||||
|
TEST_ASSERT_EQUAL(m, n);
|
||||||
|
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ReallocFailDoesNotFreeMem(void)
|
||||||
|
{
|
||||||
|
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||||
|
void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
|
||||||
|
void* n1 = malloc(10);
|
||||||
|
void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
|
||||||
|
void* n2 = malloc(10);
|
||||||
|
|
||||||
|
free(n2);
|
||||||
|
if (out_of_mem == NULL) free(n1);
|
||||||
|
free(m);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(m); /* Got a real memory location */
|
||||||
|
TEST_ASSERT_NULL(out_of_mem); /* The realloc should have failed */
|
||||||
|
TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */
|
||||||
|
TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2);
|
||||||
|
#else
|
||||||
|
TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
49
extras/memory/test/unity_memory_TestRunner.c
Normal file
49
extras/memory/test/unity_memory_TestRunner.c
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/* ==========================================
|
||||||
|
* Unity Project - A Test Framework for C
|
||||||
|
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
|
* [Released under MIT License. Please refer to license.txt for details]
|
||||||
|
* ========================================== */
|
||||||
|
|
||||||
|
#include "unity.h"
|
||||||
|
#include "unity_memory.h"
|
||||||
|
|
||||||
|
extern void test_ForceMallocFail(void);
|
||||||
|
extern void test_ReallocSmallerIsUnchanged(void);
|
||||||
|
extern void test_ReallocSameIsUnchanged(void);
|
||||||
|
extern void test_ReallocLargerNeeded(void);
|
||||||
|
extern void test_ReallocNullPointerIsLikeMalloc(void);
|
||||||
|
extern void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void);
|
||||||
|
extern void test_CallocFillsWithZero(void);
|
||||||
|
extern void test_FreeNULLSafety(void);
|
||||||
|
extern void test_DetectsLeak(void);
|
||||||
|
extern void test_BufferOverrunFoundDuringFree(void);
|
||||||
|
extern void test_BufferOverrunFoundDuringRealloc(void);
|
||||||
|
extern void test_BufferGuardWriteFoundDuringFree(void);
|
||||||
|
extern void test_BufferGuardWriteFoundDuringRealloc(void);
|
||||||
|
extern void test_MallocPastBufferFails(void);
|
||||||
|
extern void test_CallocPastBufferFails(void);
|
||||||
|
extern void test_MallocThenReallocGrowsMemoryInPlace(void);
|
||||||
|
extern void test_ReallocFailDoesNotFreeMem(void);
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
UnityBegin("unity_memory_Test.c");
|
||||||
|
RUN_TEST(test_ForceMallocFail);
|
||||||
|
RUN_TEST(test_ReallocSmallerIsUnchanged);
|
||||||
|
RUN_TEST(test_ReallocSameIsUnchanged);
|
||||||
|
RUN_TEST(test_ReallocLargerNeeded);
|
||||||
|
RUN_TEST(test_ReallocNullPointerIsLikeMalloc);
|
||||||
|
RUN_TEST(test_ReallocSizeZeroFreesMemAndReturnsNullPointer);
|
||||||
|
RUN_TEST(test_CallocFillsWithZero);
|
||||||
|
RUN_TEST(test_FreeNULLSafety);
|
||||||
|
RUN_TEST(test_DetectsLeak);
|
||||||
|
RUN_TEST(test_BufferOverrunFoundDuringFree);
|
||||||
|
RUN_TEST(test_BufferOverrunFoundDuringRealloc);
|
||||||
|
RUN_TEST(test_BufferGuardWriteFoundDuringFree);
|
||||||
|
RUN_TEST(test_BufferGuardWriteFoundDuringRealloc);
|
||||||
|
RUN_TEST(test_MallocPastBufferFails);
|
||||||
|
RUN_TEST(test_CallocPastBufferFails);
|
||||||
|
RUN_TEST(test_MallocThenReallocGrowsMemoryInPlace);
|
||||||
|
RUN_TEST(test_ReallocFailDoesNotFreeMem);
|
||||||
|
return UnityEnd();
|
||||||
|
}
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
/* ==========================================
|
||||||
* ==========================================
|
|
||||||
* Unity Project - A Test Framework for C
|
* Unity Project - A Test Framework for C
|
||||||
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
* [Released under MIT License. Please refer to license.txt for details]
|
* [Released under MIT License. Please refer to license.txt for details]
|
||||||
* ========================================== */
|
* ========================================== */
|
||||||
|
|
||||||
|
#include "unity.h"
|
||||||
#include "unity_output_Spy.h"
|
#include "unity_output_Spy.h"
|
||||||
#include "unity_fixture.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
static int size;
|
static int size;
|
||||||
static int count;
|
static int count;
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
/* Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
/* ==========================================
|
||||||
* ==========================================
|
|
||||||
* Unity Project - A Test Framework for C
|
* Unity Project - A Test Framework for C
|
||||||
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
* Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||||
* [Released under MIT License. Please refer to license.txt for details]
|
* [Released under MIT License. Please refer to license.txt for details]
|
||||||
* ========================================== */
|
* ========================================== */
|
||||||
|
|
||||||
#ifndef D_unity_output_Spy_H
|
#ifndef UNITY_OUTPUT_SPY_H
|
||||||
#define D_unity_output_Spy_H
|
#define UNITY_OUTPUT_SPY_H
|
||||||
|
|
||||||
void UnityOutputCharSpy_Create(int s);
|
void UnityOutputCharSpy_Create(int s);
|
||||||
void UnityOutputCharSpy_Destroy(void);
|
void UnityOutputCharSpy_Destroy(void);
|
||||||
Reference in New Issue
Block a user