ceedling 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +1 -1
  4. data/assets/tests_with_conditional_includes/src/feature_config.h +13 -0
  5. data/assets/tests_with_conditional_includes/src/feature_extra.h +13 -0
  6. data/assets/tests_with_conditional_includes/src/local_flag_extra.h +13 -0
  7. data/assets/tests_with_conditional_includes/src/nested_extra.h +13 -0
  8. data/assets/tests_with_conditional_includes/src/nested_wrapper.h +16 -0
  9. data/assets/tests_with_conditional_includes/src/project_flag_extra.h +13 -0
  10. data/assets/tests_with_conditional_includes/src/widget.c +48 -0
  11. data/assets/tests_with_conditional_includes/src/widget.h +15 -0
  12. data/assets/tests_with_conditional_includes/src/widget_feature.c +29 -0
  13. data/assets/tests_with_conditional_includes/src/widget_feature.h +13 -0
  14. data/assets/tests_with_conditional_includes/test/test_widget.c +44 -0
  15. data/assets/tests_with_conditional_includes/test/test_widget_feature.c +31 -0
  16. data/docs/Changelog.md +31 -1
  17. data/docs/mkdocs/configuration/reference/partials.md +7 -7
  18. data/examples/wondrous_forest/src/SensorHal.h +13 -0
  19. data/examples/wondrous_forest/src/TemperatureSensor.c +12 -5
  20. data/examples/wondrous_forest/src/TemperatureSensor.h +5 -4
  21. data/examples/wondrous_forest/test/TestTemperatureSensor.c +32 -3
  22. data/lib/ceedling/generators/generator_partials.rb +20 -1
  23. data/lib/ceedling/generators/generator_test_runner.rb +25 -1
  24. data/lib/ceedling/partials/partializer.rb +8 -1
  25. data/lib/ceedling/preprocess/preprocessinator.rb +22 -0
  26. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +33 -0
  27. data/lib/ceedling/test_invoker/test_build_executor.rb +3 -1
  28. data/lib/version.rb +1 -1
  29. data/site-local/configuration/reference/partials.html +11 -10
  30. data/site-local/sitemap.xml.gz +0 -0
  31. data/spec/support/system/spec_system_helper.rb +11 -0
  32. data/spec/support/system/system_context.rb +18 -9
  33. data/spec/system/conditional_include_macro_visibility_spec.rb +152 -0
  34. data/spec/system/encoding_stress_spec.rb +4 -4
  35. data/spec/system/example_wondrous_forest_spec.rb +2 -2
  36. data/spec/system/support/common_test_cases.rb +5 -1
  37. data/spec/system/test_runner_system_include_spec.rb +90 -0
  38. data/spec/units/generators/generator_partials_spec.rb +111 -8
  39. data/spec/units/generators/generator_test_runner_spec.rb +69 -0
  40. data/spec/units/partials/partializer_spec.rb +69 -0
  41. data/spec/units/preprocess/preprocessinator_includes_handler_spec.rb +61 -0
  42. data/spec/units/preprocess/preprocessinator_spec.rb +136 -0
  43. data/vendor/c_exception/lib/CException.h +1 -1
  44. data/vendor/c_exception/project.yml +2 -2
  45. data/vendor/c_exception/test/TestException.c +1 -1
  46. data/vendor/c_exception/test/support/CExceptionConfig.h +5 -11
  47. data/vendor/cmock/docs/CMockChangeLog.md +23 -22
  48. data/vendor/cmock/scripts/create_makefile.rb +4 -3
  49. data/vendor/cmock/src/cmock.h +1 -1
  50. data/vendor/cmock/vendor/c_exception/lib/CException.h +1 -1
  51. data/vendor/cmock/vendor/c_exception/project.yml +2 -2
  52. data/vendor/cmock/vendor/c_exception/test/TestException.c +1 -1
  53. data/vendor/cmock/vendor/c_exception/test/support/CExceptionConfig.h +5 -11
  54. data/vendor/cmock/vendor/unity/auto/generate_test_runner.rb +85 -29
  55. data/vendor/cmock/vendor/unity/docs/UnityChangeLog.md +1 -0
  56. data/vendor/cmock/vendor/unity/examples/unity_config.h +8 -0
  57. data/vendor/cmock/vendor/unity/src/unity.c +9 -1
  58. data/vendor/cmock/vendor/unity/src/unity.h +1 -1
  59. data/vendor/cmock/vendor/unity/test/rakefile +2 -1
  60. data/vendor/cmock/vendor/unity/test/testdata/testRunnerGeneratorEmpty.c +13 -0
  61. data/vendor/cmock/vendor/unity/test/tests/test_generate_test_runner.rb +31 -0
  62. data/vendor/unity/auto/generate_test_runner.rb +63 -57
  63. data/vendor/unity/docs/UnityChangeLog.md +1 -0
  64. data/vendor/unity/examples/unity_config.h +8 -0
  65. data/vendor/unity/src/unity.c +9 -1
  66. data/vendor/unity/src/unity.h +1 -1
  67. data/vendor/unity/test/rakefile +2 -1
  68. data/vendor/unity/test/tests/test_generate_test_runner.rb +20 -0
  69. metadata +21 -3
  70. data/vendor/cmock/vendor/unity/auto/run_test.erb +0 -37
