ceedling 0.28.2 → 0.28.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (253) hide show
  1. checksums.yaml +4 -4
  2. data/assets/ceedling +3 -0
  3. data/assets/ceedling.cmd +1 -0
  4. data/assets/default_gitignore +5 -0
  5. data/assets/project_with_guts.yml +1 -0
  6. data/assets/project_with_guts_gcov.yml +3 -0
  7. data/assets/test_example_file_verbose.c +12 -0
  8. data/bin/ceedling +30 -6
  9. data/docs/CeedlingPacket.md +135 -23
  10. data/docs/CeedlingPacket.odt +0 -0
  11. data/examples/blinky/rakefile.rb +2 -1
  12. data/lib/ceedling/configurator.rb +7 -5
  13. data/lib/ceedling/configurator_builder.rb +10 -7
  14. data/lib/ceedling/configurator_plugins.rb +29 -24
  15. data/lib/ceedling/configurator_setup.rb +0 -1
  16. data/lib/ceedling/defaults.rb +7 -2
  17. data/lib/ceedling/dependinator.rb +10 -2
  18. data/lib/ceedling/file_finder.rb +57 -49
  19. data/lib/ceedling/file_path_utils.rb +12 -4
  20. data/lib/ceedling/file_wrapper.rb +4 -0
  21. data/lib/ceedling/generator.rb +4 -3
  22. data/lib/ceedling/generator_test_results.rb +15 -13
  23. data/lib/ceedling/plugin_manager.rb +18 -18
  24. data/lib/ceedling/plugin_reportinator.rb +3 -2
  25. data/lib/ceedling/plugin_reportinator_helper.rb +2 -3
  26. data/lib/ceedling/preprocessinator_extractor.rb +2 -2
  27. data/lib/ceedling/preprocessinator_includes_handler.rb +5 -0
  28. data/lib/ceedling/rakefile.rb +1 -0
  29. data/lib/ceedling/release_invoker_helper.rb +5 -2
  30. data/lib/ceedling/rules_release.rake +2 -1
  31. data/lib/ceedling/rules_tests.rake +18 -9
  32. data/lib/ceedling/rules_tests_deep_dependencies.rake +2 -2
  33. data/lib/ceedling/task_invoker.rb +15 -3
  34. data/lib/ceedling/tasks_vendor.rake +3 -3
  35. data/lib/ceedling/test_invoker.rb +39 -12
  36. data/lib/ceedling/test_invoker_helper.rb +5 -1
  37. data/lib/ceedling/tool_executor.rb +8 -4
  38. data/lib/ceedling/version.rb +1 -1
  39. data/out.fail +21 -0
  40. data/plugins/beep/README.md +22 -0
  41. data/plugins/beep/lib/beep.rb +40 -0
  42. data/plugins/bullseye/bullseye.rake +43 -36
  43. data/plugins/bullseye/config/defaults.yml +4 -0
  44. data/plugins/bullseye/lib/bullseye.rb +27 -5
  45. data/plugins/command_hooks/lib/command_hooks.rb +3 -0
  46. data/plugins/gcov/README.md +34 -1
  47. data/plugins/gcov/config/defaults.yml +3 -3
  48. data/plugins/gcov/gcov.rake +7 -5
  49. data/plugins/gcov/lib/gcov.rb +3 -1
  50. data/plugins/gcov/lib/gcov_constants.rb +2 -0
  51. data/plugins/junit_tests_report/lib/junit_tests_report.rb +12 -9
  52. data/plugins/module_generator/lib/module_generator.rb +14 -1
  53. data/plugins/module_generator/module_generator.rake +21 -4
  54. data/plugins/raw_output_report/lib/raw_output_report.rb +41 -0
  55. data/spec/gcov/gcov_deployment_spec.rb +1 -1
  56. data/spec/gcov/gcov_test_cases_spec.rb +2 -2
  57. data/spec/generator_test_results_spec.rb +5 -0
  58. data/spec/preprocessinator_includes_handler_spec.rb +1 -0
  59. data/spec/spec_system_helper.rb +178 -4
  60. data/spec/support/test_example.fail +1 -0
  61. data/spec/support/test_example.pass +1 -0
  62. data/spec/support/test_example_empty.pass +1 -0
  63. data/spec/support/test_example_ignore.pass +1 -0
  64. data/spec/support/test_example_mangled.pass +1 -0
  65. data/spec/support/test_example_with_time.pass +22 -0
  66. data/spec/system/deployment_spec.rb +33 -0
  67. data/vendor/cmock/README.md +4 -3
  68. data/vendor/cmock/docs/CMock_Summary.md +1 -1
  69. data/vendor/cmock/lib/cmock_config.rb +4 -0
  70. data/vendor/cmock/lib/cmock_generator.rb +5 -2
  71. data/vendor/cmock/lib/cmock_generator_plugin_array.rb +4 -4
  72. data/vendor/cmock/lib/cmock_generator_plugin_callback.rb +9 -11
  73. data/vendor/cmock/lib/cmock_generator_plugin_cexception.rb +0 -1
  74. data/vendor/cmock/lib/cmock_generator_plugin_ignore.rb +2 -3
  75. data/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb +2 -4
  76. data/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb +0 -2
  77. data/vendor/cmock/lib/cmock_generator_utils.rb +16 -3
  78. data/vendor/cmock/lib/cmock_header_parser.rb +59 -34
  79. data/vendor/cmock/release/build.info +1 -1
  80. data/vendor/cmock/release/version.info +1 -1
  81. data/vendor/cmock/scripts/create_makefile.rb +17 -2
  82. data/vendor/cmock/src/cmock.c +13 -7
  83. data/vendor/cmock/test/test_helper.rb +11 -10
  84. data/vendor/cmock/test/unit/cmock_config_test.rb +4 -2
  85. data/vendor/cmock/test/unit/cmock_generator_main_test.rb +10 -4
  86. data/vendor/cmock/test/unit/cmock_generator_plugin_array_test.rb +20 -12
  87. data/vendor/cmock/test/unit/cmock_generator_plugin_expect_a_test.rb +2 -2
  88. data/vendor/cmock/test/unit/cmock_generator_plugin_expect_b_test.rb +2 -2
  89. data/vendor/cmock/test/unit/cmock_generator_plugin_ignore_arg_test.rb +3 -3
  90. data/vendor/cmock/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb +8 -6
  91. data/vendor/cmock/test/unit/cmock_generator_utils_test.rb +27 -10
  92. data/vendor/cmock/test/unit/cmock_header_parser_test.rb +108 -20
  93. data/vendor/cmock/vendor/c_exception/Gemfile +4 -0
  94. data/vendor/cmock/vendor/c_exception/Gemfile.lock +12 -0
  95. data/vendor/cmock/vendor/c_exception/LICENSE.txt +30 -0
  96. data/vendor/cmock/vendor/c_exception/README.md +162 -0
  97. data/vendor/cmock/vendor/c_exception/Rakefile +42 -0
  98. data/vendor/cmock/vendor/c_exception/docs/CException.md +292 -0
  99. data/vendor/cmock/vendor/c_exception/docs/ThrowTheSwitchCodingStandard.md +207 -0
  100. data/vendor/cmock/vendor/c_exception/lib/CException.c +46 -0
  101. data/vendor/cmock/vendor/c_exception/lib/CException.h +110 -0
  102. data/vendor/cmock/vendor/c_exception/makefile +24 -0
  103. data/vendor/cmock/vendor/c_exception/release/build.info +2 -0
  104. data/vendor/cmock/vendor/c_exception/release/version.info +2 -0
  105. data/vendor/cmock/vendor/c_exception/test/CExceptionConfig.h +46 -0
  106. data/vendor/cmock/vendor/c_exception/test/TestException.c +391 -0
  107. data/vendor/cmock/vendor/c_exception/test/TestException_Runner.c +67 -0
  108. data/vendor/cmock/vendor/unity/README.md +231 -0
  109. data/vendor/cmock/vendor/unity/auto/colour_prompt.rb +118 -0
  110. data/vendor/cmock/vendor/unity/auto/colour_reporter.rb +39 -0
  111. data/vendor/cmock/vendor/unity/auto/generate_config.yml +36 -0
  112. data/vendor/cmock/vendor/unity/auto/generate_module.rb +308 -0
  113. data/vendor/cmock/vendor/unity/auto/generate_test_runner.rb +457 -0
  114. data/vendor/cmock/vendor/unity/auto/parse_output.rb +323 -0
  115. data/vendor/cmock/vendor/unity/auto/stylize_as_junit.rb +252 -0
  116. data/vendor/cmock/vendor/unity/auto/test_file_filter.rb +25 -0
  117. data/vendor/cmock/vendor/unity/auto/type_sanitizer.rb +6 -0
  118. data/vendor/cmock/vendor/unity/auto/unity_test_summary.py +139 -0
  119. data/vendor/cmock/vendor/unity/auto/unity_test_summary.rb +136 -0
  120. data/vendor/cmock/vendor/unity/auto/unity_to_junit.py +146 -0
  121. data/vendor/cmock/vendor/unity/docs/ThrowTheSwitchCodingStandard.md +206 -0
  122. data/vendor/cmock/vendor/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf +0 -0
  123. data/vendor/cmock/vendor/unity/docs/UnityAssertionsReference.md +779 -0
  124. data/vendor/cmock/vendor/unity/docs/UnityConfigurationGuide.md +433 -0
  125. data/vendor/cmock/vendor/unity/docs/UnityGettingStartedGuide.md +192 -0
  126. data/vendor/cmock/vendor/unity/docs/UnityHelperScriptsGuide.md +260 -0
  127. data/vendor/cmock/vendor/unity/docs/license.txt +21 -0
  128. data/vendor/cmock/vendor/unity/examples/example_1/makefile +71 -0
  129. data/vendor/cmock/vendor/unity/examples/example_1/readme.txt +5 -0
  130. data/vendor/cmock/vendor/unity/examples/example_1/src/ProductionCode.c +24 -0
  131. data/vendor/cmock/vendor/unity/examples/example_1/src/ProductionCode.h +3 -0
  132. data/vendor/cmock/vendor/unity/examples/example_1/src/ProductionCode2.c +11 -0
  133. data/vendor/cmock/vendor/unity/examples/example_1/src/ProductionCode2.h +2 -0
  134. data/vendor/cmock/vendor/unity/examples/example_1/test/TestProductionCode.c +62 -0
  135. data/vendor/cmock/vendor/unity/examples/example_1/test/TestProductionCode2.c +31 -0
  136. data/vendor/cmock/vendor/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c +53 -0
  137. data/vendor/cmock/vendor/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c +57 -0
  138. data/vendor/cmock/vendor/unity/examples/example_2/makefile +70 -0
  139. data/vendor/cmock/vendor/unity/examples/example_2/readme.txt +5 -0
  140. data/vendor/cmock/vendor/unity/examples/example_2/src/ProductionCode.c +24 -0
  141. data/vendor/cmock/vendor/unity/examples/example_2/src/ProductionCode.h +3 -0
  142. data/vendor/cmock/vendor/unity/examples/example_2/src/ProductionCode2.c +11 -0
  143. data/vendor/cmock/vendor/unity/examples/example_2/src/ProductionCode2.h +2 -0
  144. data/vendor/cmock/vendor/unity/examples/example_2/test/TestProductionCode.c +64 -0
  145. data/vendor/cmock/vendor/unity/examples/example_2/test/TestProductionCode2.c +33 -0
  146. data/vendor/cmock/vendor/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c +9 -0
  147. data/vendor/cmock/vendor/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c +11 -0
  148. data/vendor/cmock/vendor/unity/examples/example_2/test/test_runners/all_tests.c +12 -0
  149. data/vendor/cmock/vendor/unity/examples/example_3/helper/UnityHelper.c +10 -0
  150. data/vendor/cmock/vendor/unity/examples/example_3/helper/UnityHelper.h +12 -0
  151. data/vendor/cmock/vendor/unity/examples/example_3/rakefile.rb +43 -0
  152. data/vendor/cmock/vendor/unity/examples/example_3/rakefile_helper.rb +249 -0
  153. data/vendor/cmock/vendor/unity/examples/example_3/readme.txt +13 -0
  154. data/vendor/cmock/vendor/unity/examples/example_3/src/ProductionCode.c +24 -0
  155. data/vendor/cmock/vendor/unity/examples/example_3/src/ProductionCode.h +3 -0
  156. data/vendor/cmock/vendor/unity/examples/example_3/src/ProductionCode2.c +11 -0
  157. data/vendor/cmock/vendor/unity/examples/example_3/src/ProductionCode2.h +2 -0
  158. data/vendor/cmock/vendor/unity/examples/example_3/target_gcc_32.yml +46 -0
  159. data/vendor/cmock/vendor/unity/examples/example_3/test/TestProductionCode.c +62 -0
  160. data/vendor/cmock/vendor/unity/examples/example_3/test/TestProductionCode2.c +31 -0
  161. data/vendor/cmock/vendor/unity/examples/unity_config.h +247 -0
  162. data/vendor/cmock/vendor/unity/extras/eclipse/error_parsers.txt +26 -0
  163. data/vendor/cmock/vendor/unity/extras/fixture/rakefile.rb +48 -0
  164. data/vendor/cmock/vendor/unity/extras/fixture/rakefile_helper.rb +178 -0
  165. data/vendor/cmock/vendor/unity/extras/fixture/readme.txt +9 -0
  166. data/vendor/cmock/vendor/unity/extras/fixture/src/unity_fixture.c +436 -0
  167. data/vendor/cmock/vendor/unity/extras/fixture/src/unity_fixture.h +83 -0
  168. data/vendor/cmock/vendor/unity/extras/fixture/src/unity_fixture_internals.h +51 -0
  169. data/vendor/cmock/vendor/unity/extras/fixture/src/unity_fixture_malloc_overrides.h +47 -0
  170. data/vendor/cmock/vendor/unity/extras/fixture/test/Makefile +75 -0
  171. data/vendor/cmock/vendor/unity/extras/fixture/test/main/AllTests.c +22 -0
  172. data/vendor/cmock/vendor/unity/extras/fixture/test/template_fixture_tests.c +39 -0
  173. data/vendor/cmock/vendor/unity/extras/fixture/test/unity_fixture_Test.c +543 -0
  174. data/vendor/cmock/vendor/unity/extras/fixture/test/unity_fixture_TestRunner.c +57 -0
  175. data/vendor/cmock/vendor/unity/extras/fixture/test/unity_output_Spy.c +57 -0
  176. data/vendor/cmock/vendor/unity/extras/fixture/test/unity_output_Spy.h +17 -0
  177. data/vendor/cmock/vendor/unity/release/build.info +2 -0
  178. data/vendor/cmock/vendor/unity/release/version.info +2 -0
  179. data/vendor/cmock/vendor/unity/src/unity.c +1572 -0
  180. data/vendor/cmock/vendor/unity/src/unity.h +503 -0
  181. data/vendor/cmock/vendor/unity/src/unity_internals.h +924 -0
  182. data/vendor/cmock/vendor/unity/test/Makefile +68 -0
  183. data/vendor/cmock/vendor/unity/test/expectdata/testsample_cmd.c +61 -0
  184. data/vendor/cmock/vendor/unity/test/expectdata/testsample_def.c +57 -0
  185. data/vendor/cmock/vendor/unity/test/expectdata/testsample_head1.c +55 -0
  186. data/vendor/cmock/vendor/unity/test/expectdata/testsample_head1.h +15 -0
  187. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_cmd.c +80 -0
  188. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_def.c +76 -0
  189. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_head1.c +75 -0
  190. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_head1.h +13 -0
  191. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_new1.c +89 -0
  192. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_new2.c +89 -0
  193. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_param.c +77 -0
  194. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_run1.c +89 -0
  195. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_run2.c +89 -0
  196. data/vendor/cmock/vendor/unity/test/expectdata/testsample_mock_yaml.c +90 -0
  197. data/vendor/cmock/vendor/unity/test/expectdata/testsample_new1.c +67 -0
  198. data/vendor/cmock/vendor/unity/test/expectdata/testsample_new2.c +70 -0
  199. data/vendor/cmock/vendor/unity/test/expectdata/testsample_param.c +58 -0
  200. data/vendor/cmock/vendor/unity/test/expectdata/testsample_run1.c +67 -0
  201. data/vendor/cmock/vendor/unity/test/expectdata/testsample_run2.c +70 -0
  202. data/vendor/cmock/vendor/unity/test/expectdata/testsample_yaml.c +71 -0
  203. data/vendor/cmock/vendor/unity/test/rakefile +125 -0
  204. data/vendor/cmock/vendor/unity/test/rakefile_helper.rb +260 -0
  205. data/vendor/cmock/vendor/unity/test/spec/generate_module_existing_file_spec.rb +158 -0
  206. data/vendor/cmock/vendor/unity/test/targets/clang_file.yml +78 -0
  207. data/vendor/cmock/vendor/unity/test/targets/clang_strict.yml +78 -0
  208. data/vendor/cmock/vendor/unity/test/targets/gcc_32.yml +49 -0
  209. data/vendor/cmock/vendor/unity/test/targets/gcc_64.yml +50 -0
  210. data/vendor/cmock/vendor/unity/test/targets/gcc_auto_limits.yml +47 -0
  211. data/vendor/cmock/vendor/unity/test/targets/gcc_auto_stdint.yml +59 -0
  212. data/vendor/cmock/vendor/unity/test/targets/gcc_manual_math.yml +47 -0
  213. data/vendor/cmock/vendor/unity/test/targets/hitech_picc18.yml +101 -0
  214. data/vendor/cmock/vendor/unity/test/targets/iar_arm_v4.yml +90 -0
  215. data/vendor/cmock/vendor/unity/test/targets/iar_arm_v5.yml +80 -0
  216. data/vendor/cmock/vendor/unity/test/targets/iar_arm_v5_3.yml +80 -0
  217. data/vendor/cmock/vendor/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml +94 -0
  218. data/vendor/cmock/vendor/unity/test/targets/iar_cortexm3_v5.yml +84 -0
  219. data/vendor/cmock/vendor/unity/test/targets/iar_msp430.yml +95 -0
  220. data/vendor/cmock/vendor/unity/test/targets/iar_sh2a_v6.yml +86 -0
  221. data/vendor/cmock/vendor/unity/test/testdata/CException.h +11 -0
  222. data/vendor/cmock/vendor/unity/test/testdata/Defs.h +8 -0
  223. data/vendor/cmock/vendor/unity/test/testdata/cmock.h +14 -0
  224. data/vendor/cmock/vendor/unity/test/testdata/mockMock.h +13 -0
  225. data/vendor/cmock/vendor/unity/test/testdata/testRunnerGenerator.c +186 -0
  226. data/vendor/cmock/vendor/unity/test/testdata/testRunnerGeneratorSmall.c +70 -0
  227. data/vendor/cmock/vendor/unity/test/testdata/testRunnerGeneratorWithMocks.c +195 -0
  228. data/vendor/cmock/vendor/unity/test/tests/test_generate_test_runner.rb +1252 -0
  229. data/vendor/cmock/vendor/unity/test/tests/testparameterized.c +113 -0
  230. data/vendor/cmock/vendor/unity/test/tests/testunity.c +5371 -0
  231. data/vendor/unity/auto/generate_test_runner.rb +30 -10
  232. data/vendor/unity/auto/parse_output.rb +212 -109
  233. data/vendor/unity/docs/ThrowTheSwitchCodingStandard.md +9 -10
  234. data/vendor/unity/docs/UnityAssertionsReference.md +11 -2
  235. data/vendor/unity/docs/UnityConfigurationGuide.md +90 -55
  236. data/vendor/unity/docs/UnityGettingStartedGuide.md +6 -5
  237. data/vendor/unity/docs/UnityHelperScriptsGuide.md +23 -5
  238. data/vendor/unity/examples/unity_config.h +8 -0
  239. data/vendor/unity/extras/fixture/src/unity_fixture.c +4 -0
  240. data/vendor/unity/extras/fixture/src/unity_fixture.h +1 -1
  241. data/vendor/unity/extras/fixture/src/unity_fixture_internals.h +2 -2
  242. data/vendor/unity/release/build.info +1 -1
  243. data/vendor/unity/release/version.info +1 -1
  244. data/vendor/unity/src/unity.c +64 -57
  245. data/vendor/unity/src/unity.h +111 -7
  246. data/vendor/unity/src/unity_internals.h +173 -73
  247. data/vendor/unity/test/Makefile +5 -1
  248. data/vendor/unity/test/testdata/testRunnerGenerator.c +4 -1
  249. data/vendor/unity/test/testdata/testRunnerGeneratorSmall.c +4 -1
  250. data/vendor/unity/test/testdata/testRunnerGeneratorWithMocks.c +4 -1
  251. data/vendor/unity/test/tests/testparameterized.c +5 -2
  252. data/vendor/unity/test/tests/testunity.c +34 -0
  253. metadata +150 -2
