ceedling 0.28.2 → 0.28.3

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 (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,323 @@
1
+ #============================================================
2
+ # Author: John Theofanopoulos
3
+ # A simple parser. Takes the output files generated during the
4
+ # build process and extracts information relating to the tests.
5
+ #
6
+ # Notes:
7
+ # To capture an output file under VS builds use the following:
8
+ # devenv [build instructions] > Output.txt & type Output.txt
9
+ #
10
+ # To capture an output file under Linux builds use the following:
11
+ # make | tee Output.txt
12
+ #
13
+ # This script can handle the following output formats:
14
+ # - normal output (raw unity)
15
+ # - fixture output (unity_fixture.h/.c)
16
+ # - fixture output with verbose flag set ("-v")
17
+ #
18
+ # To use this parser use the following command
19
+ # ruby parseOutput.rb [options] [file]
20
+ # options: -xml : produce a JUnit compatible XML file
21
+ # file: file to scan for results
22
+ #============================================================
23
+
24
+ # Parser class for handling the input file
25
+ class ParseOutput
26
+ def initialize
27
+ # internal data
28
+ @class_name_idx = 0
29
+ @path_delim = nil
30
+
31
+ # xml output related
32
+ @xml_out = false
33
+ @array_list = false
34
+
35
+ # current suite name and statistics
36
+ @test_suite = nil
37
+ @total_tests = 0
38
+ @test_passed = 0
39
+ @test_failed = 0
40
+ @test_ignored = 0
41
+ end
42
+
43
+ # Set the flag to indicate if there will be an XML output file or not
44
+ def set_xml_output
45
+ @xml_out = true
46
+ end
47
+
48
+ # If write our output to XML
49
+ def write_xml_output
50
+ output = File.open('report.xml', 'w')
51
+ output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
52
+ @array_list.each do |item|
53
+ output << item << "\n"
54
+ end
55
+ end
56
+
57
+ # Pushes the suite info as xml to the array list, which will be written later
58
+ def push_xml_output_suite_info
59
+ # Insert opening tag at front
60
+ heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + @test_failed.to_s + '"' + ' skips="' + @test_ignored.to_s + '">'
61
+ @array_list.insert(0, heading)
62
+ # Push back the closing tag
63
+ @array_list.push '</testsuite>'
64
+ end
65
+
66
+ # Pushes xml output data to the array list, which will be written later
67
+ def push_xml_output_passed(test_name)
68
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
69
+ end
70
+
71
+ # Pushes xml output data to the array list, which will be written later
72
+ def push_xml_output_failed(test_name, reason)
73
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
74
+ @array_list.push ' <failure type="ASSERT FAILED">' + reason + '</failure>'
75
+ @array_list.push ' </testcase>'
76
+ end
77
+
78
+ # Pushes xml output data to the array list, which will be written later
79
+ def push_xml_output_ignored(test_name, reason)
80
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
81
+ @array_list.push ' <skipped type="TEST IGNORED">' + reason + '</skipped>'
82
+ @array_list.push ' </testcase>'
83
+ end
84
+
85
+ # This function will try and determine when the suite is changed. This is
86
+ # is the name that gets added to the classname parameter.
87
+ def test_suite_verify(test_suite_name)
88
+ # Split the path name
89
+ test_name = test_suite_name.split(@path_delim)
90
+
91
+ # Remove the extension and extract the base_name
92
+ base_name = test_name[test_name.size - 1].split('.')[0]
93
+
94
+ # Return if the test suite hasn't changed
95
+ return unless base_name.to_s != @test_suite.to_s
96
+
97
+ @test_suite = base_name
98
+ printf "New Test: %s\n", @test_suite
99
+ end
100
+
101
+ # Prepares the line for verbose fixture output ("-v")
102
+ def prepare_fixture_line(line)
103
+ line = line.sub('IGNORE_TEST(', '')
104
+ line = line.sub('TEST(', '')
105
+ line = line.sub(')', ',')
106
+ line = line.chomp
107
+ array = line.split(',')
108
+ array.map { |x| x.to_s.lstrip.chomp }
109
+ end
110
+
111
+ # Test was flagged as having passed so format the output.
112
+ # This is using the Unity fixture output and not the original Unity output.
113
+ def test_passed_unity_fixture(array)
114
+ class_name = array[0]
115
+ test_name = array[1]
116
+ test_suite_verify(class_name)
117
+ printf "%-40s PASS\n", test_name
118
+
119
+ push_xml_output_passed(test_name) if @xml_out
120
+ end
121
+
122
+ # Test was flagged as having failed so format the output.
123
+ # This is using the Unity fixture output and not the original Unity output.
124
+ def test_failed_unity_fixture(array)
125
+ class_name = array[0]
126
+ test_name = array[1]
127
+ test_suite_verify(class_name)
128
+ reason_array = array[2].split(':')
129
+ reason = reason_array[-1].lstrip.chomp + ' at line: ' + reason_array[-4]
130
+
131
+ printf "%-40s FAILED\n", test_name
132
+
133
+ push_xml_output_failed(test_name, reason) if @xml_out
134
+ end
135
+
136
+ # Test was flagged as being ignored so format the output.
137
+ # This is using the Unity fixture output and not the original Unity output.
138
+ def test_ignored_unity_fixture(array)
139
+ class_name = array[0]
140
+ test_name = array[1]
141
+ reason = 'No reason given'
142
+ if array.size > 2
143
+ reason_array = array[2].split(':')
144
+ tmp_reason = reason_array[-1].lstrip.chomp
145
+ reason = tmp_reason == 'IGNORE' ? 'No reason given' : tmp_reason
146
+ end
147
+ test_suite_verify(class_name)
148
+ printf "%-40s IGNORED\n", test_name
149
+
150
+ push_xml_output_ignored(test_name, reason) if @xml_out
151
+ end
152
+
153
+ # Test was flagged as having passed so format the output
154
+ def test_passed(array)
155
+ last_item = array.length - 1
156
+ test_name = array[last_item - 1]
157
+ test_suite_verify(array[@class_name_idx])
158
+ printf "%-40s PASS\n", test_name
159
+
160
+ return unless @xml_out
161
+
162
+ push_xml_output_passed(test_name) if @xml_out
163
+ end
164
+
165
+ # Test was flagged as having failed so format the line
166
+ def test_failed(array)
167
+ last_item = array.length - 1
168
+ test_name = array[last_item - 2]
169
+ reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3]
170
+ class_name = array[@class_name_idx]
171
+
172
+ if test_name.start_with? 'TEST('
173
+ array2 = test_name.split(' ')
174
+
175
+ test_suite = array2[0].sub('TEST(', '')
176
+ test_suite = test_suite.sub(',', '')
177
+ class_name = test_suite
178
+
179
+ test_name = array2[1].sub(')', '')
180
+ end
181
+
182
+ test_suite_verify(class_name)
183
+ printf "%-40s FAILED\n", test_name
184
+
185
+ push_xml_output_failed(test_name, reason) if @xml_out
186
+ end
187
+
188
+ # Test was flagged as being ignored so format the output
189
+ def test_ignored(array)
190
+ last_item = array.length - 1
191
+ test_name = array[last_item - 2]
192
+ reason = array[last_item].chomp.lstrip
193
+ class_name = array[@class_name_idx]
194
+
195
+ if test_name.start_with? 'TEST('
196
+ array2 = test_name.split(' ')
197
+
198
+ test_suite = array2[0].sub('TEST(', '')
199
+ test_suite = test_suite.sub(',', '')
200
+ class_name = test_suite
201
+
202
+ test_name = array2[1].sub(')', '')
203
+ end
204
+
205
+ test_suite_verify(class_name)
206
+ printf "%-40s IGNORED\n", test_name
207
+
208
+ push_xml_output_ignored(test_name, reason) if @xml_out
209
+ end
210
+
211
+ # Adjusts the os specific members according to the current path style
212
+ # (Windows or Unix based)
213
+ def set_os_specifics(line)
214
+ if line.include? '\\'
215
+ # Windows X:\Y\Z
216
+ @class_name_idx = 1
217
+ @path_delim = '\\'
218
+ else
219
+ # Unix Based /X/Y/Z
220
+ @class_name_idx = 0
221
+ @path_delim = '/'
222
+ end
223
+ end
224
+
225
+ # Main function used to parse the file that was captured.
226
+ def process(file_name)
227
+ @array_list = []
228
+
229
+ puts 'Parsing file: ' + file_name
230
+
231
+ @test_passed = 0
232
+ @test_failed = 0
233
+ @test_ignored = 0
234
+ puts ''
235
+ puts '=================== RESULTS ====================='
236
+ puts ''
237
+ File.open(file_name).each do |line|
238
+ # Typical test lines look like these:
239
+ # ----------------------------------------------------
240
+ # 1. normal output:
241
+ # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
242
+ # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
243
+ # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
244
+ #
245
+ # 2. fixture output
246
+ # <path>/<test_file>.c:63:TEST(<test_group>, <test_function>):FAIL: Expected 0x00001234 Was 0x00005A5A
247
+ # <path>/<test_file>.c:36:TEST(<test_group>, <test_function>):IGNORE
248
+ # Note: "PASS" information won't be generated in this mode
249
+ #
250
+ # 3. fixture output with verbose information ("-v")
251
+ # TEST(<test_group, <test_file>)<path>/<test_file>:168::FAIL: Expected 0x8D Was 0x8C
252
+ # TEST(<test_group>, <test_file>)<path>/<test_file>:22::IGNORE: This Test Was Ignored On Purpose
253
+ # IGNORE_TEST(<test_group, <test_file>)
254
+ # TEST(<test_group, <test_file>) PASS
255
+ #
256
+ # Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)!
257
+ set_os_specifics(line)
258
+ line_array = line.split(':')
259
+
260
+ # If we were able to split the line then we can look to see if any of our target words
261
+ # were found. Case is important.
262
+ if (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
263
+
264
+ # check if the output is fixture output (with verbose flag "-v")
265
+ if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
266
+ line_array = prepare_fixture_line(line)
267
+ if line.include? ' PASS'
268
+ test_passed_unity_fixture(line_array)
269
+ @test_passed += 1
270
+ elsif line.include? 'FAIL'
271
+ test_failed_unity_fixture(line_array)
272
+ @test_failed += 1
273
+ elsif line.include? 'IGNORE'
274
+ test_ignored_unity_fixture(line_array)
275
+ @test_ignored += 1
276
+ end
277
+ # normal output / fixture output (without verbose "-v")
278
+ elsif line.include? ':PASS'
279
+ test_passed(line_array)
280
+ @test_passed += 1
281
+ elsif line.include? ':FAIL'
282
+ test_failed(line_array)
283
+ @test_failed += 1
284
+ elsif line.include? ':IGNORE:'
285
+ test_ignored(line_array)
286
+ @test_ignored += 1
287
+ elsif line.include? ':IGNORE'
288
+ line_array.push('No reason given')
289
+ test_ignored(line_array)
290
+ @test_ignored += 1
291
+ end
292
+ @total_tests = @test_passed + @test_failed + @test_ignored
293
+ end
294
+ end
295
+ puts ''
296
+ puts '=================== SUMMARY ====================='
297
+ puts ''
298
+ puts 'Tests Passed : ' + @test_passed.to_s
299
+ puts 'Tests Failed : ' + @test_failed.to_s
300
+ puts 'Tests Ignored : ' + @test_ignored.to_s
301
+
302
+ return unless @xml_out
303
+
304
+ # push information about the suite
305
+ push_xml_output_suite_info
306
+ # write xml output file
307
+ write_xml_output
308
+ end
309
+ end
310
+
311
+ # If the command line has no values in, used a default value of Output.txt
312
+ parse_my_file = ParseOutput.new
313
+
314
+ if ARGV.size >= 1
315
+ ARGV.each do |arg|
316
+ if arg == '-xml'
317
+ parse_my_file.set_xml_output
318
+ else
319
+ parse_my_file.process(arg)
320
+ break
321
+ end
322
+ end
323
+ end
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # unity_to_junit.rb
4
+ #
5
+ require 'fileutils'
6
+ require 'optparse'
7
+ require 'ostruct'
8
+ require 'set'
9
+
10
+ require 'pp'
11
+
12
+ VERSION = 1.0
13
+
14
+ class ArgvParser
15
+ #
16
+ # Return a structure describing the options.
17
+ #
18
+ def self.parse(args)
19
+ # The options specified on the command line will be collected in *options*.
20
+ # We set default values here.
21
+ options = OpenStruct.new
22
+ options.results_dir = '.'
23
+ options.root_path = '.'
24
+ options.out_file = 'results.xml'
25
+
26
+ opts = OptionParser.new do |o|
27
+ o.banner = 'Usage: unity_to_junit.rb [options]'
28
+
29
+ o.separator ''
30
+ o.separator 'Specific options:'
31
+
32
+ o.on('-r', '--results <dir>', 'Look for Unity Results files here.') do |results|
33
+ # puts "results #{results}"
34
+ options.results_dir = results
35
+ end
36
+
37
+ o.on('-p', '--root_path <path>', 'Prepend this path to files in results.') do |root_path|
38
+ options.root_path = root_path
39
+ end
40
+
41
+ o.on('-o', '--output <filename>', 'XML file to generate.') do |out_file|
42
+ # puts "out_file: #{out_file}"
43
+ options.out_file = out_file
44
+ end
45
+
46
+ o.separator ''
47
+ o.separator 'Common options:'
48
+
49
+ # No argument, shows at tail. This will print an options summary.
50
+ o.on_tail('-h', '--help', 'Show this message') do
51
+ puts o
52
+ exit
53
+ end
54
+
55
+ # Another typical switch to print the version.
56
+ o.on_tail('--version', 'Show version') do
57
+ puts "unity_to_junit.rb version #{VERSION}"
58
+ exit
59
+ end
60
+ end
61
+
62
+ opts.parse!(args)
63
+ options
64
+ end # parse()
65
+ end # class OptparseExample
66
+
67
+ class UnityToJUnit
68
+ include FileUtils::Verbose
69
+ attr_reader :report, :total_tests, :failures, :ignored
70
+ attr_writer :targets, :root, :out_file
71
+
72
+ def initialize
73
+ @report = ''
74
+ @unit_name = ''
75
+ end
76
+
77
+ def run
78
+ # Clean up result file names
79
+ results = @targets.map { |target| target.tr('\\', '/') }
80
+ # puts "Output File: #{@out_file}"
81
+ f = File.new(@out_file, 'w')
82
+ write_xml_header(f)
83
+ write_suites_header(f)
84
+ results.each do |result_file|
85
+ lines = File.readlines(result_file).map(&:chomp)
86
+
87
+ raise "Empty test result file: #{result_file}" if lines.empty?
88
+
89
+ result_output = get_details(result_file, lines)
90
+ tests, failures, ignored = parse_test_summary(lines)
91
+ result_output[:counts][:total] = tests
92
+ result_output[:counts][:failed] = failures
93
+ result_output[:counts][:ignored] = ignored
94
+ result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored])
95
+
96
+ # use line[0] from the test output to get the test_file path and name
97
+ test_file_str = lines[0].tr('\\', '/')
98
+ test_file_str = test_file_str.split(':')
99
+ test_file = if test_file_str.length < 2
100
+ result_file
101
+ else
102
+ test_file_str[0] + ':' + test_file_str[1]
103
+ end
104
+ result_output[:source][:path] = File.dirname(test_file)
105
+ result_output[:source][:file] = File.basename(test_file)
106
+
107
+ # save result_output
108
+ @unit_name = File.basename(test_file, '.*')
109
+
110
+ write_suite_header(result_output[:counts], f)
111
+ write_failures(result_output, f)
112
+ write_tests(result_output, f)
113
+ write_ignored(result_output, f)
114
+ write_suite_footer(f)
115
+ end
116
+ write_suites_footer(f)
117
+ f.close
118
+ end
119
+
120
+ def usage(err_msg = nil)
121
+ puts "\nERROR: "
122
+ puts err_msg if err_msg
123
+ puts 'Usage: unity_to_junit.rb [options]'
124
+ puts ''
125
+ puts 'Specific options:'
126
+ puts ' -r, --results <dir> Look for Unity Results files here.'
127
+ puts ' -p, --root_path <path> Prepend this path to files in results.'
128
+ puts ' -o, --output <filename> XML file to generate.'
129
+ puts ''
130
+ puts 'Common options:'
131
+ puts ' -h, --help Show this message'
132
+ puts ' --version Show version'
133
+
134
+ exit 1
135
+ end
136
+
137
+ protected
138
+
139
+ def get_details(_result_file, lines)
140
+ results = results_structure
141
+ lines.each do |line|
142
+ line = line.tr('\\', '/')
143
+ _src_file, src_line, test_name, status, msg = line.split(/:/)
144
+ case status
145
+ when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg }
146
+ when 'FAIL' then results[:failures] << { test: test_name, line: src_line, message: msg }
147
+ when 'PASS' then results[:successes] << { test: test_name, line: src_line, message: msg }
148
+ end
149
+ end
150
+ results
151
+ end
152
+
153
+ def parse_test_summary(summary)
154
+ raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
155
+ [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i]
156
+ end
157
+
158
+ def here
159
+ File.expand_path(File.dirname(__FILE__))
160
+ end
161
+
162
+ private
163
+
164
+ def results_structure
165
+ {
166
+ source: { path: '', file: '' },
167
+ successes: [],
168
+ failures: [],
169
+ ignores: [],
170
+ counts: { total: 0, passed: 0, failed: 0, ignored: 0 },
171
+ stdout: []
172
+ }
173
+ end
174
+
175
+ def write_xml_header(stream)
176
+ stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
177
+ end
178
+
179
+ def write_suites_header(stream)
180
+ stream.puts '<testsuites>'
181
+ end
182
+
183
+ def write_suite_header(counts, stream)
184
+ stream.puts "\t<testsuite errors=\"0\" skipped=\"#{counts[:ignored]}\" failures=\"#{counts[:failed]}\" tests=\"#{counts[:total]}\" name=\"unity\">"
185
+ end
186
+
187
+ def write_failures(results, stream)
188
+ result = results[:failures]
189
+ result.each do |item|
190
+ filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
191
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
192
+ stream.puts "\t\t\t<failure message=\"#{item[:message]}\" type=\"Assertion\"/>"
193
+ stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
194
+ stream.puts "\t\t</testcase>"
195
+ end
196
+ end
197
+
198
+ def write_tests(results, stream)
199
+ result = results[:successes]
200
+ result.each do |item|
201
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\" />"
202
+ end
203
+ end
204
+
205
+ def write_ignored(results, stream)
206
+ result = results[:ignores]
207
+ result.each do |item|
208
+ filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
209
+ puts "Writing ignored tests for test harness: #{filename}"
210
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
211
+ stream.puts "\t\t\t<skipped message=\"#{item[:message]}\" type=\"Assertion\"/>"
212
+ stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
213
+ stream.puts "\t\t</testcase>"
214
+ end
215
+ end
216
+
217
+ def write_suite_footer(stream)
218
+ stream.puts "\t</testsuite>"
219
+ end
220
+
221
+ def write_suites_footer(stream)
222
+ stream.puts '</testsuites>'
223
+ end
224
+ end # UnityToJUnit
225
+
226
+ if __FILE__ == $0
227
+ # parse out the command options
228
+ options = ArgvParser.parse(ARGV)
229
+
230
+ # create an instance to work with
231
+ utj = UnityToJUnit.new
232
+ begin
233
+ # look in the specified or current directory for result files
234
+ targets = "#{options.results_dir.tr('\\', '/')}**/*.test*"
235
+
236
+ results = Dir[targets]
237
+ raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
238
+ utj.targets = results
239
+
240
+ # set the root path
241
+ utj.root = options.root_path
242
+
243
+ # set the output XML file name
244
+ # puts "Output File from options: #{options.out_file}"
245
+ utj.out_file = options.out_file
246
+
247
+ # run the summarizer
248
+ puts utj.run
249
+ rescue StandardError => e
250
+ utj.usage e.message
251
+ end
252
+ end