@@ -71,24 +71,30 @@ class UnityTestRunnerGenerator
71
71
  source = File.read(input_file)
72
72
  source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
73
73
  tests = find_tests(source)
74
- headers = find_includes(source)
75
- testfile_includes = @options[:use_system_files] ? (headers[:local] + headers[:system]) : headers[:local]
76
- used_mocks = find_mocks(testfile_includes)
77
- testfile_includes = (testfile_includes - used_mocks)
78
- testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
74
+ includes = find_includes(source)
75
+ headers = includes[:headers]
76
+ used_mocks = find_mocks(headers)
77
+ headers = (headers - used_mocks)
78
+ headers.delete_if { |inc| inc =~ /(unity|cmock)/ }
79
79
  find_setup_and_teardown(source)
80
80
 
81
81
  # build runner file
82
- generate(input_file, output_file, tests, used_mocks, testfile_includes)
82
+ generate(input_file, output_file, tests, used_mocks, headers)
83
83
 
84
84
  # determine which files were used to return them
85
85
  all_files_used = [input_file, output_file]
86
- all_files_used += testfile_includes.map { |filename| "#{filename}.c" } unless testfile_includes.empty?
86
+ all_files_used += headers.reject { |filename| filename =~ /^</ }.map { |filename| "#{filename}.c" } unless headers.empty?
87
87
  all_files_used += @options[:includes] unless @options[:includes].empty?
88
- all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
88
+ all_files_used += includes[:linkonly] unless includes[:linkonly].empty?
89
89
  all_files_used.uniq
90
90
  end
91
91
 
92
+ # Generate a test file for the given features:
93
+ # input_file - the name of the test file this is based on
94
+ # output_file - the name of the test runner file to generate
95
+ # tests - an array of all the tests which can be run from this test runner
96
+ # used_mocks - an array of all mock files which are used by this test runner
97
+ # testfile_includes - an array of all included headers, in order, where system headers still have their <> attached
92
98
  def generate(input_file, output_file, tests, used_mocks, testfile_includes)
93
99
  File.open(output_file, 'w') do |output|
94
100
  create_header(output, used_mocks, testfile_includes)
@@ -100,16 +106,17 @@ class UnityTestRunnerGenerator
100
106
  create_suite_setup(output)
101
107
  create_suite_teardown(output)
102
108
  create_reset(output)
103
- create_run_test(output) unless tests.empty?
109
+ create_run_test(output)
104
110
  create_args_wrappers(output, tests)
105
111
  create_shuffle_tests(output) if @options[:shuffle_tests]
112
+ tests = create_warning_test(output, input_file, tests)
106
113
  create_main(output, input_file, tests, used_mocks)
107
114
  end
108
115
 
109
116
  return unless @options[:header_file] && !@options[:header_file].empty?
110
117
 
111
118
  File.open(@options[:header_file], 'w') do |output|
112
- create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
119
+ create_h_file(output, @options[:header_file], tests, headers, used_mocks)
113
120
  end
114
121
  end
115
122
 
@@ -211,10 +218,14 @@ class UnityTestRunnerGenerator
211
218
  source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
212
219
  source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
213
220
 
