From e067b442a38205b0f96c30e61e6557d84b3a96ac Mon Sep 17 00:00:00 2001 From: mvandervoord Date: Tue, 4 Jan 2011 20:08:32 +0000 Subject: [PATCH] - updates to fixture in extras (submitted by James Grenning) git-svn-id: http://unity.svn.sourceforge.net/svnroot/unity/trunk@111 e7d17a6e-8845-0410-bbbc-c8efb4fdad7e --- extras/fixture/build/MakefileWorker.mk | 331 +++++++++++++++++++++++ extras/fixture/build/filterGcov.sh | 61 +++++ extras/fixture/{test => main}/AllTests.c | 0 extras/fixture/rakefile_helper.rb | 7 +- extras/fixture/src/unity_fixture.c | 32 ++- extras/fixture/test/unity_fixture_Test.c | 6 +- 6 files changed, 422 insertions(+), 15 deletions(-) create mode 100644 extras/fixture/build/MakefileWorker.mk create mode 100644 extras/fixture/build/filterGcov.sh rename extras/fixture/{test => main}/AllTests.c (100%) diff --git a/extras/fixture/build/MakefileWorker.mk b/extras/fixture/build/MakefileWorker.mk new file mode 100644 index 0000000..9948751 --- /dev/null +++ b/extras/fixture/build/MakefileWorker.mk @@ -0,0 +1,331 @@ +#--------- +# +# MakefileWorker.mk +# +# Include this helper file in your makefile +# It makes +# A static library holding the application objs +# A test executable +# +# See this example for parameter settings +# examples/Makefile +# +#---------- +# Inputs - these variables describe what to build +# +# INCLUDE_DIRS - Directories used to search for include files. +# This generates a -I for each directory +# SRC_DIRS - Directories containing source file to built into the library +# SRC_FILES - Specific source files to build into library. Helpful when not all code +# in a directory can be built for test (hopefully a temporary situation) +# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner +# These do not go in a library. They are explicitly included in the test runner +#---------- +# You can adjust these variables to influence how to build the test target +# and where to put and name outputs +# See below to determine defaults +# COMPONENT_NAME - the name of the thing being built +# UNITY_HOME - where Unity home dir found +# UNITY_BUILD_HOME - place for scripts +# UNITY_OBJS_DIR - a directory where o and d files go +# UNITY_LIB_DIR - a directory where libs go +# UNITY_ENABLE_DEBUG - build for debug +# UNITY_USE_MEM_LEAK_DETECTION - Links with overridden new and delete +# UNITY_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out +# of the test harness +# UNITY_USE_GCOV - Turn on coverage analysis +# Clean then build with this flag set to Y, then 'make gcov' +# UNITY_TEST_RUNNER_FLAGS +# None by default +# UNITY_MAPFILE - generate a map file +# UNITY_WARNINGFLAGS - overly picky by default +# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make +# other targets. Like CSlim, which is part of fitnesse +#---------- +# +# Other flags users can initialize to sneak in their settings +# UNITY_CFLAGS - C complier +# UNITY_LDFLAGS - Linker flags +#---------- + + +ifndef COMPONENT_NAME + COMPONENT_NAME = name_this_in_the_makefile +endif + +# Debug on by default +ifndef UNITY_ENABLE_DEBUG + UNITY_ENABLE_DEBUG = Y +endif + +# new and delete for memory leak detection on by default +ifndef UNITY_USE_MEM_LEAK_DETECTION + UNITY_USE_MEM_LEAK_DETECTION = Y +endif + +# Use gcov, off by default +ifndef UNITY_USE_GCOV + UNITY_USE_GCOV = N +endif + +# Default warnings +ifndef UNITY_WARNINGFLAGS + UNITY_WARNINGFLAGS = -Wall -Werror -Wshadow -Wswitch-default +endif + +# Default dir for temporary files (d, o) +ifndef UNITY_OBJS_DIR + UNITY_OBJS_DIR = objs +endif + +# Default dir for the outout library +ifndef UNITY_LIB_DIR + UNITY_LIB_DIR = lib +endif + +# No map by default +ifndef UNITY_MAP_FILE + UNITY_MAP_FILE = N +endif + +#Not verbose by deafult +ifdef VERBOSE + UNITY_TEST_RUNNER_FLAGS += -v +endif + +ifdef GROUP + UNITY_TEST_RUNNER_FLAGS += -g $(GROUP) +endif + +ifdef NAME + UNITY_TEST_RUNNER_FLAGS += -n $(NAME) +endif + +ifdef REPEAT + UNITY_TEST_RUNNER_FLAGS += -r $(REPEAT) +endif + + +# -------------------------------------- +# derived flags in the following area +# -------------------------------------- +ifeq ($(UNITY_USE_MEM_LEAK_DETECTION), N) + UNITY_CFLAGS += -DUNITY_MEM_LEAK_DETECTION_DISABLED +else + UNITY_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(UNITY_HOME)/extras/fixture/src/unity_fixture_malloc_overrides.h +endif + +ifeq ($(UNITY_ENABLE_DEBUG), Y) + UNITY_CFLAGS += -g +endif + +ifeq ($(UNITY_USE_GCOV), Y) + UNITY_CFLAGS += -fprofile-arcs -ftest-coverage +endif + +UNITY_CFLAGS += $(UNITY_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) + +TARGET_MAP = $(COMPONENT_NAME).map.txt +ifeq ($(UNITY_MAP_FILE), Y) + UNITY_LDFLAGS += -Wl,-map,$(TARGET_MAP) +endif + +LD_LIBRARIES += -lgcov + +TARGET_LIB = \ + $(UNITY_LIB_DIR)/lib$(COMPONENT_NAME).a + +TEST_TARGET = \ + $(COMPONENT_NAME)_tests + +#Helper Functions +get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.c) +get_dirs_from_dirspec = $(wildcard $1) +get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) +__src_to = $(subst .c,$1, $(subst .cpp,$1,$2)) +src_to = $(addprefix $(UNITY_OBJS_DIR)/,$(call __src_to,$1,$2)) +src_to_o = $(call src_to,.o,$1) +src_to_d = $(call src_to,.d,$1) +src_to_gcda = $(call src_to,.gcda,$1) +src_to_gcno = $(call src_to,.gcno,$1) +make_dotdot_a_subdir = $(subst ..,_dot_dot, $1) +time = $(shell date +%s) +delta_t = $(eval minus, $1, $2) +debug_print_list = $(foreach word,$1,echo " $(word)";) echo; + +#Derived +STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) + +SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) +OBJ = $(call src_to_o,$(SRC)) +OBJ2 = $(call make_dotdot_a_subdir. $(OBJ)) + +STUFF_TO_CLEAN += $(OBJ) + +TEST_SRC = $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) +TEST_OBJS = $(call src_to_o,$(TEST_SRC)) +STUFF_TO_CLEAN += $(TEST_OBJS) + + +MOCKS_SRC = $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) +MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) +STUFF_TO_CLEAN += $(MOCKS_OBJS) + +ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) + +#Test coverage with gcov +GCOV_OUTPUT = gcov_output.txt +GCOV_REPORT = gcov_report.txt +GCOV_ERROR = gcov_error.txt +GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) +GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) +TEST_OUTPUT = $(TEST_TARGET).txt +STUFF_TO_CLEAN += \ + $(GCOV_OUTPUT)\ + $(GCOV_REPORT)\ + $(GCOV_REPORT).html\ + $(GCOV_ERROR)\ + $(GCOV_GCDA_FILES)\ + $(GCOV_GCNO_FILES)\ + $(TEST_OUTPUT) + + +#The gcda files for gcov need to be deleted before each run +#To avoid annoying messages. +GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) +RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(UNITY_TEST_RUNNER_FLAGS) + +INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) +INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) +MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) +INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) + + +DEP_FILES = $(call src_to_d, $(ALL_SRC)) +STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) +STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output + +# We'll use the UNITY_CFLAGS etc so that you can override AND add to the CppUTest flags +CFLAGS = $(UNITY_CFLAGS) $(UNITY_ADDITIONAL_CFLAGS) $(INCLUDES) $(UNITY_WARNINGFLAGS) +LDFLAGS = $(UNITY_LDFLAGS) $(UNITY_ADDITIONAL_LDFLAGS) + +# Targets + +.PHONY: all +all: start $(TEST_TARGET) + $(RUN_TEST_TARGET) + +.PHONY: start +start: $(TEST_TARGET) + $(SILENCE)START_TIME=$(call time) + +.PHONY: all_no_tests +all_no_tests: $(TEST_TARGET) + +.PHONY: flags +flags: + @echo + @echo "Compile C source with CFLAGS:" + @$(call debug_print_list,$(CFLAGS)) + @echo "Link with LDFLAGS:" + @$(call debug_print_list,$(LDFLAGS)) + @echo "Link with LD_LIBRARIES:" + @$(call debug_print_list,$(LD_LIBRARIES)) + @echo "Create libraries with ARFLAGS:" + @$(call debug_print_list,$(ARFLAGS)) + @echo "OBJ files:" + @$(call debug_print_list,$(OBJ2)) + + +$(TEST_TARGET): $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(STDLIB_CODE_START) + $(SILENCE)echo Linking $@ + $(SILENCE)$(LINK.o) -o $@ $^ $(LD_LIBRARIES) + +$(TARGET_LIB): $(OBJ) + $(SILENCE)echo Building archive $@ + $(SILENCE)mkdir -p lib + $(SILENCE)$(AR) $(ARFLAGS) $@ $^ + $(SILENCE)ranlib $@ + +test: $(TEST_TARGET) + $(RUN_TEST_TARGET) | tee $(TEST_OUTPUT) + +vtest: $(TEST_TARGET) + $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) + +$(UNITY_OBJS_DIR)/%.o: %.cpp + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) -MMD -MP $(OUTPUT_OPTION) $< + +$(UNITY_OBJS_DIR)/%.o: %.c + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.c) -MMD -MP $(OUTPUT_OPTION) $< + +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEP_FILES) +endif + +.PHONY: clean +clean: + $(SILENCE)echo Making clean + $(SILENCE)$(RM) $(STUFF_TO_CLEAN) + $(SILENCE)rm -rf gcov $(UNITY_OBJS_DIR) + $(SILENCE)find . -name "*.gcno" | xargs rm -f + $(SILENCE)find . -name "*.gcda" | xargs rm -f + +#realclean gets rid of all gcov, o and d files in the directory tree +#not just the ones made by this makefile +.PHONY: realclean +realclean: clean + $(SILENCE)rm -rf gcov + $(SILENCE)find . -name "*.gdcno" | xargs rm -f + $(SILENCE)find . -name "*.[do]" | xargs rm -f + +gcov: test + $(SILENCE)for d in $(SRC_DIRS) ; do \ + gcov --object-directory $(UNITY_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done + $(SILENCE)for f in $(SRC_FILES) ; do \ + gcov --object-directory $(UNITY_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done + $(UNITY_BUILD_HOME)/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + $(SILENCE)cat $(GCOV_REPORT) + $(SILENCE)mkdir -p gcov + $(SILENCE)mv *.gcov gcov + $(SILENCE)mv gcov_* gcov + $(SILENCE)echo "See gcov directory for details" + +debug: + @echo + @echo "Target Source files:" + @$(call debug_print_list,$(SRC)) + @echo "Target Object files:" + @$(call debug_print_list,$(OBJ)) + @echo "Test Source files:" + @$(call debug_print_list,$(TEST_SRC)) + @echo "Test Object files:" + @$(call debug_print_list,$(TEST_OBJS)) + @echo "Mock Source files:" + @$(call debug_print_list,$(MOCKS_SRC)) + @echo "Mock Object files:" + @$(call debug_print_list,$(MOCKS_OBJS)) + @echo "All Input Dependency files:" + @$(call debug_print_list,$(DEP_FILES)) + @echo Stuff to clean: + @$(call debug_print_list,$(STUFF_TO_CLEAN)) + @echo Includes: + @$(call debug_print_list,$(INCLUDES)) + +ifneq "$(OTHER_MAKEFILE_TO_INCLUDE)" "" +-include $(OTHER_MAKEFILE_TO_INCLUDE) +endif + + + +st,$(TEST_SRC)) + @echo "Test Object files:" + @$(call debug_print \ No newline at end of file diff --git a/extras/fixture/build/filterGcov.sh b/extras/fixture/build/filterGcov.sh new file mode 100644 index 0000000..a861cf6 --- /dev/null +++ b/extras/fixture/build/filterGcov.sh @@ -0,0 +1,61 @@ +#!/bin/bash +INPUT_FILE=$1 +TEMP_FILE1=${INPUT_FILE}1.tmp +TEMP_FILE2=${INPUT_FILE}2.tmp +TEMP_FILE3=${INPUT_FILE}3.tmp +ERROR_FILE=$2 +OUTPUT_FILE=$3 +HTML_OUTPUT_FILE=$3.html +TEST_RESULTS=$4 + +flattenGcovOutput() { +while read line1 +do + read line2 + echo $line2 " " $line1 + read junk + read junk +done < ${INPUT_FILE} +} + +getRidOfCruft() { +sed '-e s/^Lines.*://g' \ + '-e s/^[0-9]\./ &/g' \ + '-e s/^[0-9][0-9]\./ &/g' \ + '-e s/of.*File/ /g' \ + "-e s/'//g" \ + '-e s/^.*\/usr\/.*$//g' \ + '-e s/^.*\.$//g' +} + +getFileNameRootFromErrorFile() { +sed '-e s/gc..:cannot open .* file//g' ${ERROR_FILE} +} + +writeEachNoTestCoverageFile() { +while read line +do + echo " 0.00% " ${line} +done +} + +createHtmlOutput() { + echo "" + echo "" + sed "-e s/.*% /
CoverageFile
&<\/td>/" \ + "-e s/[a-zA-Z0-9_]*\.[ch][a-z]*/&<\/a><\/td><\/tr>/" + echo "
" + sed "-e s/.*/&
/g" < ${TEST_RESULTS} +} + + +flattenGcovOutput | getRidOfCruft > ${TEMP_FILE1} +getFileNameRootFromErrorFile | writeEachNoTestCoverageFile > ${TEMP_FILE2} +cat ${TEMP_FILE1} ${TEMP_FILE2} | sort | uniq > ${OUTPUT_FILE} +createHtmlOutput < ${OUTPUT_FILE} > ${HTML_OUTPUT_FILE} +rm -f ${TEMP_FILE1} ${TEMP_FILE2} +erageFile" + sed "-e s/.*% /&<\/td>/" \ + "-e s/[a-zA-Z0-9_]*\.[ch][a-z]*/&<\/a><\/td><\/tr>/" + echo "" + sed "-e s/.*/&
/g" < ${TEST_RESULTS \ No newline at end of file diff --git a/extras/fixture/test/AllTests.c b/extras/fixture/main/AllTests.c similarity index 100% rename from extras/fixture/test/AllTests.c rename to extras/fixture/main/AllTests.c diff --git a/extras/fixture/rakefile_helper.rb b/extras/fixture/rakefile_helper.rb index 01a5d66..c30f9a2 100644 --- a/extras/fixture/rakefile_helper.rb +++ b/extras/fixture/rakefile_helper.rb @@ -24,7 +24,11 @@ module RakefileHelpers end def configure_clean - CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? + unless $cfg['compiler']['build_path'].nil? + CLEAN.include($cfg['compiler']['build_path'] + "*#{$cfg['compiler']['object_files']['extension']}") + CLEAN.include($cfg['compiler']['build_path'] + "*#{$cfg['linker']['bin_files']['extension']}") + CLEAN.include($cfg['compiler']['build_path'] + "*.test*") + end end def configure_toolchain(config_file=DEFAULT_CONFIG_FILE) @@ -147,6 +151,7 @@ module RakefileHelpers # Get a list of all source files needed src_files = Dir[HERE+'src/*.c'] + src_files += Dir[HERE+'main/*.c'] src_files += Dir[HERE+'test/*.c'] src_files << '../../src/Unity.c' diff --git a/extras/fixture/src/unity_fixture.c b/extras/fixture/src/unity_fixture.c index d4c6e82..5d56db1 100644 --- a/extras/fixture/src/unity_fixture.c +++ b/extras/fixture/src/unity_fixture.c @@ -186,18 +186,32 @@ void * unity_malloc(size_t size) return (void*)mem; } -void unity_free(void * mem) +static int isOverrun(void * mem) { Guard* guard = (Guard*)mem; char* memAsChar = (char*)mem; guard--; - if (strcmp(&memAsChar[guard->size], end) != 0) + + return strcmp(&memAsChar[guard->size], end) != 0; +} + +static void release_memory(void * mem) +{ + Guard* guard = (Guard*)mem; + guard--; + + malloc_count--; + free(guard); +} + +void unity_free(void * mem) +{ + int overrun = isOverrun(mem);//strcmp(&memAsChar[guard->size], end) != 0; + release_memory(mem); + if (overrun) { TEST_FAIL_MESSAGE("Buffer overrun detected during free()"); } - - malloc_count--; - free((void*)guard); } void* unity_calloc(size_t num, size_t size) @@ -210,21 +224,22 @@ void* unity_calloc(size_t num, size_t size) void* unity_realloc(void * oldMem, size_t size) { Guard* guard = (Guard*)oldMem; - char* memAsChar = (char*)oldMem; +// char* memAsChar = (char*)oldMem; void* newMem; if (oldMem == 0) return unity_malloc(size); guard--; - if (strcmp(&memAsChar[guard->size], end) != 0) + if (isOverrun(oldMem)) { + release_memory(oldMem); TEST_FAIL_MESSAGE("Buffer overrun detected during realloc()"); } if (size == 0) { - unity_free(oldMem); + release_memory(oldMem); return 0; } @@ -356,4 +371,3 @@ void UnityConcludeFixtureTest() Unity.CurrentTestFailed = 0; Unity.CurrentTestIgnored = 0; } - diff --git a/extras/fixture/test/unity_fixture_Test.c b/extras/fixture/test/unity_fixture_Test.c index 7cb86a4..2ff8a87 100644 --- a/extras/fixture/test/unity_fixture_Test.c +++ b/extras/fixture/test/unity_fixture_Test.c @@ -285,7 +285,6 @@ TEST(LeakDetection, DetectsLeak) UnityOutputCharSpy_Enable(1); EXPECT_ABORT_BEGIN UnityMalloc_EndTest(); - UnityPointer_UndoAllSets(); EXPECT_ABORT_END UnityOutputCharSpy_Enable(0); CHECK(strstr(UnityOutputCharSpy_Get(), "This test leaks!")); @@ -303,7 +302,6 @@ TEST(LeakDetection, BufferOverrunFoundDuringFree) free(m); EXPECT_ABORT_END UnityOutputCharSpy_Enable(0); - UnityPointer_UndoAllSets(); CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()")); Unity.CurrentTestFailed = 0; } @@ -318,8 +316,6 @@ TEST(LeakDetection, BufferOverrunFoundDuringRealloc) m = realloc(m, 100); EXPECT_ABORT_END UnityOutputCharSpy_Enable(0); - UnityPointer_UndoAllSets(); CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()")); - free(m); Unity.CurrentTestFailed = 0; -} +} \ No newline at end of file