From 4d3d062b56309ab15d924b0a0f7117b733ed1c4e Mon Sep 17 00:00:00 2001 From: Mark VanderVoord Date: Tue, 21 Jun 2016 16:07:10 -0400 Subject: [PATCH] Adding command line support. Started with -n (test name matching) -x (test name exclusion). Script verification hasn't been added yet. --- auto/generate_test_runner.rb | 21 +++++-- src/unity.c | 116 +++++++++++++++++++++++++++++++++++ src/unity_internals.h | 9 +++ 3 files changed, 141 insertions(+), 5 deletions(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 85a315d..829cd4d 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -28,7 +28,9 @@ class UnityTestRunnerGenerator :test_prefix => "test|spec|should", :setup_name => "setUp", :teardown_name => "tearDown", - :main_name => "main", + :main_name => "main", #set to nil to automatically generate each time + :cmdline_args => false, + } end @@ -257,6 +259,7 @@ class UnityTestRunnerGenerator output.puts("{ \\") output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\") output.puts(" Unity.CurrentTestLineNumber = TestLineNum; \\") + output.puts(" if (UnityTestMatches()) { \\") if (@options[:cmdline_args]) output.puts(" Unity.NumberOfTests++; \\") output.puts(" CMock_Init(); \\") unless (used_mocks.empty?) output.puts(" UNITY_CLR_DETAILS(); \\") unless (used_mocks.empty?) @@ -275,6 +278,7 @@ class UnityTestRunnerGenerator output.puts(" } \\") output.puts(" CMock_Destroy(); \\") unless (used_mocks.empty?) output.puts(" UnityConcludeTest(); \\") + output.puts(" } \\") if (@options[:cmdline_args]) output.puts("}\n") end @@ -293,11 +297,18 @@ class UnityTestRunnerGenerator def create_main(output, filename, tests, used_mocks) output.puts("\n\n/*=======MAIN=====*/") - if (@options[:main_name] != "main") - output.puts("int #{@options[:main_name]}(void);") + main_name = @options[:main_name].nil? ? "main_#{filename.gsub('.c','')}" : "#{@options[:main_name]}" + if (main_name != "main") + output.puts("int #{main_name}(void);") + end + if (@options[:cmdline_args]) + output.puts("int #{main_name}(int argc, char** argv)") + output.puts("{") + output.puts(" UnityParseOptions(argc, argv);") + else + output.puts("int #{main_name}(void)") + output.puts("{") end - output.puts("int #{@options[:main_name]}(void)") - output.puts("{") output.puts(" suite_setup();") unless @options[:suite_setup].nil? output.puts(" UnityBegin(\"#{filename.gsub(/\\/,'\\\\')}\");") if (@options[:use_param_tests]) diff --git a/src/unity.c b/src/unity.c index a93bf86..e00c88c 100644 --- a/src/unity.c +++ b/src/unity.c @@ -1300,4 +1300,120 @@ int UnityEnd(void) return (int)(Unity.TestFailures); } +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_PARSE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; + +int UnityParseOptions(int argc, char** argv) +{ + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + + for (int i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch(argv[i][1]) + { + case 'l': /* list tests */ + break; + case 'n': /* include tests with name including this string */ + i++; + if (i < argc) + UnityOptionIncludeNamed = argv[i]; + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + i++; + if (i < argc) + UnityOptionExcludeNamed = argv[i]; + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_PRINT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + return 1; + } + } + } + + return 0; +} + +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + if (UnityOptionsIncludedNamed) + retval = UnityStringArgumentMatches(UnityOptionIncludedNamed); + else + retval = 1; + + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionsExcludedNamed) + if (UnityStringArgumentMatches(UnityOptionExcludedNamed)) + retval = 0; + + return retval; +} + +int UnityStringArgumentMatches(const char* str) +{ + char* ptr = (char*)str; + while (*ptr) + { + char *begin = ptr; + char *pattern = (char *)Unity.CurrentTestName; + char *prefix = (char *)Unity.TestFile; + + /* First, find out if this is the right test case */ + while (*ptr && *prefix && (*prefix == *ptr || *prefix == '.')) + { + ptr++; + prefix++; + if (*ptr == '*') + return 1; + + } + prefix++; + if (!*prefix) + { + while (*ptr && *pattern && *pattern == *ptr) + { + ptr++; + pattern++; + if (*ptr == '*') + return 1; + } + + /* If complete test name match, return true */ + if (!*pattern) + return 1; + } + + ptr = begin + 1; + } +} + +#endif /* UNITY_PARSE_COMMAND_LINE_ARGS */ /*-----------------------------------------------*/ diff --git a/src/unity_internals.h b/src/unity_internals.h index e46c7e2..6043596 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -640,6 +640,15 @@ extern const char UnityStrErr64[]; #define UNITY_UNUSED(x) (void)(sizeof(x)) +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_PARSE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + /*------------------------------------------------------- * Basic Fail and Ignore *-------------------------------------------------------*/ -- GitLab