214
- # parse out includes
221
+ # parse out includes (NOTICE: system includes KEEP the angle-brackets in the string, to preserve this information)
222
+ headers = if @options[:use_system_files]
223
+ source.scan(/^\s*#include\s+(?:(<)|")\s*(.+\.#{@options[:include_extensions]})\s*(?:(>)|")/).map(&:join).flatten
224
+ else
225
+ source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten
226
+ end
215
227
  {
216
- local: source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten,
217
- system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
228
+ headers: headers,
218
229
  linkonly: source.scan(/^TEST_SOURCE_FILE\(\s*"\s*(.+\.#{@options[:source_extensions]})\s*"/).flatten
219
230
  }
220
231
  end
@@ -251,7 +262,7 @@ class UnityTestRunnerGenerator
251
262
  end
252
263
  end
253
264
 
254
- def create_header(output, mocks, testfile_includes = [])
265
+ def create_header(output, mocks, headers = [])
255
266
  output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
256
267
  output.puts("\n/*=======Automagically Detected Files To Include=====*/")
257
268
  output.puts('extern "C" {') if @options[:externcincludes]
@@ -274,10 +285,7 @@ class UnityTestRunnerGenerator
274
285
  if @options[:header_file] && !@options[:header_file].empty?
275
286
  output.puts("#include \"#{File.basename(@options[:header_file])}\"")
276
287
  else
277
- @options[:includes].flatten.uniq.compact.each do |inc|
278
- output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
279
- end
280
- testfile_includes.each do |inc|
288
+ [@options[:includes], headers].flatten.uniq.compact.each do |inc|
281
289
  output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
282
290
  end
283
291
  end
@@ -406,10 +414,43 @@ class UnityTestRunnerGenerator
406
414
  end
407
415
 
408
416
  def create_run_test(output)
409
- require 'erb'
410
- file = File.read(File.join(__dir__, 'run_test.erb'))
411
- template = ERB.new(file, trim_mode: '<>')
412
- output.puts("\n#{template.result(binding)}")
417
+ output.puts('/*=======Test Runner Used To Run Each Test=====*/')
418
+ output.puts('static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE line_num)')
419
+ output.puts('{')
420
+ output.puts(' Unity.CurrentTestName = name;')
421
+ output.puts(' Unity.CurrentTestLineNumber = (UNITY_UINT) line_num;')
422
+ output.puts('#ifdef UNITY_USE_COMMAND_LINE_ARGS')
423
+ output.puts(' if (!UnityTestMatches())')
424
+ output.puts(' return;')
425
+ output.puts('#endif')
426
+ output.puts(' Unity.NumberOfTests++;')
427
+ output.puts(' UNITY_CLR_DETAILS();')
428
+ output.puts(' UNITY_EXEC_TIME_START();')
429
+ output.puts(' CMock_Init();')
430
+ output.puts(' if (TEST_PROTECT())')
431
+ output.puts(' {')
432
+ if @options[:plugins].include?(:cexception)
433
+ output.puts(' volatile CEXCEPTION_T e;')
434
+ output.puts(' Try {')
435
+ output.puts(" #{@options[:setup_name]}();")
436
+ output.puts(' func();')
437
+ output.puts(' } Catch(e) {')
438
+ output.puts(' TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!");')
439
+ output.puts(' }')
440
+ else
441
+ output.puts(" #{@options[:setup_name]}();")
442
+ output.puts(' func();')
443
+ end
444
+ output.puts(' }')
445
+ output.puts(' if (TEST_PROTECT())')
446
+ output.puts(' {')
447
+ output.puts(" #{@options[:teardown_name]}();")
448
+ output.puts(' CMock_Verify();')
449
+ output.puts(' }')
450
+ output.puts(' CMock_Destroy();')
451
+ output.puts(' UNITY_EXEC_TIME_STOP();')
452
+ output.puts(' UnityConcludeTest();')
453
+ output.puts('}')
413
454
  end
414
455
 
415
456
  def create_args_wrappers(output, tests)
@@ -428,6 +469,22 @@ class UnityTestRunnerGenerator
428
469
  end
429
470
  end
430
471
 
472
+ def create_warning_test(output, filename, tests)
473
+ if count_tests(tests) == 0
474
+ warning_test = {
475
+ :test => 'test_empty_warning',
476
+ :line_number => 0
477
+ }
478
+ output.puts("\n/*=======Warning Test=====*/")
479
+ output.puts("static void #{warning_test[:test]}(void)")
480
+ output.puts('{')
481
+ output.puts(" TEST_IGNORE_MESSAGE(\"Test file '#{filename.gsub(/\\/, '\\\\\\')}' contains no tests.\");")
482
+ output.puts("}\n")
483
+ tests = [warning_test]
484
+ end
485
+ tests
486
+ end
487
+
431
488
  def create_shuffle_tests(output)
432
489
  output.puts("\n/*=======Shuffle Test Order=====*/")
433
490
  output.puts('static void shuffleTests(struct UnityRunTestParameters run_test_params_arr[], int num_of_tests)')
@@ -453,13 +510,15 @@ class UnityTestRunnerGenerator
453
510
  end
454
511
  output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
455
512
  output.puts('{')
513
+ output.puts('(void)argc;')
514
+ output.puts('(void)argv;')
456
515
  output.puts('#ifdef UNITY_USE_COMMAND_LINE_ARGS')
457
516
  output.puts(' int parse_status = UnityParseOptions(argc, argv);')
458
517
  output.puts(' if (parse_status != 0)')
459
518
  output.puts(' {')
460
519
  output.puts(' if (parse_status < 0)')
461
520
  output.puts(' {')
462
- output.puts(" UnityPrint(\"#{filename.gsub('.c', '').gsub(/\\/, '\\\\\\')}.\");")
521
+ output.puts(" UnityPrint(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
463
522
  output.puts(' UNITY_PRINT_EOL();')
464
523
  tests.each do |test|
465
524
  if !@options[:use_param_tests] || test[:args].nil? || test[:args].empty?
@@ -533,7 +592,7 @@ class UnityTestRunnerGenerator
533
592
  output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
534
593
  if @options[:has_suite_teardown]
535
594
  if @options[:omit_begin_end]
536
- output.puts(' (void) suite_teardown(0);')
595
+ output.puts(' (void) suiteTearDown(0);')
537
596
  else
538
597
  output.puts(' return suiteTearDown(UNITY_END());')
539
598
  end
@@ -543,17 +602,14 @@ class UnityTestRunnerGenerator
543
602
  output.puts('}')
544
603
  end
545
604
 
546
- def create_h_file(output, filename, tests, testfile_includes, used_mocks)
605
+ def create_h_file(output, filename, tests, headers, used_mocks)
547
606
  filename = File.basename(filename).gsub(/[-\/\\.,\s]/, '_').upcase
548
607
  output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
549
608
  output.puts("#ifndef _#{filename}")
550
609
  output.puts("#define _#{filename}\n\n")
551
610
  output.puts("#include \"#{@options[:framework]}.h\"")
552
611
  output.puts('#include "cmock.h"') unless used_mocks.empty?
553
- @options[:includes].flatten.uniq.compact.each do |inc|
554
- output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
555
- end
556
- testfile_includes.each do |inc|
612
+ [@options[:includes], headers].flatten.uniq.compact.each do |inc|
557
613
  output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
558
614
  end
559
615
  output.puts "\n"
@@ -29,6 +29,7 @@ Significant Bugfixes:
29
29
  - display of failures fixed on ARM processors, particularly with arrays (#807)
30
30
  - fixed each-equal assertion for memory (#797)
31
31
  - fix many warnings.
32
+ - Test runner generator calls custom suite teardown when begin/end calls are omitted. @94xhn
32
33
 
33
34
  Other:
34
35
 
@@ -250,4 +250,12 @@
250
250
  */
251
251
  /* #define UNITY_INCLUDE_EXEC_TIME */
252
252
 
253
+ /* Define this macro to redefine what the UnityPrintChar() function considers
254
+ * a printable character.
255
+ *
256
+ * Example, for printing UTF-8:
257
+ * #define UNITY_IS_PRINTABLE_CHAR(c) ((128 <= (c)) && ((c) <= 255))
258
+ */
259
+ /* #define UNITY_IS_PRINTABLE_CHAR(c) ((32 <= (c)) && ((c) <= 126)) */
260
+
253
261
  #endif /* UNITY_CONFIG_H */
@@ -7,6 +7,8 @@
7
7
 
8
8
  #include "unity.h"
9
9
 
10
+ #include <stdbool.h>
11
+
10
12
  #ifndef UNITY_PROGMEM
11
13
  #define UNITY_PROGMEM
12
14
  #endif
@@ -88,8 +90,14 @@ static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DET
88
90
  /* Local helper function to print characters. */
89
91
  static void UnityPrintChar(const char* pch)
90
92
  {
93
+ #ifdef UNITY_IS_PRINTABLE_CHAR
94
+ const int isPrintable = UNITY_IS_PRINTABLE_CHAR(*pch);
95
+ #else
96
+ const int isPrintable = ((32 <= *pch) && (*pch <= 126));
97
+ #endif
98
+
91
99
  /* printable characters plus CR & LF are printed */
92
- if ((*pch <= 126) && (*pch >= 32))
100
+ if (isPrintable)
93
101
  {
94
102
  UNITY_OUTPUT_CHAR(*pch);
95
103
  }
@@ -11,7 +11,7 @@
11
11
 
12
12
  #define UNITY_VERSION_MAJOR 2
13
13
  #define UNITY_VERSION_MINOR 7
14
- #define UNITY_VERSION_BUILD 0
14
+ #define UNITY_VERSION_BUILD 2
15
15
  #define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD)
16
16
 
17
17
  #ifdef __cplusplus
@@ -19,6 +19,7 @@ TEMP_DIRS = [
19
19
 
20
20
  TEMP_DIRS.each do |dir|
21
21
  directory(dir)
22
+ CLEAN.include(File.join(dir, '*.*'))
22
23
  CLOBBER.include(dir)
23
24
  end
24
25
 
@@ -167,7 +168,7 @@ namespace :style do
167
168
 
168
169
  desc "Attempt to Autocorrect style"
169
170
  task :auto => ['style:clean'] do
170
- execute("rubocop ../auto ../examples ../extras --auto-correct --config .rubocop.yml")
171
+ execute("rubocop ../auto ../examples ../extras --autocorrect --config .rubocop.yml")
171
172
  report "Autocorrected What We Could."
172
173
  end
173
174
 
@@ -0,0 +1,13 @@
1
+ /* =========================================================================
2
+ Unity - A Test Framework for C
3
+ ThrowTheSwitch.org
4
+ Copyright (c) 2007-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
5
+ SPDX-License-Identifier: MIT
6
+ ========================================================================= */
7
+
8
+ /* This Test File Is Used To Verify The Warning When No Tests Are Found */
9
+
10
+ #include "unity.h"
11
+
12
+ void setUp(void) {}
13
+ void tearDown(void) {}
@@ -336,6 +336,17 @@ RUNNER_TESTS = [
336
336
  },
337
337
 
338
338
 
339
+ { :name => 'EmptyFileWarning',
340
+ :testfile => 'testdata/testRunnerGeneratorEmpty.c',
341
+ :testdefines => ['TEST'],
342
+ :options => nil, #defaults
343
+ :expected => {
344
+ :to_pass => [ ],
345
+ :to_fail => [ ],
346
+ :to_ignore => [ 'test_empty_warning' ],
347
+ }
348
+ },
349
+
339
350
  #### WITH MOCKS ##########################################
340
351
 
341
352
  { :name => 'DefaultsThroughOptions',
@@ -1303,6 +1314,26 @@ def verify_number(expected, expression, output)
1303
1314
  end
1304
1315
  end
1305
1316
 
1317
+ should 'GenerateSuiteTeardownWhenBeginAndEndAreOmitted' do
1318
+ runner_name = OUT_FILE + 'SuiteTeardownWithoutBeginEnd_runner.c'
1319
+ UnityTestRunnerGenerator.new(
1320
+ :test_prefix => 'test',
1321
+ :suite_teardown => ' return num_failures;',
1322
+ :omit_begin_end => true,
1323
+ ).run('testdata/testRunnerGenerator.c', runner_name)
1324
+
1325
+ runner = File.read(runner_name)
1326
+ correct_call = runner.include?('(void) suiteTearDown(0);')
1327
+ incorrect_call = runner.include?('(void) suite_teardown(0);')
1328
+ if correct_call && !incorrect_call
1329
+ report 'Runner_GenerateSuiteTeardownWhenBeginAndEndAreOmitted:PASS'
1330
+ else
1331
+ report 'Runner_GenerateSuiteTeardownWhenBeginAndEndAreOmitted:FAIL'
1332
+ $generate_test_runner_failures += 1
1333
+ end
1334
+ $generate_test_runner_tests += 1
1335
+ end
1336
+
1306
1337
  RUNNER_TESTS.each do |testset|
1307
1338
  basename = File.basename(testset[:testfile], C_EXTENSION)
1308
1339
  testset_name = "Runner_#{basename}_#{testset[:name]}"
@@ -71,24 +71,30 @@ class UnityTestRunnerGenerator
71
71
  source = File.read(input_file)
72
72
  source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
73
73
  tests = find_tests(source)
74
- headers = find_includes(source)
75
- testfile_includes = @options[:use_system_files] ? (headers[:local] + headers[:system]) : headers[:local]
76
- used_mocks = find_mocks(testfile_includes)
77
- testfile_includes = (testfile_includes - used_mocks)
78
- testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
74
+ includes = find_includes(source)
75
+ headers = includes[:headers]
76
+ used_mocks = find_mocks(headers)
77
+ headers = (headers - used_mocks)
78
+ headers.delete_if { |inc| inc =~ /(unity|cmock)/ }
79
79
  find_setup_and_teardown(source)
80
80
 
81
81
  # build runner file
82
- generate(input_file, output_file, tests, used_mocks, testfile_includes)
82
+ generate(input_file, output_file, tests, used_mocks, headers)
83
83
 
84
84
  # determine which files were used to return them
85
85
  all_files_used = [input_file, output_file]
86
- all_files_used += testfile_includes.map { |filename| "#{filename}.c" } unless testfile_includes.empty?
86
+ all_files_used += headers.reject { |filename| filename =~ /^</ }.map { |filename| "#{filename}.c" } unless headers.empty?
87
87
  all_files_used += @options[:includes] unless @options[:includes].empty?
88
- all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
88
+ all_files_used += includes[:linkonly] unless includes[:linkonly].empty?
89
89
  all_files_used.uniq
90
90
  end
91
91
 
92
+ # Generate a test file for the given features:
93
+ # input_file - the name of the test file this is based on
94
+ # output_file - the name of the test runner file to generate
95
+ # tests - an array of all the tests which can be run from this test runner
96
+ # used_mocks - an array of all mock files which are used by this test runner
97
+ # testfile_includes - an array of all included headers, in order, where system headers still have their <> attached
92
98
  def generate(input_file, output_file, tests, used_mocks, testfile_includes)
93
99
  File.open(output_file, 'w') do |output|
94
100
  create_header(output, used_mocks, testfile_includes)
@@ -110,7 +116,7 @@ class UnityTestRunnerGenerator
110
116
  return unless @options[:header_file] && !@options[:header_file].empty?
111
117
 
112
118
  File.open(@options[:header_file], 'w') do |output|
113
- create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
119
+ create_h_file(output, @options[:header_file], tests, headers, used_mocks)
114
120
  end
115
121
  end
116
122
 
@@ -212,10 +218,14 @@ class UnityTestRunnerGenerator
212
218
  source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
213
219
  source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
214
220
 
215
- # parse out includes
221
+ # parse out includes (NOTICE: system includes KEEP the angle-brackets in the string, to preserve this information)
222
+ headers = if @options[:use_system_files]
223
+ source.scan(/^\s*#include\s+(?:(<)|")\s*(.+\.#{@options[:include_extensions]})\s*(?:(>)|")/).map(&:join).flatten
224
+ else
225
+ source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten
226
+ end
216
227
  {
217
- local: source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten,
218
- system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
228
+ headers: headers,
219
229
  linkonly: source.scan(/^TEST_SOURCE_FILE\(\s*"\s*(.+\.#{@options[:source_extensions]})\s*"/).flatten
220
230
  }
221
231
  end
@@ -252,7 +262,7 @@ class UnityTestRunnerGenerator
252
262
  end
253
263
  end
254
264
 
255
- def create_header(output, mocks, testfile_includes = [])
265
+ def create_header(output, mocks, headers = [])
256
266
  output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
257
267
  output.puts("\n/*=======Automagically Detected Files To Include=====*/")
258
268
  output.puts('extern "C" {') if @options[:externcincludes]
@@ -275,10 +285,7 @@ class UnityTestRunnerGenerator
275
285
  if @options[:header_file] && !@options[:header_file].empty?
276
286
  output.puts("#include \"#{File.basename(@options[:header_file])}\"")
277
287
  else
278
- @options[:includes].flatten.uniq.compact.each do |inc|
279
- output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
280
- end
281
- testfile_includes.each do |inc|
288
+ [@options[:includes], headers].flatten.uniq.compact.each do |inc|
282
289
  output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
283
290
  end
284
291
  end
@@ -407,43 +414,43 @@ class UnityTestRunnerGenerator
407
414
  end
408
415
 
409
416
  def create_run_test(output)
410
- output.puts("/*=======Test Runner Used To Run Each Test=====*/")
411
- output.puts("static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE line_num)")
412
- output.puts("{")
413
- output.puts(" Unity.CurrentTestName = name;")
414
- output.puts(" Unity.CurrentTestLineNumber = (UNITY_UINT) line_num;")
415
- output.puts("#ifdef UNITY_USE_COMMAND_LINE_ARGS")
416
- output.puts(" if (!UnityTestMatches())")
417
- output.puts(" return;")
418
- output.puts("#endif")
419
- output.puts(" Unity.NumberOfTests++;")
420
- output.puts(" UNITY_CLR_DETAILS();")
421
- output.puts(" UNITY_EXEC_TIME_START();")
422
- output.puts(" CMock_Init();")
423
- output.puts(" if (TEST_PROTECT())")
424
- output.puts(" {")
417
+ output.puts('/*=======Test Runner Used To Run Each Test=====*/')
418
+ output.puts('static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE line_num)')
419
+ output.puts('{')
420
+ output.puts(' Unity.CurrentTestName = name;')
421
+ output.puts(' Unity.CurrentTestLineNumber = (UNITY_UINT) line_num;')
422
+ output.puts('#ifdef UNITY_USE_COMMAND_LINE_ARGS')
423
+ output.puts(' if (!UnityTestMatches())')
424
+ output.puts(' return;')
425
+ output.puts('#endif')
426
+ output.puts(' Unity.NumberOfTests++;')
427
+ output.puts(' UNITY_CLR_DETAILS();')
428
+ output.puts(' UNITY_EXEC_TIME_START();')
429
+ output.puts(' CMock_Init();')
430
+ output.puts(' if (TEST_PROTECT())')
431
+ output.puts(' {')
425
432
  if @options[:plugins].include?(:cexception)
426
- output.puts(" volatile CEXCEPTION_T e;")
427
- output.puts(" Try {")
433
+ output.puts(' volatile CEXCEPTION_T e;')
434
+ output.puts(' Try {')
428
435
  output.puts(" #{@options[:setup_name]}();")
429
- output.puts(" func();")
430
- output.puts(" } Catch(e) {")
431
- output.puts(" TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\");")
432
- output.puts(" }")
436
+ output.puts(' func();')
437
+ output.puts(' } Catch(e) {')
438
+ output.puts(' TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!");')
439
+ output.puts(' }')
433
440
  else
434
441
  output.puts(" #{@options[:setup_name]}();")
435
- output.puts(" func();")
442
+ output.puts(' func();')
436
443
  end
437
- output.puts(" }")
438
- output.puts(" if (TEST_PROTECT())")
439
- output.puts(" {")
444
+ output.puts(' }')
445
+ output.puts(' if (TEST_PROTECT())')
446
+ output.puts(' {')
440
447
  output.puts(" #{@options[:teardown_name]}();")
441
- output.puts(" CMock_Verify();")
442
- output.puts(" }")
443
- output.puts(" CMock_Destroy();")
444
- output.puts(" UNITY_EXEC_TIME_STOP();")
445
- output.puts(" UnityConcludeTest();")
446
- output.puts("}")
448
+ output.puts(' CMock_Verify();')
449
+ output.puts(' }')
450
+ output.puts(' CMock_Destroy();')
451
+ output.puts(' UNITY_EXEC_TIME_STOP();')
452
+ output.puts(' UnityConcludeTest();')
453
+ output.puts('}')
447
454
  end
448
455
 
449
456
  def create_args_wrappers(output, tests)
@@ -465,7 +472,7 @@ class UnityTestRunnerGenerator
465
472
  def create_warning_test(output, filename, tests)
466
473
  if count_tests(tests) == 0
467
474
  warning_test = {
468
- :test => "test_empty_warning",
475
+ :test => 'test_empty_warning',
469
476
  :line_number => 0
470
477
  }
471
478
  output.puts("\n/*=======Warning Test=====*/")
@@ -475,7 +482,7 @@ class UnityTestRunnerGenerator
475
482
  output.puts("}\n")
476
483
  tests = [warning_test]
477
484
  end
478
- return tests
485
+ tests
479
486
  end
480
487
 
481
488
  def create_shuffle_tests(output)
@@ -503,13 +510,15 @@ class UnityTestRunnerGenerator
503
510
  end
504
511
  output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
505
512
  output.puts('{')
513
+ output.puts('(void)argc;')
514
+ output.puts('(void)argv;')
506
515
  output.puts('#ifdef UNITY_USE_COMMAND_LINE_ARGS')
507
516
  output.puts(' int parse_status = UnityParseOptions(argc, argv);')
508
517
  output.puts(' if (parse_status != 0)')
509
518
  output.puts(' {')
510
519
  output.puts(' if (parse_status < 0)')
511
520
  output.puts(' {')
512
- output.puts(" UnityPrint(\"#{filename.gsub('.c', '').gsub(/\\/, '\\\\\\')}.\");")
521
+ output.puts(" UnityPrint(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
513
522
  output.puts(' UNITY_PRINT_EOL();')
514
523
  tests.each do |test|
515
524
  if !@options[:use_param_tests] || test[:args].nil? || test[:args].empty?
@@ -583,7 +592,7 @@ class UnityTestRunnerGenerator
583
592
  output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
584
593
  if @options[:has_suite_teardown]
585
594
  if @options[:omit_begin_end]
586
- output.puts(' (void) suite_teardown(0);')
595
+ output.puts(' (void) suiteTearDown(0);')
587
596
  else
588
597
  output.puts(' return suiteTearDown(UNITY_END());')
589
598
  end
@@ -593,17 +602,14 @@ class UnityTestRunnerGenerator
593
602
  output.puts('}')
594
603
  end
595
604
 
596
- def create_h_file(output, filename, tests, testfile_includes, used_mocks)
605
+ def create_h_file(output, filename, tests, headers, used_mocks)
597
606
  filename = File.basename(filename).gsub(/[-\/\\.,\s]/, '_').upcase
598
607
  output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
599
608
  output.puts("#ifndef _#{filename}")
600
609
  output.puts("#define _#{filename}\n\n")
601
610
  output.puts("#include \"#{@options[:framework]}.h\"")
602
611
  output.puts('#include "cmock.h"') unless used_mocks.empty?
603
- @options[:includes].flatten.uniq.compact.each do |inc|
604
- output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
605
- end
606
- testfile_includes.each do |inc|
612
+ [@options[:includes], headers].flatten.uniq.compact.each do |inc|
607
613
  output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
608
614
  end
609
615
  output.puts "\n"
@@ -29,6 +29,7 @@ Significant Bugfixes:
29
29
  - display of failures fixed on ARM processors, particularly with arrays (#807)
30
30
  - fixed each-equal assertion for memory (#797)
31
31
  - fix many warnings.
32
+ - Test runner generator calls custom suite teardown when begin/end calls are omitted. @94xhn
32
33
 
33
34
  Other:
34
35
 
@@ -250,4 +250,12 @@
250
250
  */
251
251
  /* #define UNITY_INCLUDE_EXEC_TIME */
252
252
 
253
+ /* Define this macro to redefine what the UnityPrintChar() function considers
254
+ * a printable character.
255
+ *
256
+ * Example, for printing UTF-8:
257
+ * #define UNITY_IS_PRINTABLE_CHAR(c) ((128 <= (c)) && ((c) <= 255))
258
+ */
259
+ /* #define UNITY_IS_PRINTABLE_CHAR(c) ((32 <= (c)) && ((c) <= 126)) */
260
+
253
261
  #endif /* UNITY_CONFIG_H */
@@ -7,6 +7,8 @@
7
7
 
8
8
  #include "unity.h"
9
9
 
10
+ #include <stdbool.h>
11
+
10
12
  #ifndef UNITY_PROGMEM
11
13
  #define UNITY_PROGMEM
12
14
  #endif
@@ -88,8 +90,14 @@ static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DET
88
90
  /* Local helper function to print characters. */
89
91
  static void UnityPrintChar(const char* pch)
90
92
  {
93
+ #ifdef UNITY_IS_PRINTABLE_CHAR
94
+ const int isPrintable = UNITY_IS_PRINTABLE_CHAR(*pch);
95
+ #else
96
+ const int isPrintable = ((32 <= *pch) && (*pch <= 126));
97
+ #endif
98
+
91
99
  /* printable characters plus CR & LF are printed */
92
- if ((*pch <= 126) && (*pch >= 32))
100
+ if (isPrintable)
93
101
  {
94
102
  UNITY_OUTPUT_CHAR(*pch);
95
103
  }
@@ -11,7 +11,7 @@
11
11
 
12
12
  #define UNITY_VERSION_MAJOR 2
13
13
  #define UNITY_VERSION_MINOR 7
14
- #define UNITY_VERSION_BUILD 1
14
+ #define UNITY_VERSION_BUILD 2
15
15
  #define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD)
16
16
 
17
17
  #ifdef __cplusplus
@@ -19,6 +19,7 @@ TEMP_DIRS = [
19
19
 
20
20
  TEMP_DIRS.each do |dir|
21
21
  directory(dir)
22
+ CLEAN.include(File.join(dir, '*.*'))
22
23
  CLOBBER.include(dir)
23
24
  end
24
25
 
@@ -167,7 +168,7 @@ namespace :style do
167
168
 
168
169
  desc "Attempt to Autocorrect style"
169
170
  task :auto => ['style:clean'] do
170
- execute("rubocop ../auto ../examples ../extras --auto-correct --config .rubocop.yml")
171
+ execute("rubocop ../auto ../examples ../extras --autocorrect --config .rubocop.yml")
171
172
  report "Autocorrected What We Could."
172
173
  end
173
174