未验证 提交 d34f7228 编写于 作者: M Mark VanderVoord 提交者: GitHub

Merge pull request #463 from ThrowTheSwitch/refactor/split_mem_from_fixture

Refactor/split mem from fixture
......@@ -24,6 +24,9 @@ script:
- cd ../extras/fixture/test && rake ci
- make -s default noStdlibMalloc
- make -s C89
- cd ../../../extras/memory/test && rake ci
- make -s default noStdlibMalloc
- make -s C89
- cd ../../../examples/example_1 && make -s ci
- cd ../example_2 && make -s ci
- cd ../example_3 && rake
......@@ -41,6 +41,7 @@ CFLAGS += -Wno-unknown-pragmas
CFLAGS += -Wstrict-prototypes
CFLAGS += -Wundef
CFLAGS += -Wold-style-definition
#CFLAGS += -Wno-misleading-indentation
TARGET_BASE1=test1
TARGET_BASE2=test2
......
......@@ -41,6 +41,7 @@ CFLAGS += -Wno-unknown-pragmas
CFLAGS += -Wstrict-prototypes
CFLAGS += -Wundef
CFLAGS += -Wold-style-definition
#CFLAGS += -Wno-misleading-indentation
TARGET_BASE1=all_tests
TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION)
......
......@@ -55,12 +55,7 @@ def build_compiler_fields
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])
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'])
end
options = squash('', $cfg['compiler']['options'])
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
......
# 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.
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.
\ No newline at end of file
......@@ -94,7 +94,6 @@ void UnityTestRunner(unityfunction* setup,
}
Unity.NumberOfTests++;
UnityMalloc_StartTest();
UnityPointer_Init();
UNITY_EXEC_TIME_START();
......@@ -111,8 +110,6 @@ void UnityTestRunner(unityfunction* setup,
if (TEST_PROTECT())
{
UnityPointer_UndoAllSets();
if (!Unity.CurrentTestFailed)
UnityMalloc_EndTest();
}
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 */
struct PointerPair
......
......@@ -10,7 +10,6 @@
#include "unity.h"
#include "unity_internals.h"
#include "unity_fixture_malloc_overrides.h"
#include "unity_fixture_internals.h"
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))
#endif
/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */
void UnityMalloc_MakeMallocFailAfterCount(int countdown);
#endif /* UNITY_FIXTURE_H_ */
......@@ -33,8 +33,6 @@ void UnityTestRunner(unityfunction* setup,
const char* file, unsigned int line);
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[]);
void UnityConcludeFixtureTest(void);
......
......@@ -5,17 +5,10 @@ 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_fixture.c \
../../../src/unity.c \
unity_fixture_Test.c \
unity_fixture_TestRunner.c \
unity_output_Spy.c \
main/AllTests.c
INC_DIR = -I../src -I../../../src/
......
......@@ -11,8 +11,6 @@ static void runAllTests(void)
{
RUN_TEST_GROUP(UnityFixture);
RUN_TEST_GROUP(UnityCommandOptions);
RUN_TEST_GROUP(LeakDetection);
RUN_TEST_GROUP(InternalMalloc);
}
int main(int argc, const char* argv[])
......
......@@ -6,7 +6,6 @@
* ========================================== */
#include "unity_fixture.h"
#include "unity_output_Spy.h"
#include <stdlib.h>
#include <string.h>
......@@ -44,71 +43,6 @@ TEST(UnityFixture, PointerSetting)
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 *p2;
......@@ -140,12 +74,10 @@ TEST(UnityFixture, ConcludeTestIncrementsFailCount)
{
UNITY_UINT savedFails = Unity.TestFailures;
UNITY_UINT savedIgnores = Unity.TestIgnores;
UnityOutputCharSpy_Enable(1);
Unity.CurrentTestFailed = 1;
UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */
Unity.CurrentTestIgnored = 1;
UnityConcludeFixtureTest(); /* Resets TestIgnored */
UnityOutputCharSpy_Enable(0);
TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures);
TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores);
Unity.TestFailures = savedFails;
......@@ -311,235 +243,3 @@ IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored)
{
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)
{
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, FreeNULLSafety);
RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount);
......@@ -37,21 +30,3 @@ TEST_GROUP_RUNNER(UnityCommandOptions)
RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters);
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);
}
# ==========================================
# 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
# ==========================================
# 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
# 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.
/* ==========================================
* 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
{
/* We know we can get away with this cast because we aligned memory already */
guard = (Guard*)(void*)(&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;
}
/* 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]
* ========================================== */
#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_
#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_
#ifndef UNITY_MEMORY_OVERRIDES_H_
#define UNITY_MEMORY_OVERRIDES_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h>
......@@ -21,17 +25,17 @@
#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.
* 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)
* For example, when using FreeRTOS UNITY_MALLOC becomes pvPortMalloc()
* and UNITY_FREE becomes vPortFree(). */
#if !defined(UNITY_MALLOC) || !defined(UNITY_FREE)
#include <stdlib.h>
#define UNITY_FIXTURE_MALLOC(size) malloc(size)
#define UNITY_FIXTURE_FREE(ptr) free(ptr)
#define UNITY_MALLOC(size) malloc(size)
#define UNITY_FREE(ptr) free(ptr)
#else
extern void* UNITY_FIXTURE_MALLOC(size_t size);
extern void UNITY_FIXTURE_FREE(void* ptr);
extern void* UNITY_MALLOC(size_t size);
extern void UNITY_FREE(void* ptr);
#endif
#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_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
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
/* ==========================================
* 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>
/* This test module includes the following tests: */
void test_ForceMallocFail(void);
void test_ReallocSmallerIsUnchanged(void);
void test_ReallocSameIsUnchanged(void);
void test_ReallocLargerNeeded(void);
void test_ReallocNullPointerIsLikeMalloc(void);
void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void);
void test_CallocFillsWithZero(void);
void test_FreeNULLSafety(void);
void test_DetectsLeak(void);
void test_BufferOverrunFoundDuringFree(void);
void test_BufferOverrunFoundDuringRealloc(void);
void test_BufferGuardWriteFoundDuringFree(void);
void test_BufferGuardWriteFoundDuringRealloc(void);
void test_MallocPastBufferFails(void);
void test_CallocPastBufferFails(void);
void test_MallocThenReallocGrowsMemoryInPlace(void);
void test_ReallocFailDoesNotFreeMem(void);
/* It makes use of the following features */
void setUp(void);
void tearDown(void);
/* Let's Go! */
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
}
/* ==========================================
* 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();
}
/* 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]
* ========================================== */
#include "unity.h"
#include "unity_output_Spy.h"
#include "unity_fixture.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int size;
static int count;
......
/* 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]
* ========================================== */
#ifndef D_unity_output_Spy_H
#define D_unity_output_Spy_H
#ifndef UNITY_OUTPUT_SPY_H
#define UNITY_OUTPUT_SPY_H
void UnityOutputCharSpy_Create(int s);
void UnityOutputCharSpy_Destroy(void);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册