@@ -0,0 +1,36 @@
1
+ #this is a sample configuration file for generate_module
2
+ #you would use it by calling generate_module with the -ygenerate_config.yml option
3
+ #files like this are useful for customizing generate_module to your environment
4
+ :generate_module:
5
+ :defaults:
6
+ #these defaults are used in place of any missing options at the command line
7
+ :path_src: ../src/
8
+ :path_inc: ../src/
9
+ :path_tst: ../test/
10
+ :update_svn: true
11
+ :includes:
12
+ #use [] for no additional includes, otherwise list the includes on separate lines
13
+ :src:
14
+ - Defs.h
15
+ - Board.h
16
+ :inc: []
17
+ :tst:
18
+ - Defs.h
19
+ - Board.h
20
+ - Exception.h
21
+ :boilerplates:
22
+ #these are inserted at the top of generated files.
23
+ #just comment out or remove if not desired.
24
+ #use %1$s where you would like the file name to appear (path/extension not included)
25
+ :src: |
26
+ //-------------------------------------------
27
+ // %1$s.c
28
+ //-------------------------------------------
29
+ :inc: |
30
+ //-------------------------------------------
31
+ // %1$s.h
32
+ //-------------------------------------------
33
+ :tst: |
34
+ //-------------------------------------------
35
+ // Test%1$s.c : Units tests for %1$s.c
36
+ //-------------------------------------------
@@ -0,0 +1,308 @@
1
+ # ==========================================
2
+ # Unity Project - A Test Framework for C
3
+ # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
4
+ # [Released under MIT License. Please refer to license.txt for details]
5
+ # ==========================================
6
+
7
+ # This script creates all the files with start code necessary for a new module.
8
+ # A simple module only requires a source file, header file, and test file.
9
+ # Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware).
10
+
11
+ require 'rubygems'
12
+ require 'fileutils'
13
+ require 'pathname'
14
+
15
+ # TEMPLATE_TST
16
+ TEMPLATE_TST ||= '#include "unity.h"
17
+ %2$s#include "%1$s.h"
18
+
19
+ void setUp(void)
20
+ {
21
+ }
22
+
23
+ void tearDown(void)
24
+ {
25
+ }
26
+
27
+ void test_%1$s_NeedToImplement(void)
28
+ {
29
+ TEST_IGNORE_MESSAGE("Need to Implement %1$s");
30
+ }
31
+ '.freeze
32
+
33
+ # TEMPLATE_SRC
34
+ TEMPLATE_SRC ||= '%2$s#include "%1$s.h"
35
+ '.freeze
36
+
37
+ # TEMPLATE_INC
38
+ TEMPLATE_INC ||= '#ifndef _%3$s_H
39
+ #define _%3$s_H
40
+ %2$s
41
+
42
+ #endif // _%3$s_H
43
+ '.freeze
44
+
45
+ class UnityModuleGenerator
46
+ ############################
47
+ def initialize(options = nil)
48
+ here = File.expand_path(File.dirname(__FILE__)) + '/'
49
+
50
+ @options = UnityModuleGenerator.default_options
51
+ case options
52
+ when NilClass then @options
53
+ when String then @options.merge!(UnityModuleGenerator.grab_config(options))
54
+ when Hash then @options.merge!(options)
55
+ else raise 'If you specify arguments, it should be a filename or a hash of options'
56
+ end
57
+
58
+ # Create default file paths if none were provided
59
+ @options[:path_src] = here + '../src/' if @options[:path_src].nil?
60
+ @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil?
61
+ @options[:path_tst] = here + '../test/' if @options[:path_tst].nil?
62
+ @options[:path_src] += '/' unless @options[:path_src][-1] == 47
63
+ @options[:path_inc] += '/' unless @options[:path_inc][-1] == 47
64
+ @options[:path_tst] += '/' unless @options[:path_tst][-1] == 47
65
+
66
+ # Built in patterns
67
+ @patterns = {
68
+ 'src' => {
69
+ '' => { inc: [] }
70
+ },
71
+ 'test' => {
72
+ '' => { inc: [] }
73
+ },
74
+ 'dh' => {
75
+ 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h')] },
76
+ 'Hardware' => { inc: [] }
77
+ },
78
+ 'dih' => {
79
+ 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] },
80
+ 'Interrupt' => { inc: [create_filename('%1$s', 'Hardware.h')] },
81
+ 'Hardware' => { inc: [] }
82
+ },
83
+ 'mch' => {
84
+ 'Model' => { inc: [] },
85
+ 'Conductor' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] },
86
+ 'Hardware' => { inc: [] }
87
+ },
88
+ 'mvp' => {
89
+ 'Model' => { inc: [] },
90
+ 'Presenter' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] },
91
+ 'View' => { inc: [] }
92
+ }
93
+ }
94
+ end
95
+
96
+ ############################
97
+ def self.default_options
98
+ {
99
+ pattern: 'src',
100
+ includes: {
101
+ src: [],
102
+ inc: [],
103
+ tst: []
104
+ },
105
+ update_svn: false,
106
+ boilerplates: {},
107
+ test_prefix: 'Test',
108
+ mock_prefix: 'Mock'
109
+ }
110
+ end
111
+
112
+ ############################
113
+ def self.grab_config(config_file)
114
+ options = default_options
115
+ unless config_file.nil? || config_file.empty?
116
+ require 'yaml'
117
+ yaml_guts = YAML.load_file(config_file)
118
+ options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
119
+ raise "No :unity or :cmock section found in #{config_file}" unless options
120
+ end
121
+ options
122
+ end
123
+
124
+ ############################
125
+ def files_to_operate_on(module_name, pattern = nil)
126
+ # strip any leading path information from the module name and save for later
127
+ subfolder = File.dirname(module_name)
128
+ module_name = File.basename(module_name)
129
+
130
+ # create triad definition
131
+ prefix = @options[:test_prefix] || 'Test'
132
+ triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] },
133
+ { ext: '.h', path: @options[:path_inc], prefix: '', template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] },
134
+ { ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst] }]
135
+
136
+ # prepare the pattern for use
137
+ pattern = (pattern || @options[:pattern] || 'src').downcase
138
+ patterns = @patterns[pattern]
139
+ raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil?
140
+
141
+ # single file patterns (currently just 'test') can reject the other parts of the triad
142
+ triad.select! { |v| v[:inc] == :tst } if pattern == 'test'
143
+
144
+ # Assemble the path/names of the files we need to work with.
145
+ files = []
146
+ triad.each do |cfg|
147
+ patterns.each_pair do |pattern_file, pattern_traits|
148
+ submodule_name = create_filename(module_name, pattern_file)
149
+ filename = cfg[:prefix] + submodule_name + cfg[:ext]
150
+ files << {
151
+ path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath,
152
+ name: submodule_name,
153
+ template: cfg[:template],
154
+ boilerplate: cfg[:boilerplate],
155
+ includes: case (cfg[:inc])
156
+ when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) })
157
+ when :inc then (@options[:includes][:inc] || [])
158
+ when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) })
159
+ end
160
+ }
161
+ end
162
+ end
163
+
164
+ files
165
+ end
166
+
167
+ ############################
168
+ def create_filename(part1, part2 = '')
169
+ if part2.empty?
170
+ case (@options[:naming])
171
+ when 'bumpy' then part1
172
+ when 'camel' then part1
173
+ when 'snake' then part1.downcase
174
+ when 'caps' then part1.upcase
175
+ else part1
176
+ end
177
+ else
178
+ case (@options[:naming])
179
+ when 'bumpy' then part1 + part2
180
+ when 'camel' then part1 + part2
181
+ when 'snake' then part1.downcase + '_' + part2.downcase
182
+ when 'caps' then part1.upcase + '_' + part2.upcase
183
+ else part1 + '_' + part2
184
+ end
185
+ end
186
+ end
187
+
188
+ ############################
189
+ def generate(module_name, pattern = nil)
190
+ files = files_to_operate_on(module_name, pattern)
191
+
192
+ # Abort if all of the module files already exist
193
+ all_files_exist = true
194
+ files.each do |file|
195
+ all_files_exist = false unless File.exist?(file[:path])
196
+ end
197
+ raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist
198
+
199
+ # Create Source Modules
200
+ files.each_with_index do |file, _i|
201
+ # If this file already exists, don't overwrite it.
202
+ if File.exist?(file[:path])
203
+ puts "File #{file[:path]} already exists!"
204
+ next
205
+ end
206
+ # Create the path first if necessary.
207
+ FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false)
208
+ File.open(file[:path], 'w') do |f|
209
+ f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil?
210
+ f.write(file[:template] % [file[:name],
211
+ file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join,
212
+ file[:name].upcase])
213
+ end
214
+ if @options[:update_svn]
215
+ `svn add \"#{file[:path]}\"`
216
+ if $!.exitstatus.zero?
217
+ puts "File #{file[:path]} created and added to source control"
218
+ else
219
+ puts "File #{file[:path]} created but FAILED adding to source control!"
220
+ end
221
+ else
222
+ puts "File #{file[:path]} created"
223
+ end
224
+ end
225
+ puts 'Generate Complete'
226
+ end
227
+
228
+ ############################
229
+ def destroy(module_name, pattern = nil)
230
+ files_to_operate_on(module_name, pattern).each do |filespec|
231
+ file = filespec[:path]
232
+ if File.exist?(file)
233
+ if @options[:update_svn]
234
+ `svn delete \"#{file}\" --force`
235
+ puts "File #{file} deleted and removed from source control"
236
+ else
237
+ FileUtils.remove(file)
238
+ puts "File #{file} deleted"
239
+ end
240
+ else
241
+ puts "File #{file} does not exist so cannot be removed."
242
+ end
243
+ end
244
+ puts 'Destroy Complete'
245
+ end
246
+ end
247
+
248
+ ############################
249
+ # Handle As Command Line If Called That Way
250
+ if $0 == __FILE__
251
+ destroy = false
252
+ options = {}
253
+ module_name = nil
254
+
255
+ # Parse the command line parameters.
256
+ ARGV.each do |arg|
257
+ case arg
258
+ when /^-d/ then destroy = true
259
+ when /^-u/ then options[:update_svn] = true
260
+ when /^-p\"?(\w+)\"?/ then options[:pattern] = Regexp.last_match(1)
261
+ when /^-s\"?(.+)\"?/ then options[:path_src] = Regexp.last_match(1)
262
+ when /^-i\"?(.+)\"?/ then options[:path_inc] = Regexp.last_match(1)
263
+ when /^-t\"?(.+)\"?/ then options[:path_tst] = Regexp.last_match(1)
264
+ when /^-n\"?(.+)\"?/ then options[:naming] = Regexp.last_match(1)
265
+ when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config(Regexp.last_match(1))
266
+ when /^(\w+)/
267
+ raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil?
268
+ module_name = arg
269
+ when /^-(h|-help)/
270
+ ARGV = [].freeze
271
+ else
272
+ raise "ERROR: Unknown option specified '#{arg}'"
273
+ end
274
+ end
275
+
276
+ unless ARGV[0]
277
+ puts ["\nGENERATE MODULE\n-------- ------",
278
+ "\nUsage: ruby generate_module [options] module_name",
279
+ " -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)",
280
+ " -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)",
281
+ " -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)",
282
+ ' -p"MCH" sets the output pattern to MCH.',
283
+ ' dh - driver hardware.',
284
+ ' dih - driver interrupt hardware.',
285
+ ' mch - model conductor hardware.',
286
+ ' mvp - model view presenter.',
287
+ ' src - just a source module, header and test. (DEFAULT)',
288
+ ' test - just a test file.',
289
+ ' -d destroy module instead of creating it.',
290
+ ' -n"camel" sets the file naming convention.',
291
+ ' bumpy - BumpyCaseFilenames.',
292
+ ' camel - camelCaseFilenames.',
293
+ ' snake - snake_case_filenames.',
294
+ ' caps - CAPS_CASE_FILENAMES.',
295
+ ' -u update subversion too (requires subversion command line)',
296
+ ' -y"my.yml" selects a different yaml config file for module generation',
297
+ ''].join("\n")
298
+ exit
299
+ end
300
+
301
+ raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil?
302
+ if destroy
303
+ UnityModuleGenerator.new(options).destroy(module_name)
304
+ else
305
+ UnityModuleGenerator.new(options).generate(module_name)
306
+ end
307
+
308
+ end
@@ -0,0 +1,457 @@
1
+ # ==========================================
2
+ # Unity Project - A Test Framework for C
3
+ # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
4
+ # [Released under MIT License. Please refer to license.txt for details]
5
+ # ==========================================
6
+
7
+ File.expand_path(File.join(File.dirname(__FILE__), 'colour_prompt'))
8
+
9
+ class UnityTestRunnerGenerator
10
+ def initialize(options = nil)
11
+ @options = UnityTestRunnerGenerator.default_options
12
+ case options
13
+ when NilClass then @options
14
+ when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options))
15
+ when Hash then @options.merge!(options)
16
+ else raise 'If you specify arguments, it should be a filename or a hash of options'
17
+ end
18
+ require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer"
19
+ end
20
+
21
+ def self.default_options
22
+ {
23
+ includes: [],
24
+ defines: [],
25
+ plugins: [],
26
+ framework: :unity,
27
+ test_prefix: 'test|spec|should',
28
+ mock_prefix: 'Mock',
29
+ mock_suffix: '',
30
+ setup_name: 'setUp',
31
+ teardown_name: 'tearDown',
32
+ main_name: 'main', # set to :auto to automatically generate each time
33
+ main_export_decl: '',
34
+ cmdline_args: false,
35
+ use_param_tests: false
36
+ }
37
+ end
38
+
39
+ def self.grab_config(config_file)
40
+ options = default_options
41
+ unless config_file.nil? || config_file.empty?
42
+ require 'yaml'
43
+ yaml_guts = YAML.load_file(config_file)
44
+ options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
45
+ raise "No :unity or :cmock section found in #{config_file}" unless options
46
+ end
47
+ options
48
+ end
49
+
50
+ def run(input_file, output_file, options = nil)
51
+ @options.merge!(options) unless options.nil?
52
+
53
+ # pull required data from source file
54
+ source = File.read(input_file)
55
+ source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
56
+ tests = find_tests(source)
57
+ headers = find_includes(source)
58
+ testfile_includes = (headers[:local] + headers[:system])
59
+ used_mocks = find_mocks(testfile_includes)
60
+ testfile_includes = (testfile_includes - used_mocks)
61
+ testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
62
+
63
+ # build runner file
64
+ generate(input_file, output_file, tests, used_mocks, testfile_includes)
65
+
66
+ # determine which files were used to return them
67
+ all_files_used = [input_file, output_file]
68
+ all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty?
69
+ all_files_used += @options[:includes] unless @options[:includes].empty?
70
+ all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
71
+ all_files_used.uniq
72
+ end
73
+
74
+ def generate(input_file, output_file, tests, used_mocks, testfile_includes)
75
+ File.open(output_file, 'w') do |output|
76
+ create_header(output, used_mocks, testfile_includes)
77
+ create_externs(output, tests, used_mocks)
78
+ create_mock_management(output, used_mocks)
79
+ create_suite_setup(output)
80
+ create_suite_teardown(output)
81
+ create_reset(output, used_mocks)
82
+ create_main(output, input_file, tests, used_mocks)
83
+ end
84
+
85
+ return unless @options[:header_file] && !@options[:header_file].empty?
86
+
87
+ File.open(@options[:header_file], 'w') do |output|
88
+ create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
89
+ end
90
+ end
91
+
92
+ def find_tests(source)
93
+ tests_and_line_numbers = []
94
+
95
+ source_scrubbed = source.clone
96
+ source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings
97
+ source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments
98
+ source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments
99
+ lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line
100
+ | (;|\{|\}) /x) # Match ;, {, and } as end of lines
101
+
102
+ lines.each_with_index do |line, _index|
103
+ # find tests
104
+ next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/
105
+ arguments = Regexp.last_match(1)
106
+ name = Regexp.last_match(2)
107
+ call = Regexp.last_match(3)
108
+ params = Regexp.last_match(4)
109
+ args = nil
110
+ if @options[:use_param_tests] && !arguments.empty?
111
+ args = []
112
+ arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] }
113
+ end
114
+ tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 }
115
+ end
116
+ tests_and_line_numbers.uniq! { |v| v[:test] }
117
+
118
+ # determine line numbers and create tests to run
119
+ source_lines = source.split("\n")
120
+ source_index = 0
121
+ tests_and_line_numbers.size.times do |i|
122
+ source_lines[source_index..-1].each_with_index do |line, index|
123
+ next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/
124
+ source_index += index
125
+ tests_and_line_numbers[i][:line_number] = source_index + 1
126
+ break
127
+ end
128
+ end
129
+
130
+ tests_and_line_numbers
131
+ end
132
+
133
+ def find_includes(source)
134
+ # remove comments (block and line, in three steps to ensure correct precedence)
135
+ source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
136
+ source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
137
+ source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
138
+
139
+ # parse out includes
140
+ includes = {
141
+ local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten,
142
+ system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
143
+ linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten
144
+ }
145
+ includes
146
+ end
147
+
148
+ def find_mocks(includes)
149
+ mock_headers = []
150
+ includes.each do |include_path|
151
+ include_file = File.basename(include_path)
152
+ mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}.*#{@options[:mock_suffix]}$/i
153
+ end
154
+ mock_headers
155
+ end
156
+
157
+ def create_header(output, mocks, testfile_includes = [])
158
+ output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
159
+ create_runtest(output, mocks)
160
+ output.puts("\n/*=======Automagically Detected Files To Include=====*/")
161
+ output.puts('#ifdef __WIN32__')
162
+ output.puts('#define UNITY_INCLUDE_SETUP_STUBS')
163
+ output.puts('#endif')
164
+ output.puts("#include \"#{@options[:framework]}.h\"")
165
+ output.puts('#include "cmock.h"') unless mocks.empty?
166
+ output.puts('#ifndef UNITY_EXCLUDE_SETJMP_H')
167
+ output.puts('#include <setjmp.h>')
168
+ output.puts("#endif")
169
+ output.puts('#include <stdio.h>')
170
+ if @options[:defines] && !@options[:defines].empty?
171
+ @options[:defines].each { |d| output.puts("#define #{d}") }
172
+ end
173
+ if @options[:header_file] && !@options[:header_file].empty?
174
+ output.puts("#include \"#{File.basename(@options[:header_file])}\"")
175
+ else
176
+ @options[:includes].flatten.uniq.compact.each do |inc|
177
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
178
+ end
179
+ testfile_includes.each do |inc|
180
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
181
+ end
182
+ end
183
+ mocks.each do |mock|
184
+ output.puts("#include \"#{mock.gsub('.h', '')}.h\"")
185
+ end
186
+ output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
187
+
188
+ return unless @options[:enforce_strict_ordering]
189
+
190
+ output.puts('')
191
+ output.puts('int GlobalExpectCount;')
192
+ output.puts('int GlobalVerifyOrder;')
193
+ output.puts('char* GlobalOrderError;')
194
+ end
195
+
196
+ def create_externs(output, tests, _mocks)
197
+ output.puts("\n/*=======External Functions This Runner Calls=====*/")
198
+ output.puts("extern void #{@options[:setup_name]}(void);")
199
+ output.puts("extern void #{@options[:teardown_name]}(void);")
200
+ tests.each do |test|
201
+ output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
202
+ end
203
+ output.puts('')
204
+ end
205
+
206
+ def create_mock_management(output, mock_headers)
207
+ return if mock_headers.empty?
208
+
209
+ output.puts("\n/*=======Mock Management=====*/")
210
+ output.puts('static void CMock_Init(void)')
211
+ output.puts('{')
212
+
213
+ if @options[:enforce_strict_ordering]
214
+ output.puts(' GlobalExpectCount = 0;')
215
+ output.puts(' GlobalVerifyOrder = 0;')
216
+ output.puts(' GlobalOrderError = NULL;')
217
+ end
218
+
219
+ mocks = mock_headers.map { |mock| File.basename(mock) }
220
+ mocks.each do |mock|
221
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
222
+ output.puts(" #{mock_clean}_Init();")
223
+ end
224
+ output.puts("}\n")
225
+
226
+ output.puts('static void CMock_Verify(void)')
227
+ output.puts('{')
228
+ mocks.each do |mock|
229
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
230
+ output.puts(" #{mock_clean}_Verify();")
231
+ end
232
+ output.puts("}\n")
233
+
234
+ output.puts('static void CMock_Destroy(void)')
235
+ output.puts('{')
236
+ mocks.each do |mock|
237
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
238
+ output.puts(" #{mock_clean}_Destroy();")
239
+ end
240
+ output.puts("}\n")
241
+ end
242
+
243
+ def create_suite_setup(output)
244
+ output.puts("\n/*=======Suite Setup=====*/")
245
+ output.puts('static void suite_setup(void)')
246
+ output.puts('{')
247
+ if @options[:suite_setup].nil?
248
+ # New style, call suiteSetUp() if we can use weak symbols
249
+ output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
250
+ output.puts(' suiteSetUp();')
251
+ output.puts('#endif')
252
+ else
253
+ # Old style, C code embedded in the :suite_setup option
254
+ output.puts(@options[:suite_setup])
255
+ end
256
+ output.puts('}')
257
+ end
258
+
259
+ def create_suite_teardown(output)
260
+ output.puts("\n/*=======Suite Teardown=====*/")
261
+ output.puts('static int suite_teardown(int num_failures)')
262
+ output.puts('{')
263
+ if @options[:suite_teardown].nil?
264
+ # New style, call suiteTearDown() if we can use weak symbols
265
+ output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
266
+ output.puts(' return suiteTearDown(num_failures);')
267
+ output.puts('#else')
268
+ output.puts(' return num_failures;')
269
+ output.puts('#endif')
270
+ else
271
+ # Old style, C code embedded in the :suite_teardown option
272
+ output.puts(@options[:suite_teardown])
273
+ end
274
+ output.puts('}')
275
+ end
276
+
277
+ def create_runtest(output, used_mocks)
278
+ cexception = @options[:plugins].include? :cexception
279
+ va_args1 = @options[:use_param_tests] ? ', ...' : ''
280
+ va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : ''
281
+ output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/")
282
+ output.puts('#define RUN_TEST_NO_ARGS') if @options[:use_param_tests]
283
+ output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\")
284
+ output.puts('{ \\')
285
+ output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\")
286
+ output.puts(' Unity.CurrentTestLineNumber = TestLineNum; \\')
287
+ output.puts(' if (UnityTestMatches()) { \\') if @options[:cmdline_args]
288
+ output.puts(' Unity.NumberOfTests++; \\')
289
+ output.puts(' CMock_Init(); \\') unless used_mocks.empty?
290
+ output.puts(' UNITY_CLR_DETAILS(); \\') unless used_mocks.empty?
291
+ output.puts(' if (TEST_PROTECT()) \\')
292
+ output.puts(' { \\')
293
+ output.puts(' CEXCEPTION_T e; \\') if cexception
294
+ output.puts(' Try { \\') if cexception
295
+ output.puts(" #{@options[:setup_name]}(); \\")
296
+ output.puts(" TestFunc(#{va_args2}); \\")
297
+ output.puts(' } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \\') if cexception
298
+ output.puts(' } \\')
299
+ output.puts(' if (TEST_PROTECT()) \\')
300
+ output.puts(' { \\')
301
+ output.puts(" #{@options[:teardown_name]}(); \\")
302
+ output.puts(' CMock_Verify(); \\') unless used_mocks.empty?
303
+ output.puts(' } \\')
304
+ output.puts(' CMock_Destroy(); \\') unless used_mocks.empty?
305
+ output.puts(' UnityConcludeTest(); \\')
306
+ output.puts(' } \\') if @options[:cmdline_args]
307
+ output.puts("}\n")
308
+ end
309
+
310
+ def create_reset(output, used_mocks)
311
+ output.puts("\n/*=======Test Reset Option=====*/")
312
+ output.puts('void resetTest(void);')
313
+ output.puts('void resetTest(void)')
314
+ output.puts('{')
315
+ output.puts(' CMock_Verify();') unless used_mocks.empty?
316
+ output.puts(' CMock_Destroy();') unless used_mocks.empty?
317
+ output.puts(" #{@options[:teardown_name]}();")
318
+ output.puts(' CMock_Init();') unless used_mocks.empty?
319
+ output.puts(" #{@options[:setup_name]}();")
320
+ output.puts('}')
321
+ end
322
+
323
+ def create_main(output, filename, tests, used_mocks)
324
+ output.puts("\n\n/*=======MAIN=====*/")
325
+ main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s
326
+ if @options[:cmdline_args]
327
+ if main_name != 'main'
328
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);")
329
+ end
330
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
331
+ output.puts('{')
332
+ output.puts(' int parse_status = UnityParseOptions(argc, argv);')
333
+ output.puts(' if (parse_status != 0)')
334
+ output.puts(' {')
335
+ output.puts(' if (parse_status < 0)')
336
+ output.puts(' {')
337
+ output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");")
338
+ output.puts(' UNITY_PRINT_EOL();')
339
+ if @options[:use_param_tests]
340
+ tests.each do |test|
341
+ if test[:args].nil? || test[:args].empty?
342
+ output.puts(" UnityPrint(\" #{test[:test]}(RUN_TEST_NO_ARGS)\");")
343
+ output.puts(' UNITY_PRINT_EOL();')
344
+ else
345
+ test[:args].each do |args|
346
+ output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");")
347
+ output.puts(' UNITY_PRINT_EOL();')
348
+ end
349
+ end
350
+ end
351
+ else
352
+ tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();") }
353
+ end
354
+ output.puts(' return 0;')
355
+ output.puts(' }')
356
+ output.puts(' return parse_status;')
357
+ output.puts(' }')
358
+ else
359
+ if main_name != 'main'
360
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(void);")
361
+ end
362
+ output.puts("int #{main_name}(void)")
363
+ output.puts('{')
364
+ end
365
+ output.puts(' suite_setup();')
366
+ output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
367
+ if @options[:use_param_tests]
368
+ tests.each do |test|
369
+ if test[:args].nil? || test[:args].empty?
370
+ output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);")
371
+ else
372
+ test[:args].each { |args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});") }
373
+ end
374
+ end
375
+ else
376
+ tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") }
377
+ end
378
+ output.puts
379
+ output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
380
+ output.puts(" return suite_teardown(UnityEnd());")
381
+ output.puts('}')
382
+ end
383
+
384
+ def create_h_file(output, filename, tests, testfile_includes, used_mocks)
385
+ filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase
386
+ output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
387
+ output.puts("#ifndef _#{filename}")
388
+ output.puts("#define _#{filename}\n\n")
389
+ output.puts("#include \"#{@options[:framework]}.h\"")
390
+ output.puts('#include "cmock.h"') unless used_mocks.empty?
391
+ @options[:includes].flatten.uniq.compact.each do |inc|
392
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
393
+ end
394
+ testfile_includes.each do |inc|
395
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
396
+ end
397
+ output.puts "\n"
398
+ tests.each do |test|
399
+ if test[:params].nil? || test[:params].empty?
400
+ output.puts("void #{test[:test]}(void);")
401
+ else
402
+ output.puts("void #{test[:test]}(#{test[:params]});")
403
+ end
404
+ end
405
+ output.puts("#endif\n\n")
406
+ end
407
+ end
408
+
409
+ if $0 == __FILE__
410
+ options = { includes: [] }
411
+
412
+ # parse out all the options first (these will all be removed as we go)
413
+ ARGV.reject! do |arg|
414
+ case arg
415
+ when '-cexception'
416
+ options[:plugins] = [:cexception]
417
+ true
418
+ when /\.*\.ya?ml/
419
+ options = UnityTestRunnerGenerator.grab_config(arg)
420
+ true
421
+ when /--(\w+)=\"?(.*)\"?/
422
+ options[Regexp.last_match(1).to_sym] = Regexp.last_match(2)
423
+ true
424
+ when /\.*\.h/
425
+ options[:includes] << arg
426
+ true
427
+ else false
428
+ end
429
+ end
430
+
431
+ # make sure there is at least one parameter left (the input file)
432
+ unless ARGV[0]
433
+ puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)",
434
+ "\n input_test_file - this is the C file you want to create a runner for",
435
+ ' output - this is the name of the runner file to generate',
436
+ ' defaults to (input_test_file)_Runner',
437
+ ' files:',
438
+ ' *.yml / *.yaml - loads configuration from here in :unity or :cmock',
439
+ ' *.h - header files are added as #includes in runner',
440
+ ' options:',
441
+ ' -cexception - include cexception support',
442
+ ' --setup_name="" - redefine setUp func name to something else',
443
+ ' --teardown_name="" - redefine tearDown func name to something else',
444
+ ' --main_name="" - redefine main func name to something else',
445
+ ' --test_prefix="" - redefine test prefix from default test|spec|should',
446
+ ' --suite_setup="" - code to execute for setup of entire suite',
447
+ ' --suite_teardown="" - code to execute for teardown of entire suite',
448
+ ' --use_param_tests=1 - enable parameterized tests (disabled by default)',
449
+ ' --header_file="" - path/name of test header file to generate too'].join("\n")
450
+ exit 1
451
+ end
452
+
453
+ # create the default test runner name if not specified
454
+ ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1]
455
+
456
+ UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
457
+ end