From 2593c31bb7e69219deaffd360d90def3711bce8f Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 13 Sep 2017 17:59:52 -0400 Subject: [PATCH 1/5] Allow suiteSetUp() and suiteTearDown() to be provided as normal C functions. This is simpler and more flexible than embedding C code in the Ruby options (:suite_setup and :suite_teardown). However, support for :suite_setup and :suite_teardown is kept for backwards compatibility. Several configurations are possible: 1. :suite_setup and :suite_teardown options provided and used. 2. :suite_setup and :suite_teardown options not provided (nil): 2a. Weak symbols not supported; suiteSetUp() and suiteTearDown() are not called. It would be simpler to make user-provided functions mandatory in this case, but it could break some pre-existing test suites. 2b. Weak symbols are supported and the stub implementations of suiteSetUp() and suiteTearDown() are called if there are no user-provided functions. 2c. Weak symbols are supported but overridden by user-provided suiteSetUp() and suiteTearDown() functions. --- auto/generate_test_runner.rb | 30 ++++++++++++++++++++++-------- src/unity.c | 6 ++++++ src/unity.h | 11 +++++++++++ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 07bde81..edb7989 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -235,22 +235,36 @@ class UnityTestRunnerGenerator end def create_suite_setup(output) - return if @options[:suite_setup].nil? - output.puts("\n/*=======Suite Setup=====*/") output.puts('static void suite_setup(void)') output.puts('{') - output.puts(@options[:suite_setup]) + if @options[:suite_setup].nil? + # New style, call suiteSetUp() if we can use weak symbols + output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)') + output.puts(' suiteSetUp();') + output.puts('#endif') + else + # Old style, C code embedded in the :suite_setup option + output.puts(@options[:suite_setup]) + end output.puts('}') end def create_suite_teardown(output) - return if @options[:suite_teardown].nil? - output.puts("\n/*=======Suite Teardown=====*/") output.puts('static int suite_teardown(int num_failures)') output.puts('{') - output.puts(@options[:suite_teardown]) + if @options[:suite_teardown].nil? + # New style, call suiteTearDown() if we can use weak symbols + output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)') + output.puts(' return suiteTearDown(num_failures);') + output.puts('#else') + output.puts(' return num_failures;') + output.puts('#endif') + else + # Old style, C code embedded in the :suite_teardown option + output.puts(@options[:suite_teardown]) + end output.puts('}') end @@ -342,7 +356,7 @@ class UnityTestRunnerGenerator output.puts("int #{main_name}(void)") output.puts('{') end - output.puts(' suite_setup();') unless @options[:suite_setup].nil? + output.puts(' suite_setup();') output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");") if @options[:use_param_tests] tests.each do |test| @@ -357,7 +371,7 @@ class UnityTestRunnerGenerator end output.puts output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty? - output.puts(" return #{@options[:suite_teardown].nil? ? '' : 'suite_teardown'}(UnityEnd());") + output.puts(" return suite_teardown(UnityEnd());") output.puts('}') end diff --git a/src/unity.c b/src/unity.c index 9783efa..08ecf63 100644 --- a/src/unity.c +++ b/src/unity.c @@ -1314,11 +1314,17 @@ void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) #if defined(UNITY_WEAK_ATTRIBUTE) UNITY_WEAK_ATTRIBUTE void setUp(void) { } UNITY_WEAK_ATTRIBUTE void tearDown(void) { } + UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { } + UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; } #elif defined(UNITY_WEAK_PRAGMA) #pragma weak setUp void setUp(void) { } #pragma weak tearDown void tearDown(void) { } + #pragma weak suiteSetUp + void suiteSetUp(void) { } + #pragma weak suiteTearDown + int suiteTearDown(int num_failures) { return num_failures; } #endif /*-----------------------------------------------*/ diff --git a/src/unity.h b/src/unity.h index 258e21c..1fa8b94 100644 --- a/src/unity.h +++ b/src/unity.h @@ -15,9 +15,20 @@ extern "C" #include "unity_internals.h" +/* These functions are intended to be called before and after each test. Unity + * provides stub implementations annotated as weak symbols (if supported by the + * compiler). */ void setUp(void); void tearDown(void); +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). Unity + * provides stub implementations annotated as weak symbols (if supported by the + * compiler). */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + /*------------------------------------------------------- * Configuration Options *------------------------------------------------------- From 1381a1a4cbf1f48ed582466d00fab3b14e8e8abd Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 13 Sep 2017 18:24:07 -0400 Subject: [PATCH 2/5] Update documentation. --- docs/UnityHelperScriptsGuide.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/UnityHelperScriptsGuide.md b/docs/UnityHelperScriptsGuide.md index 3a93009..4242990 100644 --- a/docs/UnityHelperScriptsGuide.md +++ b/docs/UnityHelperScriptsGuide.md @@ -124,7 +124,7 @@ demonstrates using a Ruby hash. ##### `:includes` -This option specifies an array of file names to be ?#include?'d at the top of +This option specifies an array of file names to be `#include`'d at the top of your runner C file. You might use it to reference custom types or anything else universally needed in your generated runners. @@ -133,11 +133,23 @@ universally needed in your generated runners. Define this option with C code to be executed _before any_ test cases are run. +Alternatively, if your C compiler supports weak symbols, you can leave this +option unset and instead provide a `void suiteSetUp(void)` function in your test +suite. The linker will look for this symbol and fall back to a Unity-provided +stub if it is not found. + ##### `:suite_teardown` -Define this option with C code to be executed ?after all?test cases have -finished. +Define this option with C code to be executed _after all_ test cases have +finished. An integer variable `num_failures` is available for diagnostics. +The code should end with a `return` statement; the value returned will become +the exit code of `main`. You can normally just return `num_failures`. + +Alternatively, if your C compiler supports weak symbols, you can leave this +option unset and instead provide a `int suiteTearDown(int num_failures)` +function in your test suite. The linker will look for this symbol and fall +back to a Unity-provided stub if it is not found. ##### `:enforce_strict_ordering` From a7e8797e0cabd738cb4cfcc54ce4348b3522f2d1 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Mon, 9 Oct 2017 10:49:58 -0400 Subject: [PATCH 3/5] Fix link errors with MinGW. MinGW supports a limited form of weak symbols, with the restriction that weak/default implementations need to be defined in the same translation unit they are called from. Strong/overriding symbols may of course be specified in a different translation unit. --- auto/generate_test_runner.rb | 1 + src/unity.c | 18 +----------------- src/unity_setup.h | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 src/unity_setup.h diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index edb7989..f436634 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -158,6 +158,7 @@ class UnityTestRunnerGenerator create_runtest(output, mocks) output.puts("\n/*=======Automagically Detected Files To Include=====*/") output.puts("#include \"#{@options[:framework]}.h\"") + output.puts("#include \"#{@options[:framework]}_setup.h\"") output.puts('#include "cmock.h"') unless mocks.empty? output.puts('#include ') output.puts('#include ') diff --git a/src/unity.c b/src/unity.c index 08ecf63..739358f 100644 --- a/src/unity.c +++ b/src/unity.c @@ -5,6 +5,7 @@ ============================================================================ */ #include "unity.h" +#include "unity_setup.h" #include /* If omitted from header, declare overrideable prototypes here so they're ready for use */ @@ -1310,23 +1311,6 @@ void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) UNITY_IGNORE_AND_BAIL; } -/*-----------------------------------------------*/ -#if defined(UNITY_WEAK_ATTRIBUTE) - UNITY_WEAK_ATTRIBUTE void setUp(void) { } - UNITY_WEAK_ATTRIBUTE void tearDown(void) { } - UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { } - UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; } -#elif defined(UNITY_WEAK_PRAGMA) - #pragma weak setUp - void setUp(void) { } - #pragma weak tearDown - void tearDown(void) { } - #pragma weak suiteSetUp - void suiteSetUp(void) { } - #pragma weak suiteTearDown - int suiteTearDown(int num_failures) { return num_failures; } -#endif - /*-----------------------------------------------*/ void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) { diff --git a/src/unity_setup.h b/src/unity_setup.h new file mode 100644 index 0000000..4672b76 --- /dev/null +++ b/src/unity_setup.h @@ -0,0 +1,33 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_SETUP_H +#define UNITY_SETUP_H + +#include "unity_internals.h" + +/* On some platforms (MinGW for example), weak function implementations + * need to be in the same translation unit they are called from. This + * header can be included to provide implementations of setUp(), tearDown(), + * suiteSetUp(), and suiteTearDown(). */ + +#if defined(UNITY_WEAK_ATTRIBUTE) + UNITY_WEAK_ATTRIBUTE void setUp(void) { } + UNITY_WEAK_ATTRIBUTE void tearDown(void) { } + UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { } + UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; } +#elif defined(UNITY_WEAK_PRAGMA) + #pragma weak setUp + void setUp(void) { } + #pragma weak tearDown + void tearDown(void) { } + #pragma weak suiteSetUp + void suiteSetUp(void) { } + #pragma weak suiteTearDown + int suiteTearDown(int num_failures) { return num_failures; } +#endif + +#endif From df78aade4bdf78e34f35d6aedeb79e55411a9b62 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Mon, 9 Oct 2017 11:38:08 -0400 Subject: [PATCH 4/5] Make weak symbol usage more portable: - Enable support for Green Hills Software compiler - Define weak implementations only once except on Windows --- auto/generate_test_runner.rb | 2 ++ src/unity_internals.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index f436634..b049bca 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -158,7 +158,9 @@ class UnityTestRunnerGenerator create_runtest(output, mocks) output.puts("\n/*=======Automagically Detected Files To Include=====*/") output.puts("#include \"#{@options[:framework]}.h\"") + output.puts('#ifdef __WIN32__') output.puts("#include \"#{@options[:framework]}_setup.h\"") + output.puts('#endif') output.puts('#include "cmock.h"') unless mocks.empty? output.puts('#include ') output.puts('#include ') diff --git a/src/unity_internals.h b/src/unity_internals.h index 1b57cd0..4761253 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -301,7 +301,7 @@ extern void UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION; * Language Features Available *-------------------------------------------------------*/ #if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) -# ifdef __GNUC__ /* includes clang */ +# if defined(__GNUC__) || defined(__ghs__) /* __GNUC__ includes clang */ # if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__) # define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) # endif From 629b86d5412e3a6768987610c67172de0eff538d Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 1 Nov 2017 11:36:26 -0400 Subject: [PATCH 5/5] Merge unity_setup.h into unity.h. --- auto/generate_test_runner.rb | 4 ++-- src/unity.c | 2 +- src/unity.h | 35 +++++++++++++++++++++++++++++------ src/unity_setup.h | 33 --------------------------------- 4 files changed, 32 insertions(+), 42 deletions(-) delete mode 100644 src/unity_setup.h diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index b049bca..344a2d0 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -157,10 +157,10 @@ class UnityTestRunnerGenerator output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') create_runtest(output, mocks) output.puts("\n/*=======Automagically Detected Files To Include=====*/") - output.puts("#include \"#{@options[:framework]}.h\"") output.puts('#ifdef __WIN32__') - output.puts("#include \"#{@options[:framework]}_setup.h\"") + output.puts('#define UNITY_INCLUDE_SETUP_STUBS') output.puts('#endif') + output.puts("#include \"#{@options[:framework]}.h\"") output.puts('#include "cmock.h"') unless mocks.empty? output.puts('#include ') output.puts('#include ') diff --git a/src/unity.c b/src/unity.c index 739358f..ab1e2fd 100644 --- a/src/unity.c +++ b/src/unity.c @@ -4,8 +4,8 @@ [Released under MIT License. Please refer to license.txt for details] ============================================================================ */ +#define UNITY_INCLUDE_SETUP_STUBS #include "unity.h" -#include "unity_setup.h" #include /* If omitted from header, declare overrideable prototypes here so they're ready for use */ diff --git a/src/unity.h b/src/unity.h index 1fa8b94..d95f1c1 100644 --- a/src/unity.h +++ b/src/unity.h @@ -15,20 +15,43 @@ extern "C" #include "unity_internals.h" -/* These functions are intended to be called before and after each test. Unity - * provides stub implementations annotated as weak symbols (if supported by the - * compiler). */ +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. */ void setUp(void); void tearDown(void); /* These functions are intended to be called at the beginning and end of an * entire test suite. suiteTearDown() is passed the number of tests that - * failed, and its return value becomes the exit code of main(). Unity - * provides stub implementations annotated as weak symbols (if supported by the - * compiler). */ + * failed, and its return value becomes the exit code of main(). */ void suiteSetUp(void); int suiteTearDown(int num_failures); +/* If the compiler supports it, the following block provides stub + * implementations of the above functions as weak symbols. Note that on + * some platforms (MinGW for example), weak function implementations need + * to be in the same translation unit they are called from. This can be + * achieved by defining UNITY_INCLUDE_SETUP_STUBS before including unity.h. */ +#ifdef UNITY_INCLUDE_SETUP_STUBS + #ifdef UNITY_WEAK_ATTRIBUTE + UNITY_WEAK_ATTRIBUTE void setUp(void) { } + UNITY_WEAK_ATTRIBUTE void tearDown(void) { } + UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { } + UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; } + #elif defined(UNITY_WEAK_PRAGMA) + #pragma weak setUp + void setUp(void) { } + #pragma weak tearDown + void tearDown(void) { } + #pragma weak suiteSetUp + void suiteSetUp(void) { } + #pragma weak suiteTearDown + int suiteTearDown(int num_failures) { return num_failures; } + #endif +#endif + /*------------------------------------------------------- * Configuration Options *------------------------------------------------------- diff --git a/src/unity_setup.h b/src/unity_setup.h deleted file mode 100644 index 4672b76..0000000 --- a/src/unity_setup.h +++ /dev/null @@ -1,33 +0,0 @@ -/* ========================================== - Unity Project - A Test Framework for C - Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams - [Released under MIT License. Please refer to license.txt for details] -========================================== */ - -#ifndef UNITY_SETUP_H -#define UNITY_SETUP_H - -#include "unity_internals.h" - -/* On some platforms (MinGW for example), weak function implementations - * need to be in the same translation unit they are called from. This - * header can be included to provide implementations of setUp(), tearDown(), - * suiteSetUp(), and suiteTearDown(). */ - -#if defined(UNITY_WEAK_ATTRIBUTE) - UNITY_WEAK_ATTRIBUTE void setUp(void) { } - UNITY_WEAK_ATTRIBUTE void tearDown(void) { } - UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { } - UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; } -#elif defined(UNITY_WEAK_PRAGMA) - #pragma weak setUp - void setUp(void) { } - #pragma weak tearDown - void tearDown(void) { } - #pragma weak suiteSetUp - void suiteSetUp(void) { } - #pragma weak suiteTearDown - int suiteTearDown(int num_failures) { return num_failures; } -#endif - -#endif