summaryrefslogtreecommitdiffstats
path: root/tinyusb/test
diff options
context:
space:
mode:
Diffstat (limited to 'tinyusb/test')
-rwxr-xr-xtinyusb/test/ceedling3
-rwxr-xr-xtinyusb/test/project.yml106
-rwxr-xr-xtinyusb/test/test/device/msc/test_msc_device.c273
-rwxr-xr-xtinyusb/test/test/device/usbd/test_usbd.c243
-rwxr-xr-xtinyusb/test/test/support/tusb_config.h106
-rwxr-xr-xtinyusb/test/test/test_fifo.c318
-rwxr-xr-xtinyusb/test/vendor/ceedling/bin/ceedling337
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/CException.md292
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/CMock_Summary.md603
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/CeedlingPacket.md2060
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/ThrowTheSwitchCodingStandard.md206
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdfbin0 -> 144467 bytes
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/UnityAssertionsReference.md779
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/UnityConfigurationGuide.md433
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/UnityGettingStartedGuide.md192
-rwxr-xr-xtinyusb/test/vendor/ceedling/docs/UnityHelperScriptsGuide.md260
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling.rb99
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/build_invoker_utils.rb39
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/cacheinator.rb47
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/cacheinator_helper.rb31
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/cmock_builder.rb15
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/configurator.rb363
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/configurator_builder.rb458
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/configurator_plugins.rb111
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/configurator_setup.rb127
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/configurator_validator.rb193
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/constants.rb97
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/defaults.rb418
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/dependinator.rb98
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/erb_wrapper.rb9
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/file_finder.rb149
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/file_finder_helper.rb54
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/file_path_utils.rb200
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/file_system_utils.rb69
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/file_system_wrapper.rb10
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/file_wrapper.rb83
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/flaginator.rb74
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/generator.rb183
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/generator_helper.rb40
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results.rb89
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results_sanity_checker.rb65
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/generator_test_runner.rb56
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/loginator.rb31
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/makefile.rb46
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/objects.yml310
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/par_map.rb19
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/plugin.rb80
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/plugin_builder.rb53
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager.rb107
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager_helper.rb19
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator.rb76
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb51
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator.rb42
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb30
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb21
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb46
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb181
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/project_config_manager.rb46
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/project_file_loader.rb99
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rake_utils.rb17
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rake_wrapper.rb33
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rakefile.rb86
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/release_invoker.rb73
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/release_invoker_helper.rb19
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/reportinator.rb26
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rules_cmock.rake9
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rules_preprocess.rake26
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rules_release.rake86
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake15
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rules_tests.rake74
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake15
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/setupinator.rb53
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/stream_wrapper.rb28
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/streaminator.rb40
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/streaminator_helper.rb15
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/system_utils.rb37
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/system_wrapper.rb80
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/target_loader.rb38
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/task_invoker.rb117
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tasks_base.rake111
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tasks_filesystem.rake103
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tasks_release.rake30
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake9
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests.rake60
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake9
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tasks_vendor.rake35
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/test_includes_extractor.rb85
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/test_invoker.rb188
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/test_invoker_helper.rb32
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tool_executor.rb229
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/tool_executor_helper.rb164
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/verbosinator.rb10
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/version.rb36
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/version.rb.erb15
-rwxr-xr-xtinyusb/test/vendor/ceedling/lib/ceedling/yaml_wrapper.rb17
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/beep/README.md22
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/beep/lib/beep.rb40
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/bullseye/assets/template.erb15
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/bullseye/bullseye.rake169
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/bullseye/config/defaults.yml57
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb194
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/bullseye/readme.txt0
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/colour_report/lib/colour_report.rb16
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/command_hooks/README.md53
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb92
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md250
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile19
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml71
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb7
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c1
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h14
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h6
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c7
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h16
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c93
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h11
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c16
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h8
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c1
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h6
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c155
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c47
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb87
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb163
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb304
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb149
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb51
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb96
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h33
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/gcov/README.md101
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/gcov/assets/template.erb15
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/gcov/config/defaults.yml73
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/gcov/gcov.rake220
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov.rb113
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb19
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/junit_tests_report/README.md36
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb129
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/module_generator/config/module_generator.yml4
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb70
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/module_generator/module_generator.rake47
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb41
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb84
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy59
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/config/stdout_gtestlike_tests_report.yml4
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb43
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml4
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb44
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb59
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/config/stdout_pretty_tests_report.yml4
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb47
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/subprojects/README.md63
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/subprojects/config/defaults.yml33
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb92
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/subprojects/subprojects.rake78
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml4
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb57
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb69
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/xml_tests_report/README.md36
-rwxr-xr-xtinyusb/test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb110
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.c46
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.h115
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/c_exception/release/build.info2
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/c_exception/release/version.info2
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/config/production_environment.rb14
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/config/test_environment.rb16
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock.rb86
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_config.rb153
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_file_writer.rb44
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb268
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_array.rb63
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_callback.rb88
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_cexception.rb51
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect.rb103
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect_any_args.rb53
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore.rb75
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb42
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb79
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_utils.rb253
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb364
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_plugin_manager.rb55
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_unityhelper_parser.rb75
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/release/build.info2
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/release/version.info2
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.c216
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.h40
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/src/cmock_internals.h91
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/cmock/src/meson.build17
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/deep_merge/lib/deep_merge.rb211
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/diy/lib/diy.rb403
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/diy/lib/diy/factory.rb36
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/colour_prompt.rb119
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/colour_reporter.rb39
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/generate_config.yml36
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/generate_module.rb309
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb495
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/parse_output.rb322
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/run_test.erb36
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/stylize_as_junit.rb251
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/test_file_filter.rb25
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/type_sanitizer.rb6
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.py139
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.rb135
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/auto/unity_to_junit.py146
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/release/build.info2
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/release/version.info2
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/src/CMakeLists.txt22
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/src/meson.build16
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/src/unity.c2085
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/src/unity.h617
-rwxr-xr-xtinyusb/test/vendor/ceedling/vendor/unity/src/unity_internals.h1002
210 files changed, 25561 insertions, 0 deletions
diff --git a/tinyusb/test/ceedling b/tinyusb/test/ceedling
new file mode 100755
index 00000000..53930857
--- /dev/null
+++ b/tinyusb/test/ceedling
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+ruby vendor/ceedling/bin/ceedling $*
diff --git a/tinyusb/test/project.yml b/tinyusb/test/project.yml
new file mode 100755
index 00000000..dc4a9cb2
--- /dev/null
+++ b/tinyusb/test/project.yml
@@ -0,0 +1,106 @@
+---
+
+# Notes:
+# Sample project C code is not presently written to produce a release artifact.
+# As such, release build options are disabled.
+# This sample, therefore, only demonstrates running a collection of unit tests.
+
+:project:
+ :use_exceptions: TRUE
+ :use_mocks: TRUE
+ :use_test_preprocessor: TRUE
+ :use_auxiliary_dependencies: TRUE
+ :use_deep_dependencies: TRUE
+ :build_root: _build
+# :release_build: TRUE
+ :test_file_prefix: test_
+ :which_ceedling: vendor/ceedling
+ :default_tasks:
+ - test:all
+
+#:test_build:
+# :use_assembly: TRUE
+
+#:release_build:
+# :output: MyApp.out
+# :use_assembly: FALSE
+
+:environment:
+
+:extension:
+ :executable: .out
+
+:paths:
+ :test:
+ - +:test/**
+ - -:test/support
+ :source:
+ - ../src/**
+ :support:
+ - test/support
+
+:defines:
+ # in order to add common defines:
+ # 1) remove the trailing [] from the :common: section
+ # 2) add entries to the :common: section (e.g. :test: has TEST defined)
+ :common: &common_defines
+ - _UNITY_TEST_
+ :test:
+ - *common_defines
+ :test_preprocess:
+ - *common_defines
+
+:cmock:
+ :mock_prefix: mock_
+ :when_no_prototypes: :warn
+ :enforce_strict_ordering: TRUE
+ :plugins:
+ - :ignore
+ - :ignore_arg
+ - :return_thru_ptr
+ - :callback
+ - :array
+ :treat_as:
+ uint8: HEX8
+ uint16: HEX16
+ uint32: UINT32
+ int8: INT8
+ bool: UINT8
+
+# Add -gcov to the plugins list to make sure of the gcov plugin
+# You will need to have gcov and gcovr both installed to make it work.
+# For more information on these options, see docs in plugins/gcov
+:gcov:
+ :html_report: TRUE
+ :html_report_type: detailed
+ :html_medium_threshold: 75
+ :html_high_threshold: 90
+ :xml_report: FALSE
+
+#:tools:
+# Ceedling defaults to using gcc for compiling, linking, etc.
+# As [:tools] is blank, gcc will be used (so long as it's in your system path)
+# See documentation to configure a given toolchain for use
+
+# LIBRARIES
+# These libraries are automatically injected into the build process. Those specified as
+# common will be used in all types of builds. Otherwise, libraries can be injected in just
+# tests or releases. These options are MERGED with the options in supplemental yaml files.
+:libraries:
+ :placement: :end
+ :flag: "${1}" # or "-L ${1}" for example
+ :common: &common_libraries []
+ :test:
+ - *common_libraries
+ :release:
+ - *common_libraries
+
+:plugins:
+ :load_paths:
+ - vendor/ceedling/plugins
+ :enabled:
+ - stdout_pretty_tests_report
+ - module_generator
+ - raw_output_report
+ - colour_report
+...
diff --git a/tinyusb/test/test/device/msc/test_msc_device.c b/tinyusb/test/test/device/msc/test_msc_device.c
new file mode 100755
index 00000000..00bb86cc
--- /dev/null
+++ b/tinyusb/test/test/device/msc/test_msc_device.c
@@ -0,0 +1,273 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019, hathach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+
+#include "unity.h"
+
+// Files to test
+#include "tusb_fifo.h"
+#include "tusb.h"
+#include "usbd.h"
+TEST_FILE("usbd_control.c")
+TEST_FILE("msc_device.c")
+
+// Mock File
+#include "mock_dcd.h"
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+
+enum
+{
+ EDPT_CTRL_OUT = 0x00,
+ EDPT_CTRL_IN = 0x80,
+
+ EDPT_MSC_OUT = 0x01,
+ EDPT_MSC_IN = 0x81,
+};
+
+uint8_t const rhport = 0;
+
+enum
+{
+ ITF_NUM_MSC,
+ ITF_NUM_TOTAL
+};
+
+#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN)
+
+uint8_t const data_desc_configuration[] =
+{
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+
+ // Interface number, string index, EP Out & EP In address, EP size
+ TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EDPT_MSC_OUT, EDPT_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64),
+};
+
+tusb_control_request_t const request_set_configuration =
+{
+ .bmRequestType = 0x00,
+ .bRequest = TUSB_REQ_SET_CONFIGURATION,
+ .wValue = 1,
+ .wIndex = 0,
+ .wLength = 0
+};
+
+uint8_t const* desc_configuration;
+
+
+enum
+{
+ DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount
+ DISK_BLOCK_SIZE = 512
+};
+
+uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE];
+
+// Invoked when received SCSI_CMD_INQUIRY
+// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
+void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
+{
+ (void) lun;
+
+ const char vid[] = "TinyUSB";
+ const char pid[] = "Mass Storage";
+ const char rev[] = "1.0";
+
+ memcpy(vendor_id , vid, strlen(vid));
+ memcpy(product_id , pid, strlen(pid));
+ memcpy(product_rev, rev, strlen(rev));
+}
+
+// Invoked when received Test Unit Ready command.
+// return true allowing host to read/write this LUN e.g SD card inserted
+bool tud_msc_test_unit_ready_cb(uint8_t lun)
+{
+ (void) lun;
+
+ return true; // RAM disk is always ready
+}
+
+// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
+// Application update block count and block size
+void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
+{
+ (void) lun;
+
+ *block_count = DISK_BLOCK_NUM;
+ *block_size = DISK_BLOCK_SIZE;
+}
+
+// Invoked when received Start Stop Unit command
+// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
+// - Start = 1 : active mode, if load_eject = 1 : load disk storage
+bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
+{
+ (void) lun;
+ (void) power_condition;
+
+ return true;
+}
+
+// Callback invoked when received READ10 command.
+// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
+int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
+{
+ (void) lun;
+
+ uint8_t const* addr = msc_disk[lba] + offset;
+ memcpy(buffer, addr, bufsize);
+
+ return bufsize;
+}
+
+// Callback invoked when received WRITE10 command.
+// Process data in buffer to disk's storage and return number of written bytes
+int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
+{
+ (void) lun;
+
+ uint8_t* addr = msc_disk[lba] + offset;
+ memcpy(addr, buffer, bufsize);
+
+ return bufsize;
+}
+
+// Callback invoked when received an SCSI command not in built-in list below
+// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
+// - READ10 and WRITE10 has their own callbacks
+int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
+{
+ // read10 & write10 has their own callback and MUST not be handled here
+
+ void const* response = NULL;
+ uint16_t resplen = 0;
+
+ return resplen;
+}
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+uint8_t const * tud_descriptor_device_cb(void)
+{
+ return NULL;
+}
+
+uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
+{
+ return desc_configuration;
+}
+
+uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
+{
+ (void) langid;
+
+ return NULL;
+}
+
+void setUp(void)
+{
+ dcd_int_disable_Ignore();
+ dcd_int_enable_Ignore();
+
+ if ( !tusb_inited() )
+ {
+ dcd_init_Expect(rhport);
+ tusb_init();
+ }
+
+ dcd_event_bus_reset(rhport, TUSB_SPEED_HIGH, false);
+ tud_task();
+}
+
+void tearDown(void)
+{
+}
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+void test_msc(void)
+{
+ // Read 1 LBA = 0, Block count = 1
+ msc_cbw_t cbw_read10 =
+ {
+ .signature = MSC_CBW_SIGNATURE,
+ .tag = 0xCAFECAFE,
+ .total_bytes = 512,
+ .lun = 0,
+ .dir = TUSB_DIR_IN_MASK,
+ .cmd_len = sizeof(scsi_read10_t)
+ };
+
+ scsi_read10_t cmd_read10 =
+ {
+ .cmd_code = SCSI_CMD_READ_10,
+ .lba = tu_htonl(0),
+ .block_count = tu_htons(1)
+ };
+
+ memcpy(cbw_read10.command, &cmd_read10, cbw_read10.cmd_len);
+
+ desc_configuration = data_desc_configuration;
+ uint8_t const* desc_ep = tu_desc_next(tu_desc_next(desc_configuration));
+
+ dcd_event_setup_received(rhport, (uint8_t*) &request_set_configuration, false);
+
+ // open endpoints
+ dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) desc_ep, true);
+ dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep), true);
+
+ // Prepare SCSI command
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true);
+ dcd_edpt_xfer_IgnoreArg_buffer();
+ dcd_edpt_xfer_ReturnMemThruPtr_buffer( (uint8_t*) &cbw_read10, sizeof(msc_cbw_t));
+
+ // command received
+ dcd_event_xfer_complete(rhport, EDPT_MSC_OUT, sizeof(msc_cbw_t), 0, true);
+
+ // control status
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true);
+
+ // SCSI Data transfer
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 512, true);
+ dcd_edpt_xfer_IgnoreArg_buffer();
+ dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 512, 0, true); // complete
+
+ // SCSI Status
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 13, true);
+ dcd_edpt_xfer_IgnoreArg_buffer();
+ dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 13, 0, true);
+
+ // Prepare for next command
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true);
+ dcd_edpt_xfer_IgnoreArg_buffer();
+
+ tud_task();
+}
diff --git a/tinyusb/test/test/device/usbd/test_usbd.c b/tinyusb/test/test/device/usbd/test_usbd.c
new file mode 100755
index 00000000..c90383b5
--- /dev/null
+++ b/tinyusb/test/test/device/usbd/test_usbd.c
@@ -0,0 +1,243 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "unity.h"
+
+// Files to test
+#include "tusb_fifo.h"
+#include "tusb.h"
+#include "usbd.h"
+TEST_FILE("usbd_control.c")
+
+// Mock File
+#include "mock_dcd.h"
+#include "mock_msc_device.h"
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+
+enum
+{
+ EDPT_CTRL_OUT = 0x00,
+ EDPT_CTRL_IN = 0x80
+};
+
+uint8_t const rhport = 0;
+
+tusb_desc_device_t const data_desc_device =
+{
+ .bLength = sizeof(tusb_desc_device_t),
+ .bDescriptorType = TUSB_DESC_DEVICE,
+ .bcdUSB = 0x0200,
+
+ // Use Interface Association Descriptor (IAD) for CDC
+ // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
+
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+
+ .idVendor = 0xCafe,
+ .idProduct = 0xCafe,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01
+};
+
+uint8_t const data_desc_configuration[] =
+{
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+};
+
+tusb_control_request_t const req_get_desc_device =
+{
+ .bmRequestType = 0x80,
+ .bRequest = TUSB_REQ_GET_DESCRIPTOR,
+ .wValue = (TUSB_DESC_DEVICE << 8),
+ .wIndex = 0x0000,
+ .wLength = 64
+};
+
+tusb_control_request_t const req_get_desc_configuration =
+{
+ .bmRequestType = 0x80,
+ .bRequest = TUSB_REQ_GET_DESCRIPTOR,
+ .wValue = (TUSB_DESC_CONFIGURATION << 8),
+ .wIndex = 0x0000,
+ .wLength = 256
+};
+
+uint8_t const* desc_device;
+uint8_t const* desc_configuration;
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+uint8_t const * tud_descriptor_device_cb(void)
+{
+ return desc_device;
+}
+
+uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
+{
+ return desc_configuration;
+}
+
+uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
+{
+ (void) langid;
+
+ return NULL;
+}
+
+void setUp(void)
+{
+ dcd_int_disable_Ignore();
+ dcd_int_enable_Ignore();
+
+ if ( !tusb_inited() )
+ {
+ mscd_init_Expect();
+ dcd_init_Expect(rhport);
+ tusb_init();
+ }
+}
+
+void tearDown(void)
+{
+}
+
+//--------------------------------------------------------------------+
+// Get Descriptor
+//--------------------------------------------------------------------+
+
+//------------- Device -------------//
+void test_usbd_get_device_descriptor(void)
+{
+ desc_device = (uint8_t const *) &data_desc_device;
+ dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false);
+
+ // data
+ dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*)&data_desc_device, sizeof(tusb_desc_device_t), sizeof(tusb_desc_device_t), true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, sizeof(tusb_desc_device_t), 0, false);
+
+ // status
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false);
+ dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_device, 1);
+
+ tud_task();
+}
+
+void test_usbd_get_device_descriptor_null(void)
+{
+ desc_device = NULL;
+
+ dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false);
+
+ dcd_edpt_stall_Expect(rhport, EDPT_CTRL_OUT);
+ dcd_edpt_stall_Expect(rhport, EDPT_CTRL_IN);
+
+ tud_task();
+}
+
+//------------- Configuration -------------//
+
+void test_usbd_get_configuration_descriptor(void)
+{
+ desc_configuration = data_desc_configuration;
+ uint16_t total_len = ((tusb_desc_configuration_t const*) data_desc_configuration)->wTotalLength;
+
+ dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false);
+
+ // data
+ dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*) data_desc_configuration, total_len, total_len, true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, total_len, 0, false);
+
+ // status
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false);
+ dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1);
+
+ tud_task();
+}
+
+void test_usbd_get_configuration_descriptor_null(void)
+{
+ desc_configuration = NULL;
+ dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false);
+
+ dcd_edpt_stall_Expect(rhport, EDPT_CTRL_OUT);
+ dcd_edpt_stall_Expect(rhport, EDPT_CTRL_IN);
+
+ tud_task();
+}
+
+//--------------------------------------------------------------------+
+// Control ZLP
+//--------------------------------------------------------------------+
+
+void test_usbd_control_in_zlp(void)
+{
+ // 128 byte total len, with EP0 size = 64, and request length = 256
+ // ZLP must be return
+ uint8_t zlp_desc_configuration[CFG_TUD_ENDPOINT0_SIZE*2] =
+ {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, 0, 0, CFG_TUD_ENDPOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+ };
+
+ desc_configuration = zlp_desc_configuration;
+
+ // request, then 1st, 2nd xact + ZLP + status
+ dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false);
+
+ // 1st transaction
+ dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN,
+ zlp_desc_configuration, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false);
+
+ // 2nd transaction
+ dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN,
+ zlp_desc_configuration + CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false);
+
+ // Expect Zero length Packet
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, 0, 0, false);
+
+ // Status
+ dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true);
+ dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false);
+ dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1);
+
+ tud_task();
+}
diff --git a/tinyusb/test/test/support/tusb_config.h b/tinyusb/test/test/support/tusb_config.h
new file mode 100755
index 00000000..0455f933
--- /dev/null
+++ b/tinyusb/test/test/support/tusb_config.h
@@ -0,0 +1,106 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+// testing framework
+#include "unity.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+ //#error CFG_TUSB_MCU must be defined
+ #define CFG_TUSB_MCU OPT_MCU_NRF5X
+#endif
+
+#ifndef CFG_TUSB_RHPORT0_MODE
+#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
+#endif
+
+#define CFG_TUSB_OS OPT_OS_NONE
+
+// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
+#ifndef CFG_TUSB_DEBUG
+#define CFG_TUSB_DEBUG 0
+#endif
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUSB_MEM_SECTION
+#define CFG_TUSB_MEM_SECTION
+#endif
+
+#ifndef CFG_TUSB_MEM_ALIGN
+#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------
+
+#define CFG_TUD_TASK_QUEUE_SZ 100
+#define CFG_TUD_ENDPOINT0_SIZE 64
+
+//------------- CLASS -------------//
+//#define CFG_TUD_CDC 0
+#define CFG_TUD_MSC 1
+//#define CFG_TUD_HID 0
+//#define CFG_TUD_MIDI 0
+//#define CFG_TUD_VENDOR 0
+
+//------------- CDC -------------//
+
+// FIFO size of CDC TX and RX
+#define CFG_TUD_CDC_RX_BUFSIZE 512
+#define CFG_TUD_CDC_TX_BUFSIZE 512
+
+//------------- MSC -------------//
+
+// Buffer size of Device Mass storage
+#define CFG_TUD_MSC_BUFSIZE 512
+
+//------------- HID -------------//
+
+// Should be sufficient to hold ID (if any) + Data
+#define CFG_TUD_HID_EP_BUFSIZE 64
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/tinyusb/test/test/test_fifo.c b/tinyusb/test/test/test_fifo.c
new file mode 100755
index 00000000..0a5f4d3b
--- /dev/null
+++ b/tinyusb/test/test/test_fifo.c
@@ -0,0 +1,318 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include <string.h>
+#include "unity.h"
+#include "tusb_fifo.h"
+
+#define FIFO_SIZE 10
+TU_FIFO_DEF(tu_ff, FIFO_SIZE, uint8_t, false);
+tu_fifo_t* ff = &tu_ff;
+tu_fifo_buffer_info_t info;
+
+void setUp(void)
+{
+ tu_fifo_clear(ff);
+ memset(&info, 0, sizeof(tu_fifo_buffer_info_t));
+}
+
+void tearDown(void)
+{
+}
+
+//--------------------------------------------------------------------+
+// Tests
+//--------------------------------------------------------------------+
+void test_normal(void)
+{
+ for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i);
+
+ for(uint8_t i=0; i < FIFO_SIZE; i++)
+ {
+ uint8_t c;
+ tu_fifo_read(ff, &c);
+ TEST_ASSERT_EQUAL(i, c);
+ }
+}
+
+void test_item_size(void)
+{
+ TU_FIFO_DEF(ff4, FIFO_SIZE, uint32_t, false);
+ tu_fifo_clear(&ff4);
+
+ uint32_t data[20];
+ for(uint32_t i=0; i<sizeof(data)/4; i++) data[i] = i;
+
+ tu_fifo_write_n(&ff4, data, 10);
+
+ uint32_t rd[10];
+ uint16_t rd_count;
+
+ // read 0 -> 4
+ rd_count = tu_fifo_read_n(&ff4, rd, 5);
+ TEST_ASSERT_EQUAL( 5, rd_count );
+ TEST_ASSERT_EQUAL_UINT32_ARRAY( data, rd, rd_count ); // 0 -> 4
+
+ tu_fifo_write_n(&ff4, data+10, 5);
+
+ // read 5 -> 14
+ rd_count = tu_fifo_read_n(&ff4, rd, 10);
+ TEST_ASSERT_EQUAL( 10, rd_count );
+ TEST_ASSERT_EQUAL_UINT32_ARRAY( data+5, rd, rd_count ); // 5 -> 14
+}
+
+void test_read_n(void)
+{
+ // prepare data
+ uint8_t data[20];
+ for(int i=0; i<sizeof(data); i++) data[i] = i;
+
+ for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, data+i);
+
+ uint8_t rd[10];
+ uint16_t rd_count;
+
+ // case 1: Read index + count < depth
+ // read 0 -> 4
+ rd_count = tu_fifo_read_n(ff, rd, 5);
+ TEST_ASSERT_EQUAL( 5, rd_count );
+ TEST_ASSERT_EQUAL_MEMORY( data, rd, rd_count ); // 0 -> 4
+
+ // case 2: Read index + count > depth
+ // write 10, 11, 12
+ tu_fifo_write(ff, data+10);
+ tu_fifo_write(ff, data+11);
+ tu_fifo_write(ff, data+12);
+
+ rd_count = tu_fifo_read_n(ff, rd, 7);
+ TEST_ASSERT_EQUAL( 7, rd_count );
+
+ TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count ); // 5 -> 11
+
+ // Should only read until empty
+ TEST_ASSERT_EQUAL( 1, tu_fifo_read_n(ff, rd, 100) );
+}
+
+void test_write_n(void)
+{
+ // prepare data
+ uint8_t data[20];
+ for(int i=0; i<sizeof(data); i++) data[i] = i;
+
+ // case 1: wr + count < depth
+ tu_fifo_write_n(ff, data, 8); // wr = 8, count = 8
+
+ uint8_t rd[10];
+ uint16_t rd_count;
+
+ rd_count = tu_fifo_read_n(ff, rd, 5); // wr = 8, count = 3
+ TEST_ASSERT_EQUAL( 5, rd_count );
+ TEST_ASSERT_EQUAL_MEMORY( data, rd, rd_count ); // 0 -> 4
+
+ // case 2: wr + count > depth
+ tu_fifo_write_n(ff, data+8, 6); // wr = 3, count = 9
+
+ for(rd_count=0; rd_count<7; rd_count++) tu_fifo_read(ff, rd+rd_count); // wr = 3, count = 2
+
+ TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count); // 5 -> 11
+
+ TEST_ASSERT_EQUAL(2, tu_fifo_count(ff));
+}
+
+void test_peek(void)
+{
+ uint8_t temp;
+
+ temp = 10; tu_fifo_write(ff, &temp);
+ temp = 20; tu_fifo_write(ff, &temp);
+ temp = 30; tu_fifo_write(ff, &temp);
+
+ temp = 0;
+
+ tu_fifo_peek(ff, &temp);
+ TEST_ASSERT_EQUAL(10, temp);
+
+ tu_fifo_read(ff, &temp);
+ tu_fifo_read(ff, &temp);
+
+ tu_fifo_peek(ff, &temp);
+ TEST_ASSERT_EQUAL(30, temp);
+}
+
+void test_get_read_info_when_no_wrap()
+{
+ uint8_t ch = 1;
+
+ // write 6 items
+ for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch);
+
+ // read 2 items
+ tu_fifo_read(ff, &ch);
+ tu_fifo_read(ff, &ch);
+
+ tu_fifo_get_read_info(ff, &info);
+
+ TEST_ASSERT_EQUAL(4, info.len_lin);
+ TEST_ASSERT_EQUAL(0, info.len_wrap);
+
+ TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info.ptr_lin);
+ TEST_ASSERT_NULL(info.ptr_wrap);
+}
+
+void test_get_read_info_when_wrapped()
+{
+ uint8_t ch = 1;
+
+ // make fifo full
+ for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &ch);
+
+ // read 6 items
+ for(uint8_t i=0; i < 6; i++) tu_fifo_read(ff, &ch);
+
+ // write 2 items
+ tu_fifo_write(ff, &ch);
+ tu_fifo_write(ff, &ch);
+
+ tu_fifo_get_read_info(ff, &info);
+
+ TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin);
+ TEST_ASSERT_EQUAL(2, info.len_wrap);
+
+ TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info.ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap);
+}
+
+void test_get_write_info_when_no_wrap()
+{
+ uint8_t ch = 1;
+
+ // write 2 items
+ tu_fifo_write(ff, &ch);
+ tu_fifo_write(ff, &ch);
+
+ tu_fifo_get_write_info(ff, &info);
+
+ TEST_ASSERT_EQUAL(FIFO_SIZE-2, info.len_lin);
+ TEST_ASSERT_EQUAL(0, info.len_wrap);
+
+ TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info .ptr_lin);
+ // application should check len instead of ptr.
+ // TEST_ASSERT_NULL(info.ptr_wrap);
+}
+
+void test_get_write_info_when_wrapped()
+{
+ uint8_t ch = 1;
+
+ // write 6 items
+ for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch);
+
+ // read 2 items
+ tu_fifo_read(ff, &ch);
+ tu_fifo_read(ff, &ch);
+
+ tu_fifo_get_write_info(ff, &info);
+
+ TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin);
+ TEST_ASSERT_EQUAL(2, info.len_wrap);
+
+ TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info .ptr_lin);
+ TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap);
+}
+
+void test_empty(void)
+{
+ uint8_t temp;
+ TEST_ASSERT_TRUE(tu_fifo_empty(ff));
+
+ // read info
+ tu_fifo_get_read_info(ff, &info);
+
+ TEST_ASSERT_EQUAL(0, info.len_lin);
+ TEST_ASSERT_EQUAL(0, info.len_wrap);
+
+ TEST_ASSERT_NULL(info.ptr_lin);
+ TEST_ASSERT_NULL(info.ptr_wrap);
+
+ // write info
+ tu_fifo_get_write_info(ff, &info);
+
+ TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin);
+ TEST_ASSERT_EQUAL(0, info.len_wrap);
+
+ TEST_ASSERT_EQUAL_PTR(ff->buffer, info .ptr_lin);
+ // application should check len instead of ptr.
+ // TEST_ASSERT_NULL(info.ptr_wrap);
+
+ // write 1 then re-check empty
+ tu_fifo_write(ff, &temp);
+ TEST_ASSERT_FALSE(tu_fifo_empty(ff));
+}
+
+void test_full(void)
+{
+ TEST_ASSERT_FALSE(tu_fifo_full(ff));
+
+ for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i);
+
+ TEST_ASSERT_TRUE(tu_fifo_full(ff));
+
+ // read info
+ tu_fifo_get_read_info(ff, &info);
+
+ TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin);
+ TEST_ASSERT_EQUAL(0, info.len_wrap);
+
+ TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_lin);
+ // skip this, application must check len instead of buffer
+ // TEST_ASSERT_NULL(info.ptr_wrap);
+
+ // write info
+}
+
+void test_rd_idx_wrap()
+{
+ tu_fifo_t ff10;
+ uint8_t buf[10];
+ uint8_t dst[10];
+
+ tu_fifo_config(&ff10, buf, 10, 1, 1);
+
+ uint16_t n;
+
+ ff10.wr_idx = 6;
+ ff10.rd_idx = 15;
+
+ n = tu_fifo_read_n(&ff10, dst, 4);
+ TEST_ASSERT_EQUAL(n, 4);
+ TEST_ASSERT_EQUAL(ff10.rd_idx, 0);
+ n = tu_fifo_read_n(&ff10, dst, 4);
+ TEST_ASSERT_EQUAL(n, 4);
+ TEST_ASSERT_EQUAL(ff10.rd_idx, 4);
+ n = tu_fifo_read_n(&ff10, dst, 4);
+ TEST_ASSERT_EQUAL(n, 2);
+ TEST_ASSERT_EQUAL(ff10.rd_idx, 6);
+} \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/bin/ceedling b/tinyusb/test/vendor/ceedling/bin/ceedling
new file mode 100755
index 00000000..fa099590
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/bin/ceedling
@@ -0,0 +1,337 @@
+#!/usr/bin/env ruby
+
+#these are always used
+require 'rubygems'
+require 'fileutils'
+
+# Check for the main project file (either the one defined in the ENV or the default)
+main_filepath = ENV['CEEDLING_MAIN_PROJECT_FILE']
+project_found = (!main_filepath.nil? && File.exists?(main_filepath))
+if (!project_found)
+ main_filepath = "project.yml"
+ project_found = File.exists?(main_filepath)
+end
+
+def is_windows?
+ return ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) if defined?(RbConfig)
+ return ((Config::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false)
+end
+
+unless (project_found)
+#===================================== We Do Not Have A Project ================================================
+
+ puts "Welcome to Ceedling!"
+ require 'thor'
+
+ def here
+ File.dirname(__FILE__) + "/.."
+ end
+
+ class CeedlingTasks < Thor
+ include Thor::Actions
+
+ desc "new PROJECT_NAME", "create a new ceedling project"
+ method_option :docs, :type => :boolean, :default => false, :desc => "Add docs in project vendor directory"
+ method_option :local, :type => :boolean, :default => false, :desc => "Create a copy of Ceedling in the project vendor directory"
+ method_option :gitignore, :type => :boolean, :default => false, :desc => "Create a gitignore file for ignoring ceedling generated files"
+ method_option :no_configs, :type => :boolean, :default => false, :desc => "Don't install starter configuration files"
+ method_option :noconfigs, :type => :boolean, :default => false
+
+ #deprecated:
+ method_option :no_docs, :type => :boolean, :default => false
+ method_option :nodocs, :type => :boolean, :default => false
+ method_option :as_gem, :type => :boolean, :default => false
+ method_option :asgem, :type => :boolean, :default => false
+ method_option :with_ignore, :type => :boolean, :default => false
+ method_option :withignore, :type => :boolean, :default => false
+ def new(name, silent = false)
+ copy_assets_and_create_structure(name, silent, false, options)
+ end
+
+ desc "upgrade PROJECT_NAME", "upgrade ceedling for a project (not req'd if gem used)"
+ method_option :docs, :type => :boolean, :default => false, :desc => "Add docs in project vendor directory"
+ method_option :local, :type => :boolean, :default => false, :desc => "Create a copy of Ceedling in the project vendor directory"
+ method_option :no_configs, :type => :boolean, :default => false, :desc => "Don't install starter configuration files"
+ method_option :noconfigs, :type => :boolean, :default => false
+
+ #deprecated:
+ method_option :no_docs, :type => :boolean, :default => false
+ method_option :nodocs, :type => :boolean, :default => false
+ def upgrade(name, silent = false)
+ copy_assets_and_create_structure(name, silent, true, options || {:upgrade => true})
+ end
+
+ no_commands do
+ def copy_assets_and_create_structure(name, silent=false, force=false, options = {})
+
+ puts "WARNING: --no_docs deprecated. It is now the default. Specify -docs if you want docs installed." if (options[:no_docs] || options[:nodocs])
+ puts "WARNING: --as_gem deprecated. It is now the default. Specify -local if you want ceedling installed to this project." if (options[:as_gem] || options[:asgem])
+ puts "WARNING: --with_ignore deprecated. It is now called -gitignore" if (options[:with_ignore] || options[:with_ignore])
+
+ use_docs = options[:docs] || false
+ use_configs = !(options[:no_configs] || options[:noconfigs] || false)
+ use_gem = !(options[:local])
+ use_ignore = options[:gitignore] || false
+ is_upgrade = options[:upgrade] || false
+
+ ceedling_path = File.join(name, 'vendor', 'ceedling')
+ source_path = File.join(name, 'src')
+ test_path = File.join(name, 'test')
+ test_support_path = File.join(name, 'test/support')
+
+ # If it's not an upgrade, make sure we have the paths we expect
+ if (!is_upgrade)
+ [source_path, test_path, test_support_path].each do |d|
+ FileUtils.mkdir_p d
+ end
+ end
+
+ # Genarate gitkeep in test support path
+ FileUtils.touch(File.join(test_support_path, '.gitkeep'))
+
+ # If documentation requested, create a place to dump them and do so
+ if use_docs
+ doc_path = File.join(ceedling_path, 'docs')
+ FileUtils.mkdir_p doc_path
+
+ in_doc_path = lambda {|f| File.join(doc_path, f)}
+
+ doc_files = [
+ 'docs/CeedlingPacket.md',
+ 'vendor/c_exception/docs/CException.md',
+ 'vendor/cmock/docs/CMock_Summary.md',
+ 'vendor/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf',
+ 'vendor/unity/docs/UnityAssertionsReference.md',
+ 'vendor/unity/docs/UnityConfigurationGuide.md',
+ 'vendor/unity/docs/UnityGettingStartedGuide.md',
+ 'vendor/unity/docs/UnityHelperScriptsGuide.md',
+ 'vendor/unity/docs/ThrowTheSwitchCodingStandard.md',
+ ]
+
+ doc_files.each do |f|
+ copy_file(f, in_doc_path.call(File.basename(f)), :force => force)
+ end
+ end
+
+ # If installed locally to project, copy ceedling, unity, cmock, & supports to vendor
+ unless use_gem
+ FileUtils.mkdir_p ceedling_path
+
+ #copy full folders from ceedling gem into project
+ %w{plugins lib bin}.map do |f|
+ {:src => f, :dst => File.join(ceedling_path, f)}
+ end.each do |f|
+ directory(f[:src], f[:dst], :force => force)
+ end
+
+ # mark ceedling as an executable
+ File.chmod(0755, File.join(ceedling_path, 'bin', 'ceedling')) unless is_windows?
+
+ #copy necessary subcomponents from ceedling gem into project
+ sub_components = [
+ {:src => 'vendor/c_exception/lib/', :dst => 'vendor/c_exception/lib'},
+ {:src => 'vendor/cmock/config/', :dst => 'vendor/cmock/config'},
+ {:src => 'vendor/cmock/lib/', :dst => 'vendor/cmock/lib'},
+ {:src => 'vendor/cmock/src/', :dst => 'vendor/cmock/src'},
+ {:src => 'vendor/deep_merge/lib/', :dst => 'vendor/deep_merge/lib'},
+ {:src => 'vendor/diy/lib', :dst => 'vendor/diy/lib'},
+ {:src => 'vendor/unity/auto/', :dst => 'vendor/unity/auto'},
+ {:src => 'vendor/unity/src/', :dst => 'vendor/unity/src'},
+ ]
+
+ sub_components.each do |c|
+ directory(c[:src], File.join(ceedling_path, c[:dst]), :force => force)
+ end
+ end
+
+ # We're copying in a configuration file if we haven't said not to
+ if (use_configs)
+ if use_gem
+ copy_file(File.join('assets', 'project_as_gem.yml'), File.join(name, 'project.yml'), :force => force)
+ else
+ copy_file(File.join('assets', 'project_with_guts.yml'), File.join(name, 'project.yml'), :force => force)
+ if is_windows?
+ copy_file(File.join('assets', 'ceedling.cmd'), File.join(name, 'ceedling.cmd'), :force => force)
+ else
+ copy_file(File.join('assets', 'ceedling'), File.join(name, 'ceedling'), :force => force)
+ File.chmod(0755, File.join(name, 'ceedling'))
+ end
+ end
+ end
+
+ # Copy the gitignore file if requested
+ if (use_ignore)
+ copy_file(File.join('assets', 'default_gitignore'), File.join(name, '.gitignore'), :force => force)
+ end
+
+ unless silent
+ puts "\n"
+ puts "Project '#{name}' #{force ? "upgraded" : "created"}!"
+ puts " - Tool documentation is located in vendor/ceedling/docs" if use_docs
+ puts " - Execute 'ceedling help' to view available test & build tasks"
+ puts ''
+ end
+ end
+ end
+
+ desc "examples", "list available example projects"
+ def examples()
+ puts "Available sample projects:"
+ FileUtils.cd(File.join(here, "examples")) do
+ Dir["*"].each {|proj| puts " #{proj}"}
+ end
+ end
+
+ desc "example PROJ_NAME [DEST]", "new specified example project (in DEST, if specified)"
+ def example(proj_name, dest=nil)
+ if dest.nil? then dest = proj_name end
+
+ copy_assets_and_create_structure(dest, true, false, {:local=>true, :docs=>true})
+
+ dest_src = File.join(dest,'src')
+ dest_test = File.join(dest,'test')
+ dest_project = File.join(dest,'project.yml')
+
+ directory "examples/#{proj_name}/src", dest_src
+ directory "examples/#{proj_name}/test", dest_test
+ remove_file dest_project
+ copy_file "examples/#{proj_name}/project.yml", dest_project
+
+ puts "\n"
+ puts "Example project '#{proj_name}' created!"
+ puts " - Tool documentation is located in vendor/ceedling/docs"
+ puts " - Execute 'ceedling help' to view available test & build tasks"
+ puts ''
+ end
+
+ desc "version", "return the version of the tools installed"
+ def version()
+ require 'ceedling/version.rb'
+ puts " Ceedling:: #{Ceedling::Version::CEEDLING}"
+ puts " CMock:: #{Ceedling::Version::CMOCK}"
+ puts " Unity:: #{Ceedling::Version::UNITY}"
+ puts " CException:: #{Ceedling::Version::CEXCEPTION}"
+ end
+ end
+
+ if (ARGV[0] =~ /^\-T$/)
+ puts "\n(No Project Detected, Therefore Showing Options to Create Projects)"
+ CeedlingTasks.tasks.each_pair do |k,v|
+ puts v.usage.ljust(25,' ') + v.description
+ end
+ puts "\n"
+ else
+ CeedlingTasks.source_root here
+ CeedlingTasks.start
+ end
+
+#===================================== We Have A Project Already ================================================
+else
+ require 'yaml'
+ require 'rbconfig'
+
+ #determine platform
+ platform = begin
+ case(RbConfig::CONFIG['host_os'])
+ when /mswin|mingw|cygwin/i
+ :mswin
+ when /darwin/
+ :osx
+ else
+ :linux
+ end
+ rescue
+ :linux
+ end
+
+ #create our default meta-runner option set
+ options = {
+ :pretest => nil,
+ :args => [],
+ :add_path => [],
+ :path_connector => (platform == :mswin) ? ";" : ":",
+ :graceful_fail => false,
+ :which_ceedling => (Dir.exists?("vendor/ceedling") ? "vendor/ceedling" : 'gem'),
+ :default_tasks => [ 'test:all' ],
+ :list_tasks => false
+ }
+
+ #guess that we need a special script file first if it exists
+ if (platform == :mswin)
+ options[:pretest] = File.exists?("#{ platform.to_s }_setup.bat") ? "#{ platform.to_s }_setup.bat" : nil
+ else
+ options[:pretest] = File.exists?("#{ platform.to_s }_setup.sh") ? "source #{ platform.to_s }_setup.sh" : nil
+ end
+
+ #merge in project settings if they can be found here
+ yaml_options = YAML.load_file(main_filepath)
+ if (yaml_options[:paths])
+ options[:add_path] = yaml_options[:paths][:tools] || []
+ else
+ options[:add_path] = []
+ end
+ options[:graceful_fail] = yaml_options[:graceful_fail] if yaml_options[:graceful_fail]
+ options[:which_ceedling] = yaml_options[:project][:which_ceedling] if (yaml_options[:project] && yaml_options[:project][:which_ceedling])
+ options[:default_tasks] = yaml_options[:default_tasks] if yaml_options[:default_tasks]
+
+ #sort through command line options
+ ARGV.each do |v|
+ case(v)
+ when /^(?:new|examples?|templates?)$/
+ puts "\nOops. You called ceedling with argument '#{v}'.\n" +
+ " This is an operation that will create a new project... \n" +
+ " but it looks like you're already in a project. If you really \n" +
+ " want to do this, try moving to an empty folder.\n\n"
+ abort
+ when /^help$/
+ options[:list_tasks] = true
+ when /^-T$/
+ options[:list_tasks] = true
+ when /^project:(\w+)/
+ ENV['CEEDLING_USER_PROJECT_FILE'] = "#{$1}.yml"
+ else
+ options[:args].push(v)
+ end
+ end
+
+ #add to the path
+ if (options[:add_path] && !options[:add_path].empty?)
+ path = ENV["PATH"]
+ options[:add_path].each do |p|
+ f = File.expand_path(File.dirname(__FILE__),p)
+ path = (f + options[:path_connector] + path) unless path.include? f
+ end
+ ENV["PATH"] = path
+ end
+
+ # Load Ceedling (either through the rakefile OR directly)
+ if (File.exists?("rakefile.rb"))
+ load 'rakefile.rb'
+ else
+ if (options[:which_ceedling] == 'gem')
+ require 'ceedling'
+ else
+ load "#{options[:which_ceedling]}/lib/ceedling.rb"
+ end
+ Ceedling.load_project
+ end
+
+ Rake.application.standard_exception_handling do
+ if options[:list_tasks]
+ # Display helpful task list when requested. This required us to dig into Rake internals a bit
+ Rake.application.define_singleton_method(:name=) {|n| @name = n}
+ Rake.application.name = 'ceedling'
+ Rake.application.options.show_tasks = :tasks
+ Rake.application.options.show_task_pattern = /^(?!.*build).*$/
+ Rake.application.display_tasks_and_comments()
+ else
+ task :default => options[:default_tasks]
+
+ # Run our Tasks!
+ Rake.application.collect_command_line_tasks(options[:args])
+ Rake.application.top_level
+ end
+ end
+ true
+#===================================================================================================================
+end
diff --git a/tinyusb/test/vendor/ceedling/docs/CException.md b/tinyusb/test/vendor/ceedling/docs/CException.md
new file mode 100755
index 00000000..c3718191
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/CException.md
@@ -0,0 +1,292 @@
+
+CException
+==========
+
+CException is a basic exception framework for C, suitable for use in
+embedded applications. It provides an exception framework similar in
+use to C++, but with much less overhead.
+
+
+CException uses C standard library functions `setjmp` and `longjmp` to
+operate. As long as the target system has these two functions defined,
+this library should be useable with very little configuration. It
+even supports environments where multiple program flows are in use,
+such as real-time operating systems.
+
+
+There are about a gabillion exception frameworks using a similar
+setjmp/longjmp method out there... and there will probably be more
+in the future. Unfortunately, when we started our last embedded
+project, all those that existed either (a) did not support multiple
+tasks (therefore multiple stacks) or (b) were way more complex than
+we really wanted. CException was born.
+
+
+*Why use CException?*
+
+
+0. It's ANSI C, and it beats passing error codes around.
+1. You want something simple... CException throws a single id. You can
+ define those ID's to be whatever you like. You might even choose which
+ type that number is for your project. But that's as far as it goes.
+ We weren't interested in passing objects or structs or strings...
+ just simple error codes.
+2. Performance... CException can be configured for single tasking or
+ multitasking. In single tasking, there is very little overhead past
+ the setjmp/longjmp calls (which are already fast). In multitasking,
+ your only additional overhead is the time it takes you to determine
+ a unique task id 0 - num_tasks.
+
+
+For the latest version, go to [ThrowTheSwitch.org](http://throwtheswitch.org)
+
+
+CONTENTS OF THIS DOCUMENT
+=========================
+
+* Usage
+* Limitations
+*API
+* Configuration
+* Testing
+* License
+
+
+Usage
+-----
+
+Code that is to be protected are wrapped in `Try { } Catch { }` blocks.
+The code directly following the Try call is "protected", meaning that
+if any Throws occur, program control is directly transferred to the
+start of the Catch block.
+
+
+A numerical exception ID is included with Throw, and is made accessible
+from the Catch block.
+
+
+Throws can occur from within function calls (nested as deeply as you
+like) or directly from within the function itself.
+
+
+
+Limitations
+-----------
+
+
+This library was made to be as fast as possible, and provide basic
+exception handling. It is not a full-blown exception library. Because
+of this, there are a few limitations that should be observed in order
+to successfully utilize this library:
+
+1. Do not directly "return" from within a `Try` block, nor `goto`
+ into or out of a `Try` block.
+
+ *Why?*
+
+ The `Try` macro allocates some local memory and alters a global
+ pointer. These are cleaned up at the top of the `Catch` macro.
+ Gotos and returns would bypass some of these steps, resulting in
+ memory leaks or unpredictable behavior.
+
+
+2. If (a) you change local (stack) variables within your `Try` block,
+ AND (b) wish to make use of the updated values after an exception
+ is thrown, those variables should be made `volatile`. Note that this
+ is ONLY for locals and ONLY when you need access to them after a
+ `Throw`.
+
+ *Why?*
+
+ Compilers optimize. There is no way to guarantee that the actual
+ memory location was updated and not just a register unless the
+ variable is marked volatile.
+
+
+3. Memory which is `malloc`'d or `new`'d is not automatically released
+ when an error is thrown. This will sometimes be desirable, and
+ othertimes may not. It will be the responsibility of the `Catch`
+ block to perform this kind of cleanup.
+
+ *Why?*
+
+ There's just no easy way to track `malloc`'d memory, etc., without
+ replacing or wrapping malloc calls or something like that. This
+ is a light framework, so these options were not desirable.
+
+
+
+API
+---
+
+###Try
+
+`Try` is a macro which starts a protected block. It MUST be followed by
+a pair of braces or a single protected line (similar to an 'if'),
+enclosing the data that is to be protected. It **must** be followed by a
+`Catch` block (don't worry, you'll get compiler errors to let you know if
+you mess any of that up).
+
+
+###Catch(e)
+
+`Catch` is a macro which ends the `Try` block and starts the error handling
+block. The `Catch` block is called if and only if an exception was thrown
+while within the `Try` block. This error was thrown by a `Throw` call
+somewhere within `Try` (or within a function called within `Try`, or a function
+called by a function called within `Try`, etc).
+
+The single parameter `e` is filled with the error code which was thrown.
+This can be used for reporting, conditional cleanup, etc. (or you can just
+ignore it if you really want... people ignore return codes all the time,
+right?). `e` should be of type `EXCEPTION_T`
+
+
+###Throw(e)
+
+This is the method of throwing an error. A `Throw` should only occur from within a
+protected (`Try` ... `Catch`) block, though it may easily be nested many function
+calls deep without an impact on performance or functionality. `Throw` takes
+a single argument, which is an exception id which will be passed to `Catch`
+as the reason for the error.
+
+If you wish to rethrow an error, this can be done by calling `Throw(e)` with
+the error code you just caught. It **is** valid to throw from a catch block.
+
+
+###ExitTry()
+
+On rare occasion, you might want to immediately exit your current `Try` block
+but **not** treat this as an error. Don't run the `Catch`. Just start executing
+from after the `Catch` as if nothing had happened... That's what `ExitTry` is
+for.
+
+
+CONFIGURATION
+-------------
+
+CException is a mostly portable library. It has one universal
+dependency, and some macros which are required if working in a
+multi-tasking environment.
+
+1. The standard C library setjmp must be available. Since this is part
+ of the standard library, chances are good that you'll be fine.
+
+2. If working in a multitasking environment, methods for obtaining an
+ index into an array of frames and to get the overall number of
+ id's are required. If the OS supports a method to retrieve Task
+ ID's, and those Tasks are number 0, 1, 2... you are in an ideal
+ situation. Otherwise, a more creative mapping function may be
+ required. Note that this function is likely to be called twice
+ for each protected block and once during a throw. This is the
+ only overhead in the system.
+
+
+Exception.h
+-----------
+
+By convention, most projects include `Exception.h` which defines any
+further requirements, then calls `CException.h` to do the gruntwork. All
+of these are optional. You could directly include `CException.h` if
+you wanted and just use the defaults provided.
+
+* `EXCEPTION_T`
+ * Set this to the type you want your exception id's to be. Defaults to 'unsigned int'.
+
+* `EXCEPTION_NONE`
+ * Set this to a number which will never be an exception id in your system. Defaults to `0x5a5a5a5a`.
+
+* `EXCEPTION_GET_ID`
+ * If in a multi-tasking environment, this should be
+ set to be a call to the function described in #2 above.
+ Defaults to just return `0` all the time (good for
+ single tasking environments)
+
+* `EXCEPTION_NUM_ID`
+ * If in a multi-tasking environment, this should be set
+ to the number of ID's required (usually the number of
+ tasks in the system). Defaults to `1` (for single
+ tasking environments).
+
+* `CEXCEPTION_NO_CATCH_HANDLER(id)`
+ * This macro can be optionally specified.
+ It allows you to specify code to be called when a Throw
+ is made outside of `Try` ... `Catch` protection. Consider
+ this the emergency fallback plan for when something has
+ gone terribly wrong.
+
+
+You may also want to include any header files which will commonly be
+needed by the rest of your application where it uses exception handling
+here. For example, OS header files or exception codes would be useful.
+
+
+Finally, there are some hook macros which you can implement to inject
+your own target-specific code in particular places. It is a rare instance
+where you will need these, but they are here if you need them:
+
+
+* `CEXCEPTION_HOOK_START_TRY`
+ * called immediately before the Try block
+
+* `CEXCEPTION_HOOK_HAPPY_TRY`
+ * called immediately after the Try block if no exception was thrown
+
+* `CEXCEPTION_HOOK_AFTER_TRY`
+ * called immediately after the Try block OR before an exception is caught
+
+* `CEXCEPTION_HOOK_START_CATCH`
+ * called immediately before the catch
+
+
+
+TESTING
+-------
+
+
+If you want to validate that CException works with your tools or that
+it works with your custom configuration, you may want to run the test
+suite.
+
+
+The test suite included makes use of the `Unity` Test Framework. It will
+require a native C compiler. The example makefile uses MinGW's gcc.
+Modify the makefile to include the proper paths to tools, then run `make`
+to compile and run the test application.
+
+* `C_COMPILER`
+ * The C compiler to use to perform the tests
+
+* `C_LIBS`
+ * The path to the C libraries (including setjmp)
+
+* `UNITY_DIR`
+ * The path to the Unity framework (required to run tests)
+ (get it at [ThrowTheSwitch.org](http://throwtheswitch.org))
+
+
+
+LICENSE
+-------
+
+This software is licensed under the MIT License
+
+Copyright (c) 2007-2017 Mark VanderVoord
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/tinyusb/test/vendor/ceedling/docs/CMock_Summary.md b/tinyusb/test/vendor/ceedling/docs/CMock_Summary.md
new file mode 100755
index 00000000..87f9c00b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/CMock_Summary.md
@@ -0,0 +1,603 @@
+CMock: A Summary
+================
+
+*[ThrowTheSwitch.org](http://throwtheswitch.org)*
+
+*This documentation is released under a Creative Commons 3.0 Attribution Share-Alike License*
+
+
+What Exactly Are We Talking About Here?
+---------------------------------------
+
+CMock is a nice little tool which takes your header files and creates
+a Mock interface for it so that you can more easily unit test modules
+that touch other modules. For each function prototype in your
+header, like this one:
+
+ int DoesSomething(int a, int b);
+
+
+...you get an automatically generated DoesSomething function
+that you can link to instead of your real DoesSomething function.
+By using this Mocked version, you can then verify that it receives
+the data you want, and make it return whatever data you desire,
+make it throw errors when you want, and more... Create these for
+everything your latest real module touches, and you're suddenly
+in a position of power: You can control and verify every detail
+of your latest creation.
+
+To make that easier, CMock also gives you a bunch of functions
+like the ones below, so you can tell that generated DoesSomething
+function how to behave for each test:
+
+ void DoesSomething_ExpectAndReturn(int a, int b, int toReturn);
+ void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error);
+ void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback);
+ void DoesSomething_IgnoreAndReturn(int toReturn);
+
+
+You can pile a bunch of these back to back, and it remembers what
+you wanted to pass when, like so:
+
+ test_CallsDoesSomething_ShouldDoJustThat(void)
+ {
+ DoesSomething_ExpectAndReturn(1,2,3);
+ DoesSomething_ExpectAndReturn(4,5,6);
+ DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS);
+
+ CallsDoesSomething( );
+ }
+
+
+This test will call CallsDoesSomething, which is the function
+we are testing. We are expecting that function to call DoesSomething
+three times. The first time, we check to make sure it's called
+as DoesSomething(1, 2) and we'll magically return a 3. The second
+time we check for DoesSomething(4, 5) and we'll return a 6. The
+third time we verify DoesSomething(7, 8) and we'll throw an error
+instead of returning anything. If CallsDoesSomething gets
+any of this wrong, it fails the test. It will fail if you didn't
+call DoesSomething enough, or too much, or with the wrong arguments,
+or in the wrong order.
+
+CMock is based on Unity, which it uses for all internal testing.
+It uses Ruby to do all the main work (versions 2.0.0 and above).
+
+
+Installing
+==========
+
+The first thing you need to do to install CMock is to get yourself
+a copy of Ruby. If you're on linux or osx, you probably already
+have it. You can prove it by typing the following:
+
+ ruby --version
+
+
+If it replied in a way that implies ignorance, then you're going to
+need to install it. You can go to [ruby-lang](https://ruby-lang.org)
+to get the latest version. You're also going to need to do that if it
+replied with a version that is older than 2.0.0. Go ahead. We'll wait.
+
+Once you have Ruby, you have three options:
+
+* Clone the latest [CMock repo on github](https://github.com/ThrowTheSwitch/CMock/)
+* Download the latest [CMock zip from github](https://github.com/ThrowTheSwitch/CMock/)
+* Install Ceedling (which has it built in!) through your commandline using `gem install ceedling`.
+
+
+Generated Mock Module Summary
+=============================
+
+In addition to the mocks themselves, CMock will generate the
+following functions for use in your tests. The expect functions
+are always generated. The other functions are only generated
+if those plugins are enabled:
+
+
+Expect:
+-------
+
+Your basic staple Expects which will be used for most of your day
+to day CMock work. By calling this, you are telling CMock that you
+expect that function to be called during your test. It also specifies
+which arguments you expect it to be called with, and what return
+value you want returned when that happens. You can call this function
+multiple times back to back in order to queue up multiple calls.
+
+* `void func(void)` => `void func_Expect(void)`
+* `void func(params)` => `void func_Expect(expected_params)`
+* `retval func(void)` => `void func_ExpectAndReturn(retval_to_return)`
+* `retval func(params)` => `void func_ExpectAndReturn(expected_params, retval_to_return)`
+
+
+ExpectAnyArgs:
+--------------
+
+This behaves just like the Expects calls, except that it doesn't really
+care what the arguments are that the mock gets called with. It still counts
+the number of times the mock is called and it still handles return values
+if there are some.
+
+* `void func(void)` => `void func_ExpectAnyArgs(void)`
+* `void func(params)` => `void func_ExpectAnyArgs(void)`
+* `retval func(void)` => `void func_ExpectAnyArgsAndReturn(retval_to_return)`
+* `retval func(params)` => `void func_ExpectAnyArgsAndReturn(retval_to_return)`
+
+
+Array:
+------
+
+An ExpectWithArray is another variant of Expect. Like expect, it cares about
+the number of times a mock is called, the arguments it is called with, and the
+values it is to return. This variant has another feature, though. For anything
+that resembles a pointer or array, it breaks the argument into TWO arguments.
+The first is the original pointer. The second specify the number of elements
+it is to verify of that array. If you specify 1, it'll check one object. If 2,
+it'll assume your pointer is pointing at the first of two elements in an array.
+If you specify zero elements, it will check just the pointer if
+`:smart` mode is configured or fail if `:compare_data` is set.
+
+* `void func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers)
+* `void func(ptr * param, other)` => `void func_ExpectWithArray(ptr* param, int param_depth, other)`
+* `retval func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers)
+* `retval func(other, ptr* param)` => `void func_ExpectWithArrayAndReturn(other, ptr* param, int param_depth, retval_to_return)`
+
+
+Ignore:
+-------
+
+Maybe you don't care about the number of times a particular function is called or
+the actual arguments it is called with. In that case, you want to use Ignore. Ignore
+only needs to be called once per test. It will then ignore any further calls to that
+particular mock. The IgnoreAndReturn works similarly, except that it has the added
+benefit of knowing what to return when that call happens. If the mock is called more
+times than IgnoreAndReturn was called, it will keep returning the last value without
+complaint. If it's called less times, it will also ignore that. You SAID you didn't
+care how many times it was called, right?
+
+* `void func(void)` => `void func_Ignore(void)`
+* `void func(params)` => `void func_Ignore(void)`
+* `retval func(void)` => `void func_IgnoreAndReturn(retval_to_return)`
+* `retval func(params)` => `void func_IgnoreAndReturn(retval_to_return)`
+
+
+Ignore Arg:
+------------
+
+Maybe you overall want to use Expect and its similar variations, but you don't care
+what is passed to a particular argument. This is particularly useful when that argument
+is a pointer to a value that is supposed to be filled in by the function. You don't want
+to use ExpectAnyArgs, because you still care about the other arguments. Instead, before
+any of your Expect calls are made, you can call this function. It tells CMock to ignore
+a particular argument for the rest of this test, for this mock function.
+
+* `void func(params)` => `void func_IgnoreArg_paramName(void)`
+
+
+ReturnThruPtr:
+--------------
+
+Another option which operates on a particular argument of a function is the ReturnThruPtr
+plugin. For every argument that resembles a pointer or reference, CMock generates an
+instance of this function. Just as the AndReturn functions support injecting one or more
+return values into a queue, this function lets you specify one or more return values which
+are queued up and copied into the space being pointed at each time the mock is called.
+
+* `void func(param1)` => `void func_ReturnThruPtr_paramName(val_to_return)`
+* => `void func_ReturnArrayThruPtr_paramName(cal_to_return, len)`
+* => `void func_ReturnMemThruPtr_paramName(val_to_return, size)`
+
+
+Callback:
+---------
+
+If all those other options don't work, and you really need to do something custom, you
+still have a choice. As soon as you stub a callback in a test, it will call the callback
+whenever the mock is encountered and return the retval returned from the callback (if any)
+instead of performing the usual expect checks. It can be configured to check the arguments
+first (like expects) or just jump directly to the callback.
+
+* `void func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
+where `CMOCK_func_CALLBACK` looks like: `void func(int NumCalls)`
+* `void func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
+where `CMOCK_func_CALLBACK` looks like: `void func(params, int NumCalls)`
+* `retval func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
+where `CMOCK_func_CALLBACK` looks like: `retval func(int NumCalls)`
+* `retval func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
+where `CMOCK_func_CALLBACK` looks like: `retval func(params, int NumCalls)`
+
+
+Cexception:
+-----------
+
+Finally, if you are using Cexception for error handling, you can use this to throw errors
+from inside mocks. Like Expects, it remembers which call was supposed to throw the error,
+and it still checks parameters first.
+
+* `void func(void)` => `void func_ExpectAndThrow(value_to_throw)`
+* `void func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)`
+* `retval func(void)` => `void func_ExpectAndThrow(value_to_throw)`
+* `retval func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)`
+
+
+
+Running CMock
+=============
+
+CMock is a Ruby script and class. You can therefore use it directly
+from the command line, or include it in your own scripts or rakefiles.
+
+
+Mocking from the Command Line
+-----------------------------
+
+After unpacking CMock, you will find cmock.rb in the 'lib' directory.
+This is the file that you want to run. It takes a list of header files
+to be mocked, as well as an optional yaml file for a more detailed
+configuration (see config options below).
+
+For example, this will create three mocks using the configuration
+specified in MyConfig.yml:
+
+ ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h
+
+And this will create two mocks using the default configuration:
+
+ ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h
+
+
+Mocking From Scripts or Rake
+----------------------------
+
+CMock can be used directly from your own scripts or from a rakefile.
+Start by including cmock.rb, then create an instance of CMock.
+When you create your instance, you may initialize it in one of
+three ways.
+
+You may specify nothing, allowing it to run with default settings:
+
+ require 'cmock.rb'
+ cmock = CMock.new
+
+You may specify a YAML file containing the configuration options
+you desire:
+
+ cmock = CMock.new('../MyConfig.yml')
+
+You may specify the options explicitly:
+
+ cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/')
+
+
+Config Options:
+---------------
+
+The following configuration options can be specified in the
+yaml file or directly when instantiating.
+
+Passed as Ruby, they look like this:
+
+ { :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare }
+
+Defined in the yaml file, they look more like this:
+
+ :cmock:
+ :attributes:
+ - __funky
+ - __intrinsic
+ :when_ptr: :compare
+
+In all cases, you can just include the things that you want to override
+from the defaults. We've tried to specify what the defaults are below.
+
+* `:attributes`:
+ These are attributes that CMock should ignore for you for testing
+ purposes. Custom compiler extensions and externs are handy things to
+ put here. If your compiler is choking on some extended syntax, this
+ is often a good place to look.
+
+ * defaults: ['__ramfunc', '__irq', '__fiq', 'register', 'extern']
+ * **note:** this option will reinsert these attributes onto the mock's calls.
+ If that isn't what you are looking for, check out :strippables.
+
+* `:c_calling_conventions`:
+ Similarly, CMock may need to understand which C calling conventions
+ might show up in your codebase. If it encounters something it doesn't
+ recognize, it's not going to mock it. We have the most common covered,
+ but there are many compilers out there, and therefore many other options.
+
+ * defaults: ['__stdcall', '__cdecl', '__fastcall']
+ * **note:** this option will reinsert these attributes onto the mock's calls.
+ If that isn't what you are looking for, check out :strippables.
+
+* `:callback_after_arg_check`:
+ Tell `:callback` plugin to do the normal argument checking **before** it
+ calls the callback function by setting this to true. When false, the
+ callback function is called **instead** of the argument verification.
+
+ * default: false
+
+* `:callback_include_count`:
+ Tell `:callback` plugin to include an extra parameter to specify the
+ number of times the callback has been called. If set to false, the
+ callback has the same interface as the mocked function. This can be
+ handy when you're wanting to use callback as a stub.
+
+ * default: true
+
+* `:cexception_include`:
+ Tell `:cexception` plugin where to find CException.h... You only need to
+ define this if it's not in your build path already... which it usually
+ will be for the purpose of your builds.
+
+ * default: *nil*
+
+* `:enforce_strict_ordering`:
+ CMock always enforces the order that you call a particular function,
+ so if you expect GrabNabber(int size) to be called three times, it
+ will verify that the sizes are in the order you specified. You might
+ *also* want to make sure that all different functions are called in a
+ particular order. If so, set this to true.
+
+ * default: false
+
+* `:framework`:
+ Currently the only option is `:unity.` Eventually if we support other
+ unity test frameworks (or if you write one for us), they'll get added
+ here.
+
+ : default: :unity
+
+* `:includes`:
+ An array of additional include files which should be added to the
+ mocks. Useful for global types and definitions used in your project.
+ There are more specific versions if you care WHERE in the mock files
+ the includes get placed. You can define any or all of these options.
+
+ * `:includes`
+ * `:includes_h_pre_orig_header`
+ * `:includes_h_post_orig_header`
+ * `:includes_c_pre_header`
+ * `:includes_c_post_header`
+ * default: nil #for all 5 options
+
+* `:memcmp_if_unknown`:
+ C developers create a lot of types, either through typedef or preprocessor
+ macros. CMock isn't going to automatically know what you were thinking all
+ the time (though it tries its best). If it comes across a type it doesn't
+ recognize, you have a choice on how you want it to handle it. It can either
+ perform a raw memory comparison and report any differences, or it can fail
+ with a meaningful message. Either way, this feature will only happen after
+ all other mechanisms have failed (The thing encountered isn't a standard
+ type. It isn't in the :treat_as list. It isn't in a custom unity_helper).
+
+ * default: true
+
+* `:mock_path`:
+ The directory where you would like the mock files generated to be
+ placed.
+
+ * default: mocks
+
+* `:mock_prefix`:
+ The prefix to prepend to your mock files. For example, if it's “Mock”, a file
+ “USART.h” will get a mock called “MockUSART.c”. This CAN be used with a suffix
+ at the same time.
+
+ * default: Mock
+
+* `:mock_suffix`:
+ The suffix to append to your mock files. For example, it it's "_Mock", a file
+ "USART.h" will get a mock called "USART_Mock.h". This CAN be used with a prefix
+ at the same time.
+
+ * default: ""
+
+* `:plugins`:
+ An array of which plugins to enable. ':expect' is always active. Also
+ available currently:
+
+ * `:ignore`
+ * `:ignore_arg`
+ * `:expect_any_args`
+ * `:array`
+ * `:cexception`
+ * `:callback`
+ * `:return_thru_ptr`
+
+* `:strippables`:
+ An array containing a list of items to remove from the header
+ before deciding what should be mocked. This can be something simple
+ like a compiler extension CMock wouldn't recognize, or could be a
+ regex to reject certain function name patterns. This is a great way to
+ get rid of compiler extensions when your test compiler doesn't support
+ them. For example, use `:strippables: ['(?:functionName\s*\(+.*?\)+)']`
+ to prevent a function `functionName` from being mocked. By default, it
+ is ignoring all gcc attribute extensions.
+
+ * default: ['(?:__attribute__\s*\(+.*?\)+)']
+
+* `:subdir`:
+ This is a relative subdirectory for your mocks. Set this to e.g. "sys" in
+ order to create a mock for `sys/types.h` in `(:mock_path)/sys/`.
+
+ * default: ""
+
+* `:treat_as`:
+ The `:treat_as` list is a shortcut for when you have created typedefs
+ of standard types. Why create a custom unity helper for UINT16 when
+ the unity function TEST_ASSERT_EQUAL_HEX16 will work just perfectly?
+ Just add 'UINT16' => 'HEX16' to your list (actually, don't. We already
+ did that one for you). Maybe you have a type that is a pointer to an
+ array of unsigned characters? No problem, just add 'UINT8_T*' =>
+ 'HEX8*'
+
+ * NOTE: unlike the other options, your specifications MERGE with the
+ default list. Therefore, if you want to override something, you must
+ reassign it to something else (or to *nil* if you don't want it)
+
+ * default:
+ * 'int': 'INT'
+ * 'char': 'INT8'
+ * 'short': 'INT16'
+ * 'long': 'INT'
+ * 'int8': 'INT8'
+ * 'int16': 'INT16'
+ * 'int32': 'INT'
+ * 'int8_t': 'INT8'
+ * 'int16_t': 'INT16'
+ * 'int32_t': 'INT'
+ * 'INT8_T': 'INT8'
+ * 'INT16_T': 'INT16'
+ * 'INT32_T': 'INT'
+ * 'bool': 'INT'
+ * 'bool_t': 'INT'
+ * 'BOOL': 'INT'
+ * 'BOOL_T': 'INT'
+ * 'unsigned int': 'HEX32'
+ * 'unsigned long': 'HEX32'
+ * 'uint32': 'HEX32'
+ * 'uint32_t': 'HEX32'
+ * 'UINT32': 'HEX32'
+ * 'UINT32_T': 'HEX32'
+ * 'void*': 'HEX8_ARRAY'
+ * 'unsigned short': 'HEX16'
+ * 'uint16': 'HEX16'
+ * 'uint16_t': 'HEX16'
+ * 'UINT16': 'HEX16'
+ * 'UINT16_T': 'HEX16'
+ * 'unsigned char': 'HEX8'
+ * 'uint8': 'HEX8'
+ * 'uint8_t': 'HEX8'
+ * 'UINT8': 'HEX8'
+ * 'UINT8_T': 'HEX8'
+ * 'char*': 'STRING'
+ * 'pCHAR': 'STRING'
+ * 'cstring': 'STRING'
+ * 'CSTRING': 'STRING'
+ * 'float': 'FLOAT'
+ * 'double': 'FLOAT'
+
+* `:treat_as_void`:
+ We've seen "fun" legacy systems typedef 'void' with a custom type,
+ like MY_VOID. Add any instances of those to this list to help CMock
+ understand how to deal with your code.
+
+ * default: []
+
+* `:treat_externs`:
+ This specifies how you want CMock to handle functions that have been
+ marked as extern in the header file. Should it mock them?
+
+ * `:include` will mock externed functions
+ * `:exclude` will ignore externed functions (default).
+
+* `:unity_helper_path`:
+ If you have created a header with your own extensions to unity to
+ handle your own types, you can set this argument to that path. CMock
+ will then automagically pull in your helpers and use them. The only
+ trick is that you make sure you follow the naming convention:
+ `UNITY_TEST_ASSERT_EQUAL_YourType`. If it finds macros of the right
+ shape that match that pattern, it'll use them.
+
+ * default: []
+
+* `:verbosity`:
+ How loud should CMock be?
+
+ * 0 for errors only
+ * 1 for errors and warnings
+ * 2 for normal (default)
+ * 3 for verbose
+
+* `:weak`:
+ When set this to some value, the generated mocks are defined as weak
+ symbols using the configured format. This allows them to be overridden
+ in particular tests.
+
+ * Set to '__attribute ((weak))' for weak mocks when using GCC.
+ * Set to any non-empty string for weak mocks when using IAR.
+ * default: ""
+
+* `:when_no_prototypes`:
+ When you give CMock a header file and ask it to create a mock out of
+ it, it usually contains function prototypes (otherwise what was the
+ point?). You can control what happens when this isn't true. You can
+ set this to `:warn,` `:ignore,` or `:error`
+
+ * default: :warn
+
+* `:when_ptr`:
+ You can customize how CMock deals with pointers (c strings result in
+ string comparisons... we're talking about **other** pointers here). Your
+ options are `:compare_ptr` to just verify the pointers are the same,
+ `:compare_data` or `:smart` to verify that the data is the same.
+ `:compare_data` and `:smart` behaviors will change slightly based on
+ if you have the array plugin enabled. By default, they compare a
+ single element of what is being pointed to. So if you have a pointer
+ to a struct called ORGAN_T, it will compare one ORGAN_T (whatever that
+ is).
+
+ * default: :smart
+
+* `:fail_on_unexpected_calls`:
+ By default, CMock will fail a test if a mock is called without _Expect and _Ignore
+ called first. While this forces test writers to be more explicit in their expectations,
+ it can clutter tests with _Expect or _Ignore calls for functions which are not the focus
+ of the test. While this is a good indicator that this module should be refactored, some
+ users are not fans of the additional noise.
+
+ Therefore, :fail_on_unexpected_calls can be set to false to force all mocks to start with
+ the assumption that they are operating as _Ignore unless otherwise specified.
+
+ * default: true
+ * **note:**
+ If this option is disabled, the mocked functions will return
+ a default value (0) when called (and only if they have to return something of course).
+
+
+Compiled Options:
+-----------------
+
+A number of #defines also exist for customizing the cmock experience.
+Feel free to pass these into your compiler or whatever is most
+convenient. CMock will otherwise do its best to guess what you want
+based on other settings, particularly Unity's settings.
+
+* `CMOCK_MEM_STATIC` or `CMOCK_MEM_DYNAMIC`
+ Define one of these to determine if you want to dynamically add
+ memory during tests as required from the heap. If static, you
+ can control the total footprint of Cmock. If dynamic, you will
+ need to make sure you make some heap space available for Cmock.
+
+* `CMOCK_MEM_SIZE`
+ In static mode this is the total amount of memory you are allocating
+ to Cmock. In Dynamic mode this is the size of each chunk allocated
+ at once (larger numbers grab more memory but require less mallocs).
+
+* `CMOCK_MEM_ALIGN`
+ The way to align your data to. Not everything is as flexible as
+ a PC, as most embedded designers know. This defaults to 2, meaning
+ align to the closest 2^2 -> 4 bytes (32 bits). You can turn off alignment
+ by setting 0, force alignment to the closest uint16 with 1 or even
+ to the closest uint64 with 3.
+
+* `CMOCK_MEM_PTR_AS_INT`
+ This is used internally to hold pointers... it needs to be big
+ enough. On most processors a pointer is the same as an unsigned
+ long... but maybe that's not true for yours?
+
+* `CMOCK_MEM_INDEX_TYPE`
+ This needs to be something big enough to point anywhere in Cmock's
+ memory space... usually it's an unsigned int.
+
+Examples
+========
+
+You can look in the [examples directory](/examples/) for a couple of examples on how
+you might tool CMock into your build process. You may also want to consider
+using [Ceedling](https://throwtheswitch.org/ceedling). Please note that
+these examples are meant to show how the build process works. They have
+failing tests ON PURPOSE to show what that would look like. Don't be alarmed. ;)
+
diff --git a/tinyusb/test/vendor/ceedling/docs/CeedlingPacket.md b/tinyusb/test/vendor/ceedling/docs/CeedlingPacket.md
new file mode 100755
index 00000000..88cd0202
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/CeedlingPacket.md
@@ -0,0 +1,2060 @@
+[All code is copyright © 2010-2012 Ceedling Project
+by Mike Karlesky, Mark VanderVoord, and Greg Williams.
+
+This Documentation Is Released Under a
+Creative Commons 3.0 Attribution Share-Alike License]
+
+What the What?
+
+Assembling build environments for C projects - especially with
+automated unit tests - is a pain. Whether it's Make or Rake or Premake
+or what-have-you, set up with an all-purpose build environment
+tool is tedious and requires considerable glue code to pull together
+the necessary tools and libraries. Ceedling allows you to generate
+an entire test and build environment for a C project from a single
+YAML configuration file. Ceedling is written in Ruby and works
+with the Rake build tool plus other goodness like Unity and CMock
+- the unit testing and mocking frameworks for C. Ceedling and
+its complementary tools can support the tiniest of embedded
+processors, the beefiest 64 bit power houses available, and
+everything in between.
+
+For a build project including unit tests and using the default
+toolchain gcc, the configuration file could be as simple as this:
+
+```yaml
+:project:
+ :build_root: project/build/
+ :release_build: TRUE
+
+:paths:
+ :test:
+ - tests/**
+ :source:
+ - source/**
+```
+
+From the command line, to build the release version of your project,
+you would simply run `ceedling release`. To run all your unit tests,
+you would run `ceedling test:all`. That's it!
+
+Of course, many more advanced options allow you to configure
+your project with a variety of features to meet a variety of needs.
+Ceedling can work with practically any command line toolchain
+and directory structure – all by way of the configuration file.
+Further, because Ceedling piggy backs on Rake, you can add your
+own Rake tasks to accomplish project tasks outside of testing
+and release builds. A facility for plugins also allows you to
+extend Ceedling's capabilities for needs such as custom code
+metrics reporting and coverage testing.
+
+What's with this Name?
+
+Glad you asked. Ceedling is tailored for unit tested C projects
+and is built upon / around Rake (Rake is a Make replacement implemented
+in the Ruby scripting language). So, we've got C, our Rake, and
+the fertile soil of a build environment in which to grow and tend
+your project and its unit tests. Ta da - _Ceedling_.
+
+What Do You Mean "tailored for unit tested C projects"?
+
+Well, we like to write unit tests for our C code to make it lean and
+mean (that whole [Test-Driven Development][tdd]
+thing). Along the way, this style of writing C code spawned two
+tools to make the job easier: a unit test framework for C called
+_Unity_ and a mocking library called _CMock_. And, though it's
+not directly related to testing, a C framework for exception
+handling called _CException_ also came along.
+
+[tdd]: http://en.wikipedia.org/wiki/Test-driven_development
+
+These tools and frameworks are great, but they require quite
+a bit of environment support to pull them all together in a convenient,
+usable fashion. We started off with Rakefiles to assemble everything.
+These ended up being quite complicated and had to be hand-edited
+or created anew for each new project. Ceedling replaces all that
+tedium and rework with a configuration file that ties everything
+together.
+
+Though Ceedling is tailored for unit testing, it can also go right ahead
+and build your final binary release artifact for you as well. Or,
+Ceedling and your tests can live alongside your existing release build
+setup. That said, Ceedling is more powerful as a unit test build
+environment than it is a general purpose release build environment;
+complicated projects including separate bootloaders or multiple library
+builds, etc. are not its strong suit.
+
+Hold on. Back up. Ruby? Rake? YAML? Unity? CMock? CException?
+
+Seem overwhelming? It's not bad at all, and for the benefits tests
+bring us, it's all worth it.
+
+[Ruby][] is a handy scripting
+language like Perl or Python. It's a modern, full featured language
+that happens to be quite handy for accomplishing tasks like code
+generation or automating one's workflow while developing in
+a compiled language such as C.
+
+[Ruby]: http://www.ruby-lang.org/en/
+
+[Rake][] is a utility written in Ruby
+for accomplishing dependency tracking and task automation
+common to building software. It's a modern, more flexible replacement
+for [Make][]).
+Rakefiles are Ruby files, but they contain build targets similar
+in nature to that of Makefiles (but you can also run Ruby code in
+your Rakefile).
+
+[Rake]: http://rubyrake.org/
+[Make]: http://en.wikipedia.org/wiki/Make_(software)
+
+[YAML][] is a "human friendly data serialization standard for all
+programming languages." It's kinda like a markup language, but don't
+call it that. With a YAML library, you can [serialize][] data structures
+to and from the file system in a textual, human readable form. Ceedling
+uses a serialized data structure as its configuration input.
+
+[YAML]: http://en.wikipedia.org/wiki/Yaml
+[serialize]: http://en.wikipedia.org/wiki/Serialization
+
+[Unity] is a [unit test framework][test] for C. It provides facilities
+for test assertions, executing tests, and collecting / reporting test
+results. Unity derives its name from its implementation in a single C
+source file (plus two C header files) and from the nature of its
+implementation - Unity will build in any C toolchain and is configurable
+for even the very minimalist of processors.
+
+[Unity]: http://github.com/ThrowTheSwitch/Unity
+[test]: http://en.wikipedia.org/wiki/Unit_testing
+
+[CMock] is a tool written in Ruby able to generate entire
+[mock functions][mock] in C code from a given C header file. Mock
+functions are invaluable in [interaction-based unit testing][ut].
+CMock's generated C code uses Unity.
+
+[CMock]: http://github.com/ThrowTheSwitch/CMock
+[mock]: http://en.wikipedia.org/wiki/Mock_object
+[ut]: http://martinfowler.com/articles/mocksArentStubs.html
+
+[CException] is a C source and header file that provide a simple
+[exception mechanism][exn] for C by way of wrapping up the
+[setjmp / longjmp][setjmp] standard library calls. Exceptions are a much
+cleaner and preferable alternative to managing and passing error codes
+up your return call trace.
+
+[CException]: http://github.com/ThrowTheSwitch/CException
+[exn]: http://en.wikipedia.org/wiki/Exception_handling
+[setjmp]: http://en.wikipedia.org/wiki/Setjmp.h
+
+Notes
+-----
+
+* YAML support is included with Ruby - requires no special installation
+ or configuration.
+
+* Unity, CMock, and CException are bundled with Ceedling, and
+ Ceedling is designed to glue them all together for your project
+ as seamlessly as possible.
+
+
+Installation & Setup: What Exactly Do I Need to Get Started?
+------------------------------------------------------------
+
+As a [Ruby gem](http://docs.rubygems.org/read/chapter/1):
+
+1. [Download and install Ruby](http://www.ruby-lang.org/en/downloads/)
+
+2. Use Ruby's command line gem package manager to install Ceedling:
+ `gem install ceedling`
+ (Unity, CMock, and CException come along with Ceedling for free)
+
+3. Execute Ceedling at command line to create example project
+ or an empty Ceedling project in your filesystem (executing
+ `ceedling help` first is, well, helpful).
+
+Gem install notes:
+
+1. Steps 1-2 are a one time affair for your local environment.
+ When steps 1-2 are completed once, only step 3 is needed for
+ each new project.
+
+
+
+General notes:
+
+1. Certain advanced features of Ceedling rely on gcc and cpp
+ as preprocessing tools. In most *nix systems, these tools
+ are already available. For Windows environments, we recommend
+ the [mingw project](http://www.mingw.org/) (Minimalist
+ GNU for Windows). This represents an optional, additional
+ setup / installation step to complement the list above. Upon
+ installing mingw ensure your system path is updated or set
+ [:environment][:path] in your `project.yml` file (see
+ environment section later in this document).
+
+2. To use a project file name other than the default `project.yml`
+ or place the project file in a directory other than the one
+ in which you'll run Rake, create an environment variable
+ `CEEDLING_MAIN_PROJECT_FILE` with your desired project
+ file path.
+
+3. To better understand Rake conventions, Rake execution,
+ and Rakefiles, consult the [Rake tutorial, examples, and
+ user guide](http://rubyrake.org/).
+
+4. When using Ceedling in Windows environments, a test file name may
+ not include the sequences “patch” or “setup”. The Windows Installer
+ Detection Technology (part of UAC), requires administrator
+ privileges to execute file names with these strings.
+
+
+
+Now What? How Do I Make It GO?
+------------------------------
+
+We're getting a little ahead of ourselves here, but it's good
+context on how to drive this bus. Everything is done via the command
+line. We'll cover conventions and how to actually configure
+your project in later sections.
+
+To run tests, build your release artifact, etc., you will be interacting
+with Rake on the command line. Ceedling works with Rake to present
+you with named tasks that coordinate the file generation and
+build steps needed to accomplish something useful. You can also
+add your own independent Rake tasks or create plugins to extend
+Ceedling (more on this later).
+
+
+* `ceedling [no arguments]`:
+
+ Run the default Rake task (conveniently recognized by the name default
+ by Rake). Neither Rake nor Ceedling provide a default task. Rake will
+ abort if run without arguments when no default task is defined. You can
+ conveniently define a default task in the Rakefile discussed in the
+ preceding setup & installation section of this document.
+
+* `ceedling -T`:
+
+ List all available Rake tasks with descriptions (Rake tasks without
+ descriptions are not listed). -T is a command line switch for Rake and
+ not the same as tasks that follow.
+
+* `ceedling <tasks...> --trace`:
+
+ For advanced users troubleshooting a confusing build error, debug
+ Ceedling or a plugin, --trace provides a stack trace of dependencies
+ walked during task execution and any Ruby failures along the way. Note
+ that --trace is a command line switch for Rake and is not the same as
+ tasks that follow.
+
+* `ceedling environment`:
+
+ List all configured environment variable names and string values. This
+ task is helpful in verifying the evaluatio of any Ruby expressions in
+ the [:environment] section of your config file.`: Note: Ceedling may
+ set some convenience environment variables by default.
+
+* `ceedling paths:*`:
+
+ List all paths collected from [:paths] entries in your YAML config
+ file where * is the name of any section contained in [:paths]. This
+ task is helpful in verifying the expansion of path wildcards / globs
+ specified in the [:paths] section of your config file.
+
+* `ceedling files:assembly`
+* `ceedling files:header`
+* `ceedling files:source`
+* `ceedling files:test`
+
+ List all files and file counts collected from the relevant search
+ paths specified by the [:paths] entries of your YAML config file. The
+ files:assembly task will only be available if assembly support is
+ enabled in the [:release_build] section of your configuration file.
+
+* `ceedling options:*`:
+
+ Load and merge configuration settings into the main project
+ configuration. Each task is named after a *.yml file found in the
+ configured options directory. See documentation for the configuration
+ setting [:project][:options_path] and for options files in advanced
+ topics.
+
+* `ceedling test:all`:
+
+ Run all unit tests (rebuilding anything that's changed along the way).
+
+* `ceedling test:delta`:
+
+ Run only those unit tests for which the source or test files have
+ changed (i.e. incremental build). Note: with the
+ [:project][:use_test_preprocessor] configuration file option set,
+ runner files are always regenerated limiting the total efficiency this
+ text execution option can afford.
+
+* `ceedling test:*`:
+
+ Execute the named test file or the named source file that has an
+ accompanying test. No path. Examples: ceedling test:foo.c or ceed
+ test:test_foo.c
+
+* `ceedling test:pattern[*]`:
+
+ Execute any tests whose name and/or path match the regular expression
+ pattern (case sensitive). Example: ceedling "test:pattern[(I|i)nit]" will
+ execute all tests named for initialization testing. Note: quotes may
+ be necessary around the ceedling parameter to distinguish regex characters
+ from command line operators.
+
+* `ceedling test:path[*]`:
+
+ Execute any tests whose path contains the given string (case
+ sensitive). Example: ceedling test:path[foo/bar] will execute all tests
+ whose path contains foo/bar. Note: both directory separator characters
+ / and \ are valid.
+
+* `ceedling release`:
+
+ Build all source into a release artifact (if the release build option
+ is configured).
+
+* `ceedling release:compile:*`:
+
+ Sometimes you just need to compile a single file dagnabit. Example:
+ ceedling release:compile:foo.c
+
+* `ceedling release:assemble:*`:
+
+ Sometimes you just need to assemble a single file doggonit. Example:
+ ceedling release:assemble:foo.s
+
+* `ceedling module:create[Filename]`:
+* `ceedling module:create[<Path:>Filename]`:
+
+ It's often helpful to create a file automatically. What's better than
+ that? Creating a source file, a header file, and a corresponding test
+ file all in one step!
+
+ There are also patterns which can be specified to automatically generate
+ a bunch of files. Try `ceedling module:create[Poodles,mch]` for example!
+
+ The module generator has several options you can configure.
+ F.e. Generating the source/header/test file in a subdirectory (by adding <Path> when calling module:create).
+ For more info, refer to the [Module Generator](https://github.com/ThrowTheSwitch/Ceedling/blob/master/docs/CeedlingPacket.md#module-generator) section.
+
+* `ceedling logging <tasks...>`:
+
+ Enable logging to <build path>/logs. Must come before test and release
+ tasks to log their steps and output. Log names are a concatenation of
+ project, user, and option files loaded. User and option files are
+ documented in the advanced topics section of this document.
+
+* `ceedling verbosity[x] <tasks...>`:
+
+ Change the default verbosity level. [x] ranges from 0 (quiet) to 4
+ (obnoxious). Level [3] is the default. The verbosity task must precede
+ all tasks in the command line list for which output is desired to be
+ seen. Verbosity settings are generally most meaningful in conjunction
+ with test and release tasks.
+
+* `ceedling summary`:
+
+ If plugins are enabled, this task will execute the summary method of
+ any plugins supporting it. This task is intended to provide a quick
+ roundup of build artifact metrics without re-running any part of the
+ build.
+
+* `ceedling clean`:
+
+ Deletes all toolchain binary artifacts (object files, executables),
+ test results, and any temporary files. Clean produces no output at the
+ command line unless verbosity has been set to an appreciable level.
+
+* `ceedling clobber`:
+
+ Extends clean task's behavior to also remove generated files: test
+ runners, mocks, preprocessor output. Clobber produces no output at the
+ command line unless verbosity has been set to an appreciable level.
+
+To better understand Rake conventions, Rake execution, and
+Rakefiles, consult the [Rake tutorial, examples, and user guide][guide].
+
+[guide]: http://rubyrake.org/
+
+At present, none of Ceedling's commands provide persistence.
+That is, they must each be specified at the command line each time
+they are needed. For instance, Ceedling's verbosity command
+only affects output at the time it's run.
+
+Individual test and release file tasks
+are not listed in `-T` output. Because so many files may be present
+it's unwieldy to list them all.
+
+Multiple rake tasks can be executed at the command line (order
+is executed as provided). For example, `ceed
+clobber test:all release` will removed all generated files;
+build and run all tests; and then build all source - in that order.
+If any Rake task fails along the way, execution halts before the
+next task.
+
+The `clobber` task removes certain build directories in the
+course of deleting generated files. In general, it's best not
+to add to source control any Ceedling generated directories
+below the root of your top-level build directory. That is, leave
+anything Ceedling & its accompanying tools generate out of source
+control (but go ahead and add the top-level build directory that
+holds all that stuff). Also, since Ceedling is pretty smart about
+what it rebuilds and regenerates, you needn't clobber often.
+
+Important Conventions
+=====================
+
+Directory Structure, Filenames & Extensions
+-------------------------------------------
+
+Much of Ceedling's functionality is driven by collecting files
+matching certain patterns inside the paths it's configured
+to search. See the documentation for the [:extensions] section
+of your configuration file (found later in this document) to
+configure the file extensions Ceedling uses to match and collect
+files. Test file naming is covered later in this section.
+
+Test files and source files must be segregated by directories.
+Any directory structure will do. Tests can be held in subdirectories
+within source directories, or tests and source directories
+can be wholly separated at the top of your project's directory
+tree.
+
+Search Path Order
+-----------------
+
+When Ceedling searches for files (e.g. looking for header files
+to mock) or when it provides search paths to any of the default
+gcc toolchain executables, it organizes / prioritizes its search
+paths. The order is always: test paths, support paths, source
+paths, and then include paths. This can be useful, for instance,
+in certain testing scenarios where we desire Ceedling or a compiler
+to find a stand-in header file in our support directory before
+the actual source header file of the same name.
+
+This convention only holds when Ceedling is using its default
+tool configurations and / or when tests are involved. If you define
+your own tools in the configuration file (see the [:tools] section
+documented later in this here document), you have complete control
+over what directories are searched and in what order. Further,
+test and support directories are only searched when appropriate.
+That is, when running a release build, test and support directories
+are not used at all.
+
+Source Files & Binary Release Artifacts
+---------------------------------------
+
+Your binary release artifact results from the compilation and
+linking of all source files Ceedling finds in the specified source
+directories. At present only source files with a single (configurable)
+extension are recognized. That is, *.c and *.cc files will not
+both be recognized - only one or the other. See the configuration
+options and defaults in the documentation for the [:extensions]
+sections of your configuration file (found later in this document).
+
+Test Files & Executable Test Fixtures
+-------------------------------------
+
+Ceedling builds each individual test file with its accompanying
+source file(s) into a single, monolithic test fixture executable.
+Test files are recognized by a naming convention: a (configurable)
+prefix such as "`test_`" in the file name with the same file extension
+as used by your C source files. See the configuration options
+and defaults in the documentation for the [:project] and [:extensions]
+sections of your configuration file (found later in this document).
+Depending on your configuration options, Ceedling can recognize
+a variety of test file naming patterns in your test search paths.
+For example: `test_some_super_functionality.c`, `TestYourSourceFile.cc`,
+or `testing_MyAwesomeCode.C` could each be valid test file
+names. Note, however, that Ceedling can recognize only one test
+file naming convention per project.
+
+Ceedling knows what files to compile and link into each individual
+test executable by way of the #include list contained in each
+test file. Any C source files in the configured search directories
+that correspond to the header files included in a test file will
+be compiled and linked into the resulting test fixture executable.
+From this same #include list, Ceedling knows which files to mock
+and compile and link into the test executable (if you use mocks
+in your tests). That was a lot of clauses and information in a very
+few sentences; the example that follows in a bit will make it clearer.
+
+By naming your test functions according to convention, Ceedling
+will extract and collect into a runner C file calls to all your
+test case functions. This runner file handles all the execution
+minutiae so that your test file can be quite simple and so that
+you never forget to wire up a test function to be executed. In this
+generated runner lives the `main()` entry point for the resulting
+test executable. There are no configuration options for the
+naming convention of your test case functions. A test case function
+signature must have these three elements: void return, void
+parameter list, and the function name prepended with lowercase
+"`test`". In other words, a test function signature should look
+like this: `void test``[any name you like]``(void)`.
+
+A commented sample test file follows on the next page. Also, see
+the sample project contained in the Ceedling documentation
+bundle.
+
+```c
+// test_foo.c -----------------------------------------------
+#include "unity.h" // compile/link in Unity test framework
+#include "types.h" // header file with no *.c file -- no compilation/linking
+#include "foo.h" // source file foo.c under test
+#include "mock_bar.h" // bar.h will be found and mocked as mock_bar.c + compiled/linked in;
+ // foo.c includes bar.h and uses functions declared in it
+#include "mock_baz.h" // baz.h will be found and mocked as mock_baz.c + compiled/linked in
+ // foo.c includes baz.h and uses functions declared in it
+
+
+void setUp(void) {} // every test file requires this function;
+ // setUp() is called by the generated runner before each test case function
+
+void tearDown(void) {} // every test file requires this function;
+ // tearDown() is called by the generated runner before each test case function
+
+// a test case function
+void test_Foo_Function1_should_Call_Bar_AndGrill(void)
+{
+ Bar_AndGrill_Expect(); // setup function from mock_bar.c that instructs our
+ // framework to expect Bar_AndGrill() to be called once
+ TEST_ASSERT_EQUAL(0xFF, Foo_Function1()); // assertion provided by Unity
+ // Foo_Function1() calls Bar_AndGrill() & returns a byte
+}
+
+// another test case function
+void test_Foo_Function2_should_Call_Baz_Tec(void)
+{
+ Baz_Tec_ExpectAnd_Return(1); // setup function provided by mock_baz.c that instructs our
+ // framework to expect Baz_Tec() to be called once and return 1
+ TEST_ASSERT_TRUE(Foo_Function2()); // assertion provided by Unity
+}
+
+// end of test_foo.c ----------------------------------------
+```
+
+From the test file specified above Ceedling will generate `test_foo_runner.c`;
+this runner file will contain `main()` and call both of the example
+test case functions.
+
+The final test executable will be `test_foo.exe` (for Windows
+machines or `test_foo.out` for *nix systems - depending on default
+or configured file extensions). Based on the #include list above,
+the test executable will be the output of the linker having processed
+`unity.o`, `foo.o`, `mock_bar.o`, `mock_baz.o`, `test_foo.o`,
+and `test_foo_runner.o`. Ceedling finds the files, generates
+mocks, generates a runner, compiles all the files, and links
+everything into the test executable. Ceedling will then run
+the test executable and collect test results from it to be reported
+to the developer at the command line.
+
+For more on the assertions and mocks shown, consult the documentation
+for Unity and CMock.
+
+The Magic of Dependency Tracking
+--------------------------------
+
+Ceedling is pretty smart in using Rake to build up your project's
+dependencies. This means that Ceedling automagically rebuilds
+all the appropriate files in your project when necessary: when
+your configuration changes, Ceedling or any of the other tools
+are updated, or your source or test files change. For instance,
+if you modify a header file that is mocked, Ceedling will ensure
+that the mock is regenerated and all tests that use that mock are
+rebuilt and re-run when you initiate a relevant testing task.
+When you see things rebuilding, it's for a good reason. Ceedling
+attempts to regenerate and rebuild only what's needed for a given
+execution of a task. In the case of large projects, assembling
+dependencies and acting upon them can cause some delay in executing
+tasks.
+
+With one exception, the trigger to rebuild or regenerate a file
+is always a disparity in timestamps between a target file and
+its source - if an input file is newer than its target dependency,
+the target is rebuilt or regenerated. For example, if the C source
+file from which an object file is compiled is newer than that object
+file on disk, recompilation will occur (of course, if no object
+file exists on disk, compilation will always occur). The one
+exception to this dependency behavior is specific to your input
+configuration. Only if your logical configuration changes
+will a system-wide rebuild occur. Reorganizing your input configuration
+or otherwise updating its file timestamp without modifying
+the values within the file will not trigger a rebuild. This behavior
+handles the various ways in which your input configuration can
+change (discussed later in this document) without having changed
+your actual project YAML file.
+
+Ceedling needs a bit of help to accomplish its magic with deep
+dependencies. Shallow dependencies are straightforward:
+a mock is dependent on the header file from which it's generated,
+a test file is dependent upon the source files it includes (see
+the preceding conventions section), etc. Ceedling handles
+these "out of the box." Deep dependencies are specifically a
+C-related phenomenon and occur as a consequence of include statements
+within C source files. Say a source file includes a header file
+and that header file in turn includes another header file which
+includes still another header file. A change to the deepest header
+file should trigger a recompilation of the source file, a relinking
+of all the object files comprising a test fixture, and a new execution
+of that test fixture.
+
+Ceedling can handle deep dependencies but only with the help
+of a C preprocessor. Ceedling is quite capable, but a full C preprocessor
+it ain't. Your project can be configured to use a C preprocessor
+or not. Simple projects or large projects constructed so as to
+be quite flat in their include structure generally don't need
+deep dependency preprocessing - and can enjoy the benefits of
+faster execution. Legacy code, on the other hand, will almost
+always want to be tested with deep preprocessing enabled. Set
+up of the C preprocessor is covered in the documentation for the
+[:project] and [:tools] section of the configuration file (later
+in this document). Ceedling contains all the configuration
+necessary to use the gcc preprocessor by default. That is, as
+long as gcc is in your system search path, deep preprocessing
+of deep dependencies is available to you by simply enabling it
+in your project configuration file.
+
+Ceedling's Build Output
+-----------------------
+
+Ceedling requires a top-level build directory for all the stuff
+that it, the accompanying test tools, and your toolchain generate.
+That build directory's location is configured in the [:project]
+section of your configuration file (discussed later). There
+can be a ton of generated files. By and large, you can live a full
+and meaningful life knowing absolutely nothing at all about
+the files and directories generated below the root build directory.
+
+As noted already, it's good practice to add your top-level build
+directory to source control but nothing generated beneath it.
+You'll spare yourself headache if you let Ceedling delete and
+regenerate files and directories in a non-versioned corner
+of your project's filesystem beneath the top-level build directory.
+
+The `artifacts` directory is the one and only directory you may
+want to know about beneath the top-level build directory. The
+subdirectories beneath `artifacts` will hold your binary release
+target output (if your project is configured for release builds)
+and will serve as the conventional location for plugin output.
+This directory structure was chosen specifically because it
+tends to work nicely with Continuous Integration setups that
+recognize and list build artifacts for retrieval / download.
+
+The Almighty Project Configuration File (in Glorious YAML)
+----------------------------------------------------------
+
+Please consult YAML documentation for the finer points of format
+and to understand details of our YAML-based configuration file.
+We recommend [Wikipedia's entry on YAML](http://en.wikipedia.org/wiki/Yaml)
+for this. A few highlights from that reference page:
+
+* YAML streams are encoded using the set of printable Unicode
+ characters, either in UTF-8 or UTF-16
+
+* Whitespace indentation is used to denote structure; however
+ tab characters are never allowed as indentation
+
+* Comments begin with the number sign ( # ), can start anywhere
+ on a line, and continue until the end of the line unless enclosed
+ by quotes
+
+* List members are denoted by a leading hyphen ( - ) with one member
+ per line, or enclosed in square brackets ( [ ] ) and separated
+ by comma space ( , )
+
+* Hashes are represented using the colon space ( : ) in the form
+ key: value, either one per line or enclosed in curly braces
+ ( { } ) and separated by comma space ( , )
+
+* Strings (scalars) are ordinarily unquoted, but may be enclosed
+ in double-quotes ( " ), or single-quotes ( ' )
+
+* YAML requires that colons and commas used as list separators
+ be followed by a space so that scalar values containing embedded
+ punctuation can generally be represented without needing
+ to be enclosed in quotes
+
+* Repeated nodes are initially denoted by an ampersand ( & ) and
+ thereafter referenced with an asterisk ( * )
+
+
+Notes on what follows:
+
+* Each of the following sections represent top-level entries
+ in the YAML configuration file.
+
+* Unless explicitly specified in the configuration file, default
+ values are used by Ceedling.
+
+* These three settings, at minimum, must be specified:
+ * [:project][:build_root]
+ * [:paths][:source]
+ * [:paths][:test]
+
+* As much as is possible, Ceedling validates your settings in
+ properly formed YAML.
+
+* Improperly formed YAML will cause a Ruby error when the YAML
+ is parsed. This is usually accompanied by a complaint with
+ line and column number pointing into the project file.
+
+* Certain advanced features rely on gcc and cpp as preprocessing
+ tools. In most *nix systems, these tools are already available.
+ For Windows environments, we recommend the [mingw project](http://www.mingw.org/)
+ (Minimalist GNU for Windows).
+
+* Ceedling is primarily meant as a build tool to support automated
+ unit testing. All the heavy lifting is involved there. Creating
+ a simple binary release build artifact is quite trivial in
+ comparison. Consequently, most default options and the construction
+ of Ceedling itself is skewed towards supporting testing though
+ Ceedling can, of course, build your binary release artifact
+ as well. Note that complex binary release artifacts (e.g.
+ application + bootloader or multiple libraries) are beyond
+ Ceedling's release build ability.
+
+
+Conventions / features of Ceedling-specific YAML:
+
+* Any second tier setting keys anywhere in YAML whose names end
+ in `_path` or `_paths` are automagically processed like all
+ Ceedling-specific paths in the YAML to have consistent directory
+ separators (i.e. "/") and to take advantage of inline Ruby
+ string expansion (see [:environment] setting below for further
+ explanation of string expansion).
+
+
+**Let's Be Careful Out There:** Ceedling performs validation
+on the values you set in your configuration file (this assumes
+your YAML is correct and will not fail format parsing, of course).
+That said, validation is limited to only those settings Ceedling
+uses and those that can be reasonably validated. Ceedling does
+not limit what can exist within your configuration file. In this
+way, you can take full advantage of YAML as well as add sections
+and values for use in your own custom plugins (documented later).
+The consequence of this is simple but important. A misspelled
+configuration section name or value name is unlikely to cause
+Ceedling any trouble. Ceedling will happily process that section
+or value and simply use the properly spelled default maintained
+internally - thus leading to unexpected behavior without warning.
+
+project: global project settings
+
+
+* `build_root`:
+
+ Top level directory into which generated path structure and files are
+ placed. Note: this is one of the handful of configuration values that
+ must be set. The specified path can be absolute or relative to your
+ working directory.
+
+ **Default**: (none)
+
+* `use_exceptions`:
+
+ Configures the build environment to make use of CException. Note that
+ if you do not use exceptions, there's no harm in leaving this as its
+ default value.
+
+ **Default**: TRUE
+
+* `use_mocks`:
+
+ Configures the build environment to make use of CMock. Note that if
+ you do not use mocks, there's no harm in leaving this setting as its
+ default value.
+
+ **Default**: TRUE
+
+* `use_test_preprocessor`:
+
+ This option allows Ceedling to work with test files that contain
+ conditional compilation statements (e.g. #ifdef) and header files you
+ wish to mock that contain conditional preprocessor statements and/or
+ macros.
+
+ Ceedling and CMock are advanced tools with sophisticated parsers.
+ However, they do not include entire C language preprocessors.
+ Consequently, with this option enabled, Ceedling will use gcc's
+ preprocessing mode and the cpp preprocessor tool to strip down /
+ expand test files and headers to their applicable content which can
+ then be processed by Ceedling and CMock.
+
+ With this option enabled, the gcc & cpp tools must exist in an
+ accessible system search path and test runner files are always
+ regenerated.
+
+ **Default**: FALSE
+
+* `use_deep_dependencies`:
+
+ The base rules and tasks that Ceedling creates using Rake capture most
+ of the dependencies within a standard project (e.g. when the source
+ file accompanying a test file changes, the corresponding test fixture
+ executable will be rebuilt when tests are re-run). However, deep
+ dependencies cannot be captured this way. If a typedef or macro
+ changes in a header file three levels of #include statements deep,
+ this option allows the appropriate incremental build actions to occur
+ for both test execution and release builds.
+
+ This is accomplished by using the dependencies discovery mode of gcc.
+ With this option enabled, gcc must exist in an accessible system
+ search path.
+
+ **Default**: FALSE
+
+* `generate_deep_dependencies`:
+
+ When `use_deep_dependencies` is set to TRUE, Ceedling will run a separate
+ build step to generate the deep dependencies. If you are using gcc as your
+ primary compiler, or another compiler that can generate makefile rules as
+ a side effect of compilation, then you can set this to FALSE to avoid the
+ extra build step but still use the deep dependencies data when deciding
+ which source files to rebuild.
+
+ **Default**: TRUE
+
+* `test_file_prefix`:
+
+ Ceedling collects test files by convention from within the test file
+ search paths. The convention includes a unique name prefix and a file
+ extension matching that of source files.
+
+ Why not simply recognize all files in test directories as test files?
+ By using the given convention, we have greater flexibility in what we
+ do with C files in the test directories.
+
+ **Default**: "test_"
+
+* `options_paths`:
+
+ Just as you may have various build configurations for your source
+ codebase, you may need variations of your project configuration.
+
+ By specifying options paths, Ceedling will search for other project
+ YAML files, make command line tasks available (ceedling options:variation
+ for a variation.yml file), and merge the project configuration of
+ these option files in with the main project file at runtime. See
+ advanced topics.
+
+ Note these Rake tasks at the command line - like verbosity or logging
+ control - must come before the test or release task they are meant to
+ modify.
+
+ **Default**: [] (empty)
+
+* `release_build`:
+
+ When enabled, a release Rake task is exposed. This configuration
+ option requires a corresponding release compiler and linker to be
+ defined (gcc is used as the default).
+
+ More release configuration options are available in the release_build
+ section.
+
+ **Default**: FALSE
+
+
+Example `[:project]` YAML blurb
+
+```yaml
+:project:
+ :build_root: project_awesome/build
+ :use_exceptions: FALSE
+ :use_test_preprocessor: TRUE
+ :use_deep_dependencies: TRUE
+ :options_paths:
+ - project/options
+ - external/shared/options
+ :release_build: TRUE
+```
+
+Ceedling is primarily concerned with facilitating the somewhat
+complicated mechanics of automating unit tests. The same mechanisms
+are easily capable of building a final release binary artifact
+(i.e. non test code; the thing that is your final working software
+that you execute on target hardware).
+
+
+* `output`:
+
+ The name of your release build binary artifact to be found in <build
+ path>/artifacts/release. Ceedling sets the default artifact file
+ extension to that as is explicitly specified in the [:extensions]
+ section or as is system specific otherwise.
+
+ **Default**: `project.exe` or `project.out`
+
+* `use_assembly`:
+
+ If assembly code is present in the source tree, this option causes
+ Ceedling to create appropriate build directories and use an assembler
+ tool (default is the GNU tool as - override available in the [:tools]
+ section.
+
+ **Default**: FALSE
+
+* `artifacts`:
+
+ By default, Ceedling copies to the <build path>/artifacts/release
+ directory the output of the release linker and (optionally) a map
+ file. Many toolchains produce other important output files as well.
+ Adding a file path to this list will cause Ceedling to copy that file
+ to the artifacts directory. The artifacts directory is helpful for
+ organizing important build output files and provides a central place
+ for tools such as Continuous Integration servers to point to build
+ output. Selectively copying files prevents incidental build cruft from
+ needlessly appearing in the artifacts directory. Note that inline Ruby
+ string replacement is available in the artifacts paths (see discussion
+ in the [:environment] section).
+
+ **Default**: [] (empty)
+
+Example `[:release_build]` YAML blurb
+
+```yaml
+:release_build:
+ :output: top_secret.bin
+ :use_assembly: TRUE
+ :artifacts:
+ - build/release/out/c/top_secret.s19
+```
+
+**paths**: options controlling search paths for source and header
+(and assembly) files
+
+* `test`:
+
+ All C files containing unit test code. Note: this is one of the
+ handful of configuration values that must be set.
+
+ **Default**: [] (empty)
+
+* `source`:
+
+ All C files containing release code (code to be tested). Note: this is
+ one of the handful of configuration values that must be set.
+
+ **Default**: [] (empty)
+
+* `support`:
+
+ Any C files you might need to aid your unit testing. For example, on
+ occasion, you may need to create a header file containing a subset of
+ function signatures matching those elsewhere in your code (e.g. a
+ subset of your OS functions, a portion of a library API, etc.). Why?
+ To provide finer grained control over mock function substitution or
+ limiting the size of the generated mocks.
+
+ **Default**: [] (empty)
+
+* `include`:
+
+ Any header files not already in the source search path. Note there's
+ no practical distinction between this search path and the source
+ search path; it's merely to provide options or to support any
+ peculiar source tree organization.
+
+ **Default**: [] (empty)
+
+* `test_toolchain_include`:
+
+ System header files needed by the test toolchain - should your
+ compiler be unable to find them, finds the wrong system include search
+ path, or you need a creative solution to a tricky technical problem.
+ Note that if you configure your own toolchain in the [:tools] section,
+ this search path is largely meaningless to you. However, this is a
+ convenient way to control the system include path should you rely on
+ the default gcc tools.
+
+ **Default**: [] (empty)
+
+* `release_toolchain_include`:
+
+ Same as preceding albeit related to the release toolchain.
+
+ **Default**: [] (empty)
+
+* `<custom>`
+
+ Any paths you specify for custom list. List is available to tool
+ configurations and/or plugins. Note a distinction. The preceding names
+ are recognized internally to Ceedling and the path lists are used to
+ build collections of files contained in those paths. A custom list is
+ just that - a custom list of paths.
+
+Notes on path grammar within the [:paths] section:
+
+* Order of search paths listed in [:paths] is preserved when used by an
+ entry in the [:tools] section
+
+* Wherever multiple path lists are combined for use Ceedling prioritizes
+ path groups as follows:
+ test paths, support paths, source paths, include paths.
+
+ This can be useful, for instance, in certain testing scenarios where
+ we desire Ceedling or the compiler to find a stand-in header file before
+ the actual source header file of the same name.
+
+* Paths:
+
+ 1. can be absolute or relative
+
+ 2. can be singly explicit - a single fully specified path
+
+ 3. can include a glob operator (more on this below)
+
+ 4. can use inline Ruby string replacement (see [:environment]
+ section for more)
+
+ 5. default as an addition to a specific search list (more on this
+ in the examples)
+
+ 6. can act to subtract from a glob included in the path list (more
+ on this in the examples)
+
+
+[Globs](http://ruby.about.com/od/beginningruby/a/dir2.htm)
+as used by Ceedling are wildcards for specifying directories
+without the need to list each and every required search path.
+Ceedling globs operate just as Ruby globs except that they are
+limited to matching directories and not files. Glob operators
+include the following * ** ? [-] {,} (note: this list is space separated
+and not comma separated as commas are used within the bracket
+operators).
+
+* `*`:
+
+ All subdirectories of depth 1 below the parent path and including the
+ parent path
+
+* `**`:
+
+ All subdirectories recursively discovered below the parent path and
+ including the parent path
+
+* `?`:
+
+ Single alphanumeric character wildcard
+
+* `[x-y]`:
+
+ Single alphanumeric character as found in the specified range
+
+* `{x,y}`:
+
+ Single alphanumeric character from the specified list
+
+Example [:paths] YAML blurbs
+
+```yaml
+:paths:
+ :source: #together the following comprise all source search paths
+ - project/source/* #expansion yields all subdirectories of depth 1 plus parent directory
+ - project/lib #single path
+ :test: #all test search paths
+ - project/**/test? #expansion yields any subdirectory found anywhere in the project that
+ #begins with "test" and contains 5 characters
+
+:paths:
+ :source: #all source search paths
+ - +:project/source/** #all subdirectories recursively discovered plus parent directory
+ - -:project/source/os/generated #subtract os/generated directory from expansion of above glob
+ #note that '+:' notation is merely aesthetic; default is to add
+
+ :test: #all test search paths
+ - project/test/bootloader #explicit, single search paths (searched in the order specified)
+ - project/test/application
+ - project/test/utilities
+
+ :custom: #custom path list
+ - "#{PROJECT_ROOT}/other" #inline Ruby string expansion
+```
+
+Globs and inline Ruby string expansion can require trial and
+error to arrive at your intended results. Use the `ceedling paths:*`
+command line options (documented in preceding section) to verify
+your settings.
+
+Ceedling relies on file collections automagically assembled
+from paths, globs, and file extensions. File collections greatly
+simplify project set up. However, sometimes you need to remove
+from or add individual files to those collections.
+
+
+* `test`:
+
+ Modify the collection of unit test C files.
+
+ **Default**: [] (empty)
+
+* `source`:
+
+ Modify the collection of all source files used in unit test builds and release builds.
+
+ **Default**: [] (empty)
+
+* `assembly`:
+
+ Modify the (optional) collection of assembly files used in release builds.
+
+ **Default**: [] (empty)
+
+* `include`:
+
+ Modify the collection of all source header files used in unit test builds (e.g. for mocking) and release builds.
+
+ **Default**: [] (empty)
+
+* `support`:
+
+ Modify the collection of supporting C files available to unit tests builds.
+
+ **Default**: [] (empty)
+
+
+Note: All path grammar documented in [:paths] section applies
+to [:files] path entries - albeit at the file path level and not
+the directory level.
+
+Example [:files] YAML blurb
+
+```yaml
+:files:
+ :source:
+ - callbacks/comm.c # entry defaults to file addition
+ - +:callbacks/comm*.c # add all comm files matching glob pattern
+ - -:source/board/atm134.c # not our board
+ :test:
+ - -:test/io/test_output_manager.c # remove unit tests from test build
+```
+
+**environment:** inserts environment variables into the shell
+instance executing configured tools
+
+Ceedling creates environment variables from any key / value
+pairs in the environment section. Keys become an environment
+variable name in uppercase. The values are strings assigned
+to those environment variables. These value strings are either
+simple string values in YAML or the concatenation of a YAML array.
+
+Ceedling is able to execute inline Ruby string substitution
+code to set environment variables. This evaluation occurs when
+the project file is first processed for any environment pair's
+value string including the Ruby string substitution pattern
+`#{…}`. Note that environment value strings that _begin_ with
+this pattern should always be enclosed in quotes. YAML defaults
+to processing unquoted text as a string; quoting text is optional.
+If an environment pair's value string begins with the Ruby string
+substitution pattern, YAML will interpret the string as a Ruby
+comment (because of the `#`). Enclosing each environment value
+string in quotes is a safe practice.
+
+[:environment] entries are processed in the configured order
+(later entries can reference earlier entries).
+
+Special case: PATH handling
+
+In the specific case of specifying an environment key named _path_,
+an array of string values will be concatenated with the appropriate
+platform-specific path separation character (e.g. ':' on *nix,
+';' on Windows). All other instances of environment keys assigned
+YAML arrays use simple concatenation.
+
+Example [:environment] YAML blurb
+
+```yaml
+:environment:
+ - :license_server: gizmo.intranet #LICENSE_SERVER set with value "gizmo.intranet"
+ - :license: "#{`license.exe`}" #LICENSE set to string generated from shelling out to
+ #execute license.exe; note use of enclosing quotes
+
+ - :path: #concatenated with path separator (see special case above)
+ - Tools/gizmo/bin #prepend existing PATH with gizmo path
+ - "#{ENV['PATH']}" #pattern #{…} triggers ruby evaluation string substitution
+ #note: value string must be quoted because of '#'
+
+ - :logfile: system/logs/thingamabob.log #LOGFILE set with path for a log file
+```
+
+**extension**: configure file name extensions used to collect lists of files searched in [:paths]
+
+* `header`:
+
+ C header files
+
+ **Default**: .h
+
+* `source`:
+
+ C code files (whether source or test files)
+
+ **Default**: .c
+
+* `assembly`:
+
+ Assembly files (contents wholly assembly instructions)
+
+ **Default**: .s
+
+* `object`:
+
+ Resulting binary output of C code compiler (and assembler)
+
+ **Default**: .o
+
+* `executable`:
+
+ Binary executable to be loaded and executed upon target hardware
+
+ **Default**: .exe or .out (Win or *nix)
+
+* `testpass`:
+
+ Test results file (not likely to ever need a new value)
+
+ **Default**: .pass
+
+* `testfail`:
+
+ Test results file (not likely to ever need a new value)
+
+ **Default**: .fail
+
+* `dependencies`:
+
+ File containing make-style dependency rules created by gcc preprocessor
+
+ **Default**: .d
+
+
+Example [:extension] YAML blurb
+
+ :extension:
+ :source: .cc
+ :executable: .bin
+
+**defines**: command line defines used in test and release compilation by configured tools
+
+* `test`:
+
+ Defines needed for testing. Useful for:
+
+ 1. test files containing conditional compilation statements (i.e.
+ tests active in only certain contexts)
+
+ 2. testing legacy source wherein the isolation of source under test
+ afforded by Ceedling and its complementary tools leaves certain
+ symbols unset when source files are compiled in isolation
+
+ **Default**: [] (empty)
+
+* `test_preprocess`:
+
+ If [:project][:use_test_preprocessor] or
+ [:project][:use_deep_dependencies] is set and code is structured in a
+ certain way, the gcc preprocessor may need symbol definitions to
+ properly preprocess files to extract function signatures for mocking
+ and extract deep dependencies for incremental builds.
+
+ **Default**: [] (empty)
+
+* `release`:
+
+ Defines needed for the release build binary artifact.
+
+ **Default**: [] (empty)
+
+* `release_preprocess`:
+
+ If [:project][:use_deep_dependencies] is set and code is structured in
+ a certain way, the gcc preprocessor may need symbol definitions to
+ properly preprocess files for incremental release builds due to deep
+ dependencies.
+
+ **Default**: [] (empty)
+
+
+Example [:defines] YAML blurb
+
+```yaml
+:defines:
+ :test:
+ - UNIT_TESTING #for select cases in source to allow testing with a changed behavior or interface
+ - OFF=0
+ - ON=1
+ - FEATURE_X=ON
+ :source:
+ - FEATURE_X=ON
+```
+
+
+**libraries**: command line defines used in test and release compilation by configured tools
+
+Ceedling allows you to pull in specific libraries for the purpose of release and test builds.
+It has a few levels of support for this. Start by adding a :libraries main section in your
+configuration. In this section, you can optionally have the following subsections:
+
+* `test`:
+
+ Library files that should be injected into your tests when linking occurs.
+ These can be specified as either relative or absolute paths. These files MUST
+ exist when the test attempts to build.
+
+* `source`:
+
+ Library files that should be injected into your release when linking occurs. These
+ can be specified as either relative or absolute paths. These files MUST exist when
+ the release attempts to build UNLESS you are using the subprojects plugin. In that
+ case, it will attempt to build that library for you as a dynamic dependency.
+
+* `system`:
+
+ These libraries are assumed to be in the tool path somewhere and shouldn't need to be
+ specified. The libraries added here will be injected into releases and tests.
+
+* `flag`:
+
+ This is the method of adding an argument for each library. For example, gcc really likes
+ it when you specify “-l${1}”
+
+Notes:
+
+* If you've specified your own link step, you are going to want to add ${4} to your argument
+list in the place where library files should be added to the command call. For gcc, this is
+often the very end. Other tools may vary.
+
+
+**flags**: configure per-file compilation and linking flags
+
+Ceedling tools (see later [:tools] section) are used to configure
+compilation and linking of test and source files. These tool
+configurations are a one-size-fits-all approach. Should individual files
+require special compilation or linking flags, the settings in the
+[:flags] section work in conjunction with tool definitions by way of
+argument substitution to achieve this.
+
+* `release`:
+
+ [:compile] or [:link] flags for release build
+
+* `test`:
+
+ [:compile] or [:link] flags for test build
+
+Notes:
+
+* Ceedling works with the [:release] and [:test] build contexts
+ as-is; plugins can add additional contexts
+
+* Only [:compile] and [:link] are recognized operations beneath
+ a context
+
+* File specifiers do not include a path or file extension
+
+* File specifiers are case sensitive (must match original file
+ name)
+
+* File specifiers do support regular expressions if encased in quotes
+
+* '*' is a special (optional) file specifier to provide flags
+ to all files not otherwise specified
+
+
+Example [:flags] YAML blurb
+
+```yaml
+:flags:
+ :release:
+ :compile:
+ :main: # add '-Wall' to compilation of main.c
+ - -Wall
+ :fan: # add '--O2' to compilation of fan.c
+ - --O2
+ :'test_.+': # add '-pedantic' to all test-files
+ - -pedantic
+ :*: # add '-foo' to compilation of all files not main.c or fan.c
+ - -foo
+ :test:
+ :compile:
+ :main: # add '--O1' to compilation of main.c as part of test builds including main.c
+ - --O1
+ :link:
+ :test_main: # add '--bar --baz' to linking of test_main.exe
+ - --bar
+ - --baz
+```
+
+Ceedling sets values for a subset of CMock settings. All CMock
+options are available to be set, but only those options set by
+Ceedling in an automated fashion are documented below. See CMock
+documentation.
+
+**cmock**: configure CMock's code generation options and set symbols used to modify CMock's compiled features
+Ceedling sets values for a subset of CMock settings. All CMock options are available to be set, but only those options set by Ceedling in an automated fashion are documented below. See CMock documentation.
+
+* `enforce_strict_ordering`:
+
+ Tests fail if expected call order is not same as source order
+
+ **Default**: TRUE
+
+* `mock_path`:
+
+ Path for generated mocks
+
+ **Default**: <build path>/tests/mocks
+
+* `defines`:
+
+ List of conditional compilation symbols used to configure CMock's
+ compiled features. See CMock documentation to understand available
+ options. No symbols must be set unless defaults are inappropriate for
+ your specific environment. All symbols are used only by Ceedling to
+ compile CMock C code; contents of [:defines] are ignored by CMock's
+ Ruby code when instantiated.
+
+ **Default**: [] (empty)
+
+* `verbosity`:
+
+ If not set, defaults to Ceedling's verbosity level
+
+* `plugins`:
+
+ If [:project][:use_exceptions] is enabled, the internal plugins list is pre-populated with 'cexception'.
+
+ Whether or not you have included [:cmock][:plugins] in your
+ configuration file, Ceedling automatically adds 'cexception' to the
+ plugin list if exceptions are enabled. To add to the list Ceedling
+ provides CMock, simply add [:cmock][:plugins] to your configuration
+ and specify your desired additional plugins.
+
+* `includes`:
+
+ If [:cmock][:unity_helper] set, pre-populated with unity_helper file
+ name (no path).
+
+ The [:cmock][:includes] list works identically to the plugins list
+ above with regard to adding additional files to be inserted within
+ mocks as #include statements.
+
+
+The last four settings above are directly tied to other Ceedling
+settings; hence, why they are listed and explained here. The
+first setting above, [:enforce_strict_ordering], defaults
+to FALSE within CMock. It is set to TRUE by default in Ceedling
+as our way of encouraging you to use strict ordering. It's a teeny
+bit more expensive in terms of code generated, test execution
+time, and complication in deciphering test failures. However,
+it's good practice. And, of course, you can always disable it
+by overriding the value in the Ceedling YAML configuration file.
+
+
+**cexception**: configure symbols used to modify CException's compiled features
+
+* `defines`:
+
+ List of conditional compilation symbols used to configure CException's
+ features in its source and header files. See CException documentation
+ to understand available options. No symbols must be set unless the
+ defaults are inappropriate for your specific environment.
+
+ **Default**: [] (empty)
+
+
+**unity**: configure symbols used to modify Unity's compiled features
+
+* `defines`:
+
+ List of conditional compilation symbols used to configure Unity's
+ features in its source and header files. See Unity documentation to
+ understand available options. No symbols must be set unless the
+ defaults are inappropriate for your specific environment. Most Unity
+ defines can be easily configured through the YAML file.
+
+ **Default**: [] (empty)
+
+Example [:unity] YAML blurbs
+```yaml
+:unity: #itty bitty processor & toolchain with limited test execution options
+ :defines:
+ - UNITY_INT_WIDTH=16 #16 bit processor without support for 32 bit instructions
+ - UNITY_EXCLUDE_FLOAT #no floating point unit
+
+:unity: #great big gorilla processor that grunts and scratches
+ :defines:
+ - UNITY_SUPPORT_64 #big memory, big counters, big registers
+ - UNITY_LINE_TYPE=\"unsigned int\" #apparently we're using really long test files,
+ - UNITY_COUNTER_TYPE=\"unsigned int\" #and we've got a ton of test cases in those test files
+ - UNITY_FLOAT_TYPE=\"double\" #you betcha
+```
+
+
+Notes on Unity configuration:
+
+* **Verification** - Ceedling does no verification of your configuration
+ values. In a properly configured setup, your Unity configuration
+ values are processed, collected together with any test define symbols
+ you specify elsewhere, and then passed to your toolchain during test
+ compilation. Unity's conditional compilation statements, your
+ toolchain's preprocessor, and/or your toolchain's compiler will
+ complain appropriately if your specified configuration values are
+ incorrect, incomplete, or incompatible.
+
+* **Routing $stdout** - Unity defaults to using `putchar()` in C's
+ standard library to display test results. For more exotic environments
+ than a desktop with a terminal (e.g. running tests directly on a
+ non-PC target), you have options. For example, you could create a
+ routine that transmits a character via RS232 or USB. Once you have
+ that routine, you can replace `putchar()` calls in Unity by overriding
+ the function-like macro `UNITY_OUTPUT_CHAR`. Consult your toolchain
+ and shell documentation. Eventhough this can also be defined in the YAML file
+ most shell environments do not handle parentheses as command line arguments
+ very well. To still be able to add this functionality all necessary
+ options can be defined in the `unity_config.h`. Unity needs to be told to look for
+ the `unity_config.h` in the YAML file, though.
+
+Example [:unity] YAML blurbs
+```yaml
+:unity:
+ :defines:
+ - UNITY_INCLUDE_CONFIG_H
+```
+
+Example unity_config.h
+```
+#ifndef UNITY_CONFIG_H
+#define UNITY_CONFIG_H
+
+#include "uart_output.h" //Helper library for your custom environment
+
+#define UNITY_INT_WIDTH 16
+#define UNITY_OUTPUT_START() uart_init(F_CPU, BAUD) //Helperfunction to init UART
+#define UNITY_OUTPUT_CHAR(a) uart_putchar(a) //Helperfunction to forward char via UART
+#define UNITY_OUTPUT_COMPLETE() uart_complete() //Helperfunction to inform that test has ended
+
+#endif
+```
+
+
+**tools**: a means for representing command line tools for use under
+Ceedling's automation framework
+
+Ceedling requires a variety of tools to work its magic. By default,
+the GNU toolchain (gcc, cpp, as) are configured and ready for
+use with no additions to the project configuration YAML file.
+However, as most work will require a project-specific toolchain,
+Ceedling provides a generic means for specifying / overriding
+tools.
+
+* `test_compiler`:
+
+ Compiler for test & source-under-test code
+ ${1}: input source ${2}: output object ${3}: optional output list ${4}: optional output dependencies file
+
+ **Default**: gcc
+
+* `test_linker`:
+
+ Linker to generate test fixture executables
+ ${1}: input objects ${2}: output binary ${3}: optional output map ${4}: optional library list
+
+ **Default**: gcc
+
+* `test_fixture`:
+
+ Executable test fixture
+ ${1}: simulator as executable with ${1} as input binary file argument or native test executable
+
+ **Default**: ${1}
+
+* `test_includes_preprocessor`:
+
+ Extractor of #include statements
+ ${1}: input source file
+
+ **Default**: cpp
+
+* `test_file_preprocessor`:
+
+ Preprocessor of test files (macros, conditional compilation statements)
+ ${1}: input source file ${2}: preprocessed output source file
+
+ **Default**: gcc
+
+* `test_dependencies_generator`:
+
+ Discovers deep dependencies of source & test (for incremental builds)
+ ${1}: input source file ${2}: compiled object filepath ${3}: output dependencies file
+
+ **Default**: gcc
+
+* `release_compiler`:
+
+ Compiler for release source code
+ ${1}: input source ${2}: output object ${3}: optional output list ${4}: optional output dependencies file
+
+ **Default**: gcc
+
+* `release_assembler`:
+
+ Assembler for release assembly code
+ ${1}: input assembly source file ${2}: output object file
+
+ **Default**: as
+
+* `release_linker`:
+
+ Linker for release source code
+ ${1}: input objects ${2}: output binary ${3}: optional output map ${4}: optional library list
+
+ **Default**: gcc
+
+* `release_dependencies_generator`:
+
+ Discovers deep dependencies of source files (for incremental builds)
+ ${1}: input source file ${2}: compiled object filepath ${3}: output dependencies file
+
+ **Default**: gcc
+
+
+A Ceedling tool has a handful of configurable elements:
+
+1. [:executable] (required) - Command line executable having
+ the form of:
+
+2. [:arguments] (required) - List of command line arguments
+ and substitutions
+
+3. [:name] - Simple name (e.g. "nickname") of tool beyond its
+ executable name (if not explicitly set then Ceedling will
+ form a name from the tool's YAML entry name)
+
+4. [:stderr_redirect] - Control of capturing $stderr messages
+ {:none, :auto, :win, :unix, :tcsh}.
+ Defaults to :none if unspecified; create a custom entry by
+ specifying a simple string instead of any of the available
+ symbols.
+
+5. [:background_exec] - Control execution as background process
+ {:none, :auto, :win, :unix}.
+ Defaults to :none if unspecified.
+
+
+Tool Element Runtime Substitution
+---------------------------------
+
+To accomplish useful work on multiple files, a configured tool will most
+often require that some number of its arguments or even the executable
+itself change for each run. Consequently, every tool's argument list and
+executable field possess two means for substitution at runtime. Ceedling
+provides two kinds of inline Ruby execution and a notation for
+populating elements with dynamically gathered values within the build
+environment.
+
+Tool Element Runtime Substitution: Inline Ruby Execution
+--------------------------------------------------------
+
+In-line Ruby execution works similarly to that demonstrated for the
+[:environment] section except that substitution occurs as the tool is
+executed and not at the time the configuration file is first scanned.
+
+* `#{...}`:
+
+ Ruby string substitution pattern wherein the containing string is
+ expanded to include the string generated by Ruby code between the
+ braces. Multiple instances of this expansion can occur within a single
+ tool element entry string. Note that if this string substitution
+ pattern occurs at the very beginning of a string in the YAML
+ configuration the entire string should be enclosed in quotes (see the
+ [:environment] section for further explanation on this point).
+
+* `{...} `:
+
+ If an entire tool element string is enclosed with braces, it signifies
+ that Ceedling should execute the Ruby code contained within those
+ braces. Say you have a collection of paths on disk and some of those
+ paths include spaces. Further suppose that a single tool that must use
+ those paths requires those spaces to be escaped, but all other uses of
+ those paths requires the paths to remain unchanged. You could use this
+ Ceedling feature to insert Ruby code that iterates those paths and
+ escapes those spaces in the array as used by the tool of this example.
+
+Tool Element Runtime Substitution: Notational Substitution
+----------------------------------------------------------
+
+A Ceedling tool's other form of dynamic substitution relies on a '$'
+notation. These '$' operators can exist anywhere in a string and can be
+decorated in any way needed. To use a literal '$', escape it as '\\$'.
+
+* `$`:
+
+ Simple substitution for value(s) globally available within the runtime
+ (most often a string or an array).
+
+* `${#}`:
+
+ When a Ceedling tool's command line is expanded from its configured
+ representation and used within Ceedling Ruby code, certain calls to
+ that tool will be made with a parameter list of substitution values.
+ Each numbered substitution corresponds to a position in a parameter
+ list. Ceedling Ruby code expects that configured compiler and linker
+ tools will contain ${1} and ${2} replacement arguments. In the case of
+ a compiler ${1} will be a C code file path, and ${2} will be the file
+ path of the resulting object file. For a linker ${1} will be an array
+ of object files to link, and ${2} will be the resulting binary
+ executable. For an executable test fixture ${1} is either the binary
+ executable itself (when using a local toolchain such as gcc) or a
+ binary input file given to a simulator in its arguments.
+
+
+Example [:tools] YAML blurbs
+
+```yaml
+:tools:
+ :test_compiler:
+ :executable: compiler #exists in system search path
+ :name: 'acme test compiler'
+ :arguments:
+ - -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE #expands to -I search paths
+ - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR #expands to -I search paths
+ - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR #expands to all -D defined symbols
+ - --network-license #simple command line argument
+ - -optimize-level 4 #simple command line argument
+ - "#{`args.exe -m acme.prj`}" #in-line ruby sub to shell out & build string of arguments
+ - -c ${1} #source code input file (Ruby method call param list sub)
+ - -o ${2} #object file output (Ruby method call param list sub)
+ :test_linker:
+ :executable: /programs/acme/bin/linker.exe #absolute file path
+ :name: 'acme test linker'
+ :arguments:
+ - ${1} #list of object files to link (Ruby method call param list sub)
+ - -l$-lib: #inline yaml array substitution to link in foo-lib and bar-lib
+ - foo
+ - bar
+ - -o ${2} #executable file output (Ruby method call param list sub)
+ :test_fixture:
+ :executable: tools/bin/acme_simulator.exe #relative file path to command line simulator
+ :name: 'acme test fixture'
+ :stderr_redirect: :win #inform Ceedling what model of $stderr capture to use
+ :arguments:
+ - -mem large #simple command line argument
+ - -f "${1}" #binary executable input file to simulator (Ruby method call param list sub)
+```
+
+Resulting command line constructions from preceding example [:tools] YAML blurbs
+
+ > compiler -I"/usr/include” -I”project/tests”
+ -I"project/tests/support” -I”project/source” -I”project/include”
+ -DTEST -DLONG_NAMES -network-license -optimize-level 4 arg-foo
+ arg-bar arg-baz -c project/source/source.c -o
+ build/tests/out/source.o
+
+[notes: (1.) "arg-foo arg-bar arg-baz" is a fabricated example
+string collected from $stdout as a result of shell execution
+of args.exe
+(2.) the -c and -o arguments are
+fabricated examples simulating a single compilation step for
+a test; ${1} & ${2} are single files]
+
+ > \programs\acme\bin\linker.exe thing.o unity.o
+ test_thing_runner.o test_thing.o mock_foo.o mock_bar.o -lfoo-lib
+ -lbar-lib -o build\tests\out\test_thing.exe
+
+[note: in this scenario ${1} is an array of all the object files
+needed to link a test fixture executable]
+
+ > tools\bin\acme_simulator.exe -mem large -f "build\tests\out\test_thing.bin 2>&1”
+
+[note: (1.) :executable could have simply been ${1} - if we were compiling
+and running native executables instead of cross compiling (2.) we're using
+$stderr redirection to allow us to capture simulator error messages to
+$stdout for display at the run's conclusion]
+
+
+Notes:
+
+* The upper case names are Ruby global constants that Ceedling
+ builds
+
+* "COLLECTION_" indicates that Ceedling did some work to assemble
+ the list. For instance, expanding path globs, combining multiple
+ path globs into a convenient summation, etc.
+
+* At present, $stderr redirection is primarily used to capture
+ errors from test fixtures so that they can be displayed at the
+ conclusion of a test run. For instance, if a simulator detects
+ a memory access violation or a divide by zero error, this notice
+ might go unseen in all the output scrolling past in a terminal.
+
+* The preprocessing tools can each be overridden with non-gcc
+ equivalents. However, this is an advanced feature not yet
+ documented and requires that the replacement toolchain conform
+ to the same conventions used by gcc.
+
+**Ceedling Collection Used in Compilation**:
+
+* `COLLECTION_PATHS_TEST`:
+
+ All test paths
+
+* `COLLECTION_PATHS_SOURCE`:
+
+ All source paths
+
+* `COLLECTION_PATHS_INCLUDE`:
+
+ All include paths
+
+* `COLLECTION_PATHS_SUPPORT`:
+
+ All test support paths
+
+* `COLLECTION_PATHS_SOURCE_AND_INCLUDE`:
+
+ All source and include paths
+
+* `COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR`:
+
+ All source and include paths + applicable vendor paths (e.g.
+ CException's source path if exceptions enabled)
+
+* `COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE`:
+
+ All test toolchain include paths
+
+* `COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE`:
+
+ All test, source, and include paths
+
+* `COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR`:
+
+ All test, source, include, and applicable vendor paths (e.g. Unity's
+ source path plus CMock and CException's source paths if mocks and
+ exceptions are enabled)
+
+* `COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE`:
+
+ All release toolchain include paths
+
+* `COLLECTION_DEFINES_TEST_AND_VENDOR`:
+
+ All symbols specified in [:defines][:test] + symbols defined for
+ enabled vendor tools - e.g. [:unity][:defines], [:cmock][:defines],
+ and [:cexception][:defines]
+
+* `COLLECTION_DEFINES_RELEASE_AND_VENDOR`:
+
+ All symbols specified in [:defines][:release] plus symbols defined by
+[:cexception][:defines] if exceptions are ena bled
+
+
+Notes:
+
+* Other collections exist within Ceedling. However, they are
+ only useful for advanced features not yet documented.
+
+* Wherever multiple path lists are combined for use Ceedling prioritizes
+ path groups as follows: test paths, support paths, source paths, include
+ paths.
+ This can be useful, for instance, in certain testing scenarios
+ where we desire Ceedling or the compiler to find a stand-in header file
+ before the actual source header file of the same name.
+
+
+**plugins**: Ceedling extensions
+
+* `load_paths`:
+
+ Base paths to search for plugin subdirectories or extra ruby functionalit
+
+ **Default**: [] (empty)
+
+* `enabled`:
+
+ List of plugins to be used - a plugin's name is identical to the
+ subdirectory that contains it (and the name of certain files within
+ that subdirectory)
+
+ **Default**: [] (empty)
+
+
+Plugins can provide a variety of added functionality to Ceedling. In
+general use, it's assumed that at least one reporting plugin will be
+used to format test results. However, if no reporting plugins are
+specified, Ceedling will print to `$stdout` the (quite readable) raw
+test results from all test fixtures executed.
+
+Example [:plugins] YAML blurb
+
+```yaml
+:plugins:
+ :load_paths:
+ - project/tools/ceedling/plugins #home to your collection of plugin directories
+ - project/support #maybe home to some ruby code your custom plugins share
+ :enabled:
+ - stdout_pretty_tests_report #nice test results at your command line
+ - our_custom_code_metrics_report #maybe you needed line count and complexity metrics, so you
+ #created a plugin to scan all your code and collect that info
+```
+
+* `stdout_pretty_tests_report`:
+
+ Prints to $stdout a well-formatted list of ignored and failed tests,
+ final test counts, and any extraneous output (e.g. printf statements
+ or simulator memory errors) collected from executing the test
+ fixtures. Meant to be used with runs at the command line.
+
+* `stdout_ide_tests_report`:
+
+ Prints to $stdout simple test results formatted such that an IDE
+ executing test-related Rake tasks can recognize file paths and line
+ numbers in test failures, etc. Thus, you can click a test result in
+ your IDE's execution window and jump to the failure (or ignored test)
+ in your test file (obviously meant to be used with an [IDE like
+ Eclipse][ide], etc).
+
+ [ide]: http://throwtheswitch.org/white-papers/using-with-ides.html
+
+* `xml_tests_report`:
+
+ Creates an XML file of test results in the xUnit format (handy for
+ Continuous Integration build servers or as input to other reporting
+ tools). Produces a file report.xml in <build root>/artifacts/tests.
+
+* `bullseye`:
+
+ Adds additional Rake tasks to execute tests with the commercial code
+ coverage tool provided by [Bullseye][]. See readme.txt inside the bullseye
+ plugin directory for configuration and use instructions. Note:
+ Bullseye only works with certain compilers and linkers (healthy list
+ of supported toolchains though).
+
+ [bullseye]: http://www.bullseye.com
+
+* `gcov`:
+
+ Adds additional Rake tasks to execute tests with the GNU code coverage
+ tool [gcov][]. See readme.txt inside the gcov directory for configuration
+ and use instructions. Only works with GNU compiler and linker.
+
+ [gcov]: http://gcc.gnu.org/onlinedocs/gcc/Gcov.html
+
+* `warnings_report`:
+
+ Scans compiler and linker `$stdout / $stderr` output for the word
+ 'warning' (case insensitive). All code warnings (or tool warnings) are
+ logged to a file warnings.log in the appropriate `<build
+ root>/artifacts` directory (e.g. test/ for test tasks, `release/` for a
+ release build, or even `bullseye/` for bullseye runs).
+
+Module Generator
+========================
+Ceedling includes a plugin called module_generator that will create a source, header and test file for you.
+There are several possibilities to configure this plugin through your project.yml to suit your project's needs.
+
+Directory Structure
+-------------------------------------------
+
+The default configuration for directory/project structure is:
+```yaml
+:module_generator:
+ :project_root: ./
+ :source_root: src/
+ :test_root: test/
+```
+You can change these variables in your project.yml file to comply with your project's directory structure.
+
+If you call `ceedling module:create`, it will create three files:
+1. A source file in the source_root
+2. A header file in the source_root
+3. A test file in the test_root
+
+If you want your header file to be in another location,
+you can specify the ':inc_root:" in your project.yml file:
+```yaml
+:module_generator:
+ :inc_root: inc/
+```
+The module_generator will then create the header file in your defined ':inc_root:'.
+By default, ':inc_root:' is not defined so the module_generator will use the source_root.
+
+Sometimes, your project can't be divided into a single src, inc, and test folder. You have several directories
+with sources/..., something like this for example:
+<project_root>
+ - myDriver
+ - src
+ - inc
+ - test
+ - myOtherDriver
+ - src
+ - inc
+ - test
+ - ...
+
+Don't worry, you don't have to manually create the source/header/test files.
+The module_generator can accept a path to create a source_root/inc_root/test_root folder with your files:
+`ceedling module:create[<module_root_path>:<module_name>]`
+
+F.e., applied to the above project structure:
+`ceedling module:create[myOtherDriver:driver]`
+This will make the module_generator run in the subdirectory 'myOtherDriver' and generate the module files
+for you in that directory. So, this command will generate the following files:
+1. A source file 'driver.c' in <project_root>/myOtherDriver/<source_root>
+2. A header file 'driver.h' in <project_root>/myOtherDriver/<source_root> (or <inc_root> if specified)
+3. A test file 'test_driver.c' in <project_root>/myOtherDriver/<test_root>
+
+Naming
+-------------------------------------------
+By default, the module_generator will generate your files in lowercase.
+`ceedling module:create[mydriver]` and `ceedling module:create[myDriver]`(note the uppercase) will generate the same files:
+1. mydriver.c
+2. mydriver.h
+3. test_mydriver.c
+
+You can configure the module_generator to use a differect naming mechanism through the project.yml:
+```yaml
+:module_generator:
+ :naming: "camel"
+```
+There are other possibilities as well (bumpy, camel, snake, caps).
+Refer to the unity module generator for more info (the unity module generator is used under the hood by module_generator).
+
+Advanced Topics (Coming)
+========================
+
+Modifying Your Configuration without Modifying Your Project File: Option Files & User Files
+-------------------------------------------------------------------------------------------
+
+Modifying your project file without modifying your project file
+
+Debugging and/or printf()
+-------------------------
+
+When you gotta get your hands dirty...
+
+Ceedling Plays Nice with Others - Using Ceedling for Tests Alongside Another Release Build Setup
+------------------------------------------------------------------------------------------------
+
+You've got options.
+
+Adding Handy Rake Tasks for Your Project (without Fancy Pants Custom Plugins)
+-----------------------------------------------------------------------------
+
+Simple as snot.
+
+Working with Non-Desktop Testing Environments
+---------------------------------------------
+
+For those crazy platforms lacking command line simulators and for which
+cross-compiling on the desktop just ain't gonna get it done.
+
+Creating Custom Plugins
+-----------------------
+
+Oh boy. This is going to take some explaining.
diff --git a/tinyusb/test/vendor/ceedling/docs/ThrowTheSwitchCodingStandard.md b/tinyusb/test/vendor/ceedling/docs/ThrowTheSwitchCodingStandard.md
new file mode 100755
index 00000000..bf4c099b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/ThrowTheSwitchCodingStandard.md
@@ -0,0 +1,206 @@
+# ThrowTheSwitch.org Coding Standard
+
+Hi. Welcome to the coding standard for ThrowTheSwitch.org. For the most part,
+we try to follow these standards to unify our contributors' code into a cohesive
+unit (puns intended). You might find places where these standards aren't
+followed. We're not perfect. Please be polite where you notice these discrepancies
+and we'll try to be polite when we notice yours.
+
+;)
+
+
+## Why Have A Coding Standard?
+
+Being consistent makes code easier to understand. We've tried to keep
+our standard simple because we also believe that we can only expect someone to
+follow something that is understandable. Please do your best.
+
+
+## Our Philosophy
+
+Before we get into details on syntax, let's take a moment to talk about our
+vision for these tools. We're C developers and embedded software developers.
+These tools are great to test any C code, but catering to embedded software has
+made us more tolerant of compiler quirks. There are a LOT of quirky compilers
+out there. By quirky I mean "doesn't follow standards because they feel like
+they have a license to do as they wish."
+
+Our philosophy is "support every compiler we can". Most often, this means that
+we aim for writing C code that is standards compliant (often C89... that seems
+to be a sweet spot that is almost always compatible). But it also means these
+tools are tolerant of things that aren't common. Some that aren't even
+compliant. There are configuration options to override the size of standard
+types. There are configuration options to force Unity to not use certain
+standard library functions. A lot of Unity is configurable and we have worked
+hard to make it not TOO ugly in the process.
+
+Similarly, our tools that parse C do their best. They aren't full C parsers
+(yet) and, even if they were, they would still have to accept non-standard
+additions like gcc extensions or specifying `@0x1000` to force a variable to
+compile to a particular location. It's just what we do, because we like
+everything to Just Work™.
+
+Speaking of having things Just Work™, that's our second philosophy. By that, we
+mean that we do our best to have EVERY configuration option have a logical
+default. We believe that if you're working with a simple compiler and target,
+you shouldn't need to configure very much... we try to make the tools guess as
+much as they can, but give the user the power to override it when it's wrong.
+
+
+## Naming Things
+
+Let's talk about naming things. Programming is all about naming things. We name
+files, functions, variables, and so much more. While we're not always going to
+find the best name for something, we actually put a bit of effort into
+finding *What Something WANTS to be Called*™.
+
+When naming things, we follow this hierarchy, the first being the
+most important to us (but we do all four when possible):
+1. Readable
+2. Descriptive
+3. Consistent
+4. Memorable
+
+
+#### Readable
+
+We want to read our code. This means we like names and flow that are more
+naturally read. We try to avoid double negatives. We try to avoid cryptic
+abbreviations (sticking to ones we feel are common).
+
+
+#### Descriptive
+
+We like descriptive names for things, especially functions and variables.
+Finding the right name for something is an important endeavor. You might notice
+from poking around our code that this often results in names that are a little
+longer than the average. Guilty. We're okay with a bit more typing if it
+means our code is easier to understand.
+
+There are two exceptions to this rule that we also stick to as religiously as
+possible:
+
+First, while we realize hungarian notation (and similar systems for encoding
+type information into variable names) is providing a more descriptive name, we
+feel that (for the average developer) it takes away from readability and is to be avoided.
+
+Second, loop counters and other local throw-away variables often have a purpose
+which is obvious. There's no need, therefore, to get carried away with complex
+naming. We find i, j, and k are better loop counters than loopCounterVar or
+whatnot. We only break this rule when we see that more description could improve
+understanding of an algorithm.
+
+
+#### Consistent
+
+We like consistency, but we're not really obsessed with it. We try to name our
+configuration macros in a consistent fashion... you'll notice a repeated use of
+UNITY_EXCLUDE_BLAH or UNITY_USES_BLAH macros. This helps users avoid having to
+remember each macro's details.
+
+
+#### Memorable
+
+Where ever it doesn't violate the above principles, we try to apply memorable
+names. Sometimes this means using something that is simply descriptive, but
+often we strive for descriptive AND unique... we like quirky names that stand
+out in our memory and are easier to search for. Take a look through the file
+names in Ceedling and you'll get a good idea of what we are talking about here.
+Why use preprocess when you can use preprocessinator? Or what better describes a
+module in charge of invoking tasks during releases than release_invoker? Don't
+get carried away. The names are still descriptive and fulfill the above
+requirements, but they don't feel stale.
+
+
+## C and C++ Details
+
+We don't really want to add to the style battles out there. Tabs or spaces?
+How many spaces? Where do the braces go? These are age-old questions that will
+never be answered... or at least not answered in a way that will make everyone
+happy.
+
+We've decided on our own style preferences. If you'd like to contribute to these
+projects (and we hope that you do), then we ask if you do your best to follow
+the same. It will only hurt a little. We promise.
+
+
+#### Whitespace
+
+Our C-style is to use spaces and to use 4 of them per indent level. It's a nice
+power-of-2 number that looks decent on a wide-screen. We have no more reason
+than that. We break that rule when we have lines that wrap (macros or function
+arguments or whatnot). When that happens, we like to indent further to line
+things up in nice tidy columns.
+
+```C
+ if (stuff_happened)
+ {
+ do_something();
+ }
+```
+
+
+#### Case
+
+- Files - all lower case with underscores.
+- Variables - all lower case with underscores
+- Macros - all caps with underscores.
+- Typedefs - all caps with underscores. (also ends with _T).
+- Functions - camel cased. Usually named ModuleName_FuncName
+- Constants and Globals - camel cased.
+
+
+#### Braces
+
+The left brace is on the next line after the declaration. The right brace is
+directly below that. Everything in between in indented one level. If you're
+catching an error and you have a one-line, go ahead and to it on the same line.
+
+```C
+ while (blah)
+ {
+ //Like so. Even if only one line, we use braces.
+ }
+```
+
+
+#### Comments
+
+Do you know what we hate? Old-school C block comments. BUT, we're using them
+anyway. As we mentioned, our goal is to support every compiler we can,
+especially embedded compilers. There are STILL C compilers out there that only
+support old-school block comments. So that is what we're using. We apologize. We
+think they are ugly too.
+
+
+## Ruby Details
+
+Is there really such thing as a Ruby coding standard? Ruby is such a free form
+language, it seems almost sacrilegious to suggest that people should comply to
+one method! We'll keep it really brief!
+
+
+#### Whitespace
+
+Our Ruby style is to use spaces and to use 2 of them per indent level. It's a
+nice power-of-2 number that really grooves with Ruby's compact style. We have no
+more reason than that. We break that rule when we have lines that wrap. When
+that happens, we like to indent further to line things up in nice tidy columns.
+
+
+#### Case
+
+- Files - all lower case with underscores.
+- Variables - all lower case with underscores
+- Classes, Modules, etc - Camel cased.
+- Functions - all lower case with underscores
+- Constants - all upper case with underscores
+
+
+## Documentation
+
+Egad. Really? We use mark down and we like pdf files because they can be made to
+look nice while still being portable. Good enough?
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/tinyusb/test/vendor/ceedling/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf
new file mode 100755
index 00000000..28f0c321
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf
Binary files differ
diff --git a/tinyusb/test/vendor/ceedling/docs/UnityAssertionsReference.md b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsReference.md
new file mode 100755
index 00000000..eb855f3c
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/UnityAssertionsReference.md
@@ -0,0 +1,779 @@
+# Unity Assertions Reference
+
+## Background and Overview
+
+### Super Condensed Version
+
+- An assertion establishes truth (i.e. boolean True) for a single condition.
+Upon boolean False, an assertion stops execution and reports the failure.
+- Unity is mainly a rich collection of assertions and the support to gather up
+and easily execute those assertions.
+- The structure of Unity allows you to easily separate test assertions from
+source code in, well, test code.
+- Unity's assertions:
+- Come in many, many flavors to handle different C types and assertion cases.
+- Use context to provide detailed and helpful failure messages.
+- Document types, expected values, and basic behavior in your source code for
+free.
+
+
+### Unity Is Several Things But Mainly It's Assertions
+
+One way to think of Unity is simply as a rich collection of assertions you can
+use to establish whether your source code behaves the way you think it does.
+Unity provides a framework to easily organize and execute those assertions in
+test code separate from your source code.
+
+
+### What's an Assertion?
+
+At their core, assertions are an establishment of truth - boolean truth. Was this
+thing equal to that thing? Does that code doohickey have such-and-such property
+or not? You get the idea. Assertions are executable code (to appreciate the big
+picture on this read up on the difference between
+[link:Dynamic Verification and Static Analysis]). A failing assertion stops
+execution and reports an error through some appropriate I/O channel (e.g.
+stdout, GUI, file, blinky light).
+
+Fundamentally, for dynamic verification all you need is a single assertion
+mechanism. In fact, that's what the [assert() macro in C's standard library](http://en.wikipedia.org/en/wiki/Assert.h)
+is for. So why not just use it? Well, we can do far better in the reporting
+department. C's `assert()` is pretty dumb as-is and is particularly poor for
+handling common data types like arrays, structs, etc. And, without some other
+support, it's far too tempting to litter source code with C's `assert()`'s. It's
+generally much cleaner, manageable, and more useful to separate test and source
+code in the way Unity facilitates.
+
+
+### Unity's Assertions: Helpful Messages _and_ Free Source Code Documentation
+
+Asserting a simple truth condition is valuable, but using the context of the
+assertion is even more valuable. For instance, if you know you're comparing bit
+flags and not just integers, then why not use that context to give explicit,
+readable, bit-level feedback when an assertion fails?
+
+That's what Unity's collection of assertions do - capture context to give you
+helpful, meaningful assertion failure messages. In fact, the assertions
+themselves also serve as executable documentation about types and values in your
+source code. So long as your tests remain current with your source and all those
+tests pass, you have a detailed, up-to-date view of the intent and mechanisms in
+your source code. And due to a wondrous mystery, well-tested code usually tends
+to be well designed code.
+
+
+## Assertion Conventions and Configurations
+
+### Naming and Parameter Conventions
+
+The convention of assertion parameters generally follows this order:
+
+ TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
+
+The very simplest assertion possible uses only a single "actual" parameter (e.g.
+a simple null check).
+
+"Actual" is the value being tested and unlike the other parameters in an
+assertion construction is the only parameter present in all assertion variants.
+"Modifiers" are masks, ranges, bit flag specifiers, floating point deltas.
+"Expected" is your expected value (duh) to compare to an "actual" value; it's
+marked as an optional parameter because some assertions only need a single
+"actual" parameter (e.g. null check).
+"Size/count" refers to string lengths, number of array elements, etc.
+
+Many of Unity's assertions are clear duplications in that the same data type
+is handled by several assertions. The differences among these are in how failure
+messages are presented. For instance, a `_HEX` variant of an assertion prints
+the expected and actual values of that assertion formatted as hexadecimal.
+
+
+#### TEST_ASSERT_X_MESSAGE Variants
+
+_All_ assertions are complemented with a variant that includes a simple string
+message as a final parameter. The string you specify is appended to an assertion
+failure message in Unity output.
+
+For brevity, the assertion variants with a message parameter are not listed
+below. Just tack on `_MESSAGE` as the final component to any assertion name in
+the reference list below and add a string as the final parameter.
+
+_Example:_
+
+ TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
+
+becomes messageified like thus...
+
+ TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
+
+Notes:
+- The `_MESSAGE` variants intentionally do not support `printf` style formatting
+ since many embedded projects don't support or avoid `printf` for various reasons.
+ It is possible to use `sprintf` before the assertion to assemble a complex fail
+ message, if necessary.
+- If you want to output a counter value within an assertion fail message (e.g. from
+ a loop) , building up an array of results and then using one of the `_ARRAY`
+ assertions (see below) might be a handy alternative to `sprintf`.
+
+
+#### TEST_ASSERT_X_ARRAY Variants
+
+Unity provides a collection of assertions for arrays containing a variety of
+types. These are documented in the Array section below. These are almost on par
+with the `_MESSAGE`variants of Unity's Asserts in that for pretty much any Unity
+type assertion you can tack on `_ARRAY` and run assertions on an entire block of
+memory.
+
+ TEST_ASSERT_EQUAL_TYPEX_ARRAY( expected, actual, {size/count} )
+
+"Expected" is an array itself.
+"Size/count" is one or two parameters necessary to establish the number of array
+elements and perhaps the length of elements within the array.
+
+Notes:
+- The `_MESSAGE` variant convention still applies here to array assertions. The
+`_MESSAGE` variants of the `_ARRAY` assertions have names ending with
+`_ARRAY_MESSAGE`.
+- Assertions for handling arrays of floating point values are grouped with float
+and double assertions (see immediately following section).
+
+
+### TEST_ASSERT_EACH_EQUAL_X Variants
+
+Unity provides a collection of assertions for arrays containing a variety of
+types which can be compared to a single value as well. These are documented in
+the Each Equal section below. these are almost on par with the `_MESSAGE`
+variants of Unity's Asserts in that for pretty much any Unity type assertion you
+can inject _EACH_EQUAL and run assertions on an entire block of memory.
+
+ TEST_ASSERT_EACH_EQUAL_TYPEX( expected, actual, {size/count} )
+
+"Expected" is a single value to compare to.
+"Actual" is an array where each element will be compared to the expected value.
+"Size/count" is one of two parameters necessary to establish the number of array
+elements and perhaps the length of elements within the array.
+
+Notes:
+- The `_MESSAGE` variant convention still applies here to Each Equal assertions.
+- Assertions for handling Each Equal of floating point values are grouped with
+float and double assertions (see immediately following section).
+
+
+### Configuration
+
+#### Floating Point Support Is Optional
+
+Support for floating point types is configurable. That is, by defining the
+appropriate preprocessor symbols, floats and doubles can be individually enabled
+or disabled in Unity code. This is useful for embedded targets with no floating
+point math support (i.e. Unity compiles free of errors for fixed point only
+platforms). See Unity documentation for specifics.
+
+
+#### Maximum Data Type Width Is Configurable
+
+Not all targets support 64 bit wide types or even 32 bit wide types. Define the
+appropriate preprocessor symbols and Unity will omit all operations from
+compilation that exceed the maximum width of your target. See Unity
+documentation for specifics.
+
+
+## The Assertions in All Their Blessed Glory
+
+### Basic Fail and Ignore
+
+##### `TEST_FAIL()`
+
+This fella is most often used in special conditions where your test code is
+performing logic beyond a simple assertion. That is, in practice, `TEST_FAIL()`
+will always be found inside a conditional code block.
+
+_Examples:_
+- Executing a state machine multiple times that increments a counter your test
+code then verifies as a final step.
+- Triggering an exception and verifying it (as in Try / Catch / Throw - see the
+[CException](https://github.com/ThrowTheSwitch/CException) project).
+
+##### `TEST_IGNORE()`
+
+Marks a test case (i.e. function meant to contain test assertions) as ignored.
+Usually this is employed as a breadcrumb to come back and implement a test case.
+An ignored test case has effects if other assertions are in the enclosing test
+case (see Unity documentation for more).
+
+### Boolean
+
+##### `TEST_ASSERT (condition)`
+
+##### `TEST_ASSERT_TRUE (condition)`
+
+##### `TEST_ASSERT_FALSE (condition)`
+
+##### `TEST_ASSERT_UNLESS (condition)`
+
+A simple wording variation on `TEST_ASSERT_FALSE`.The semantics of
+`TEST_ASSERT_UNLESS` aid readability in certain test constructions or
+conditional statements.
+
+##### `TEST_ASSERT_NULL (pointer)`
+
+##### `TEST_ASSERT_NOT_NULL (pointer)`
+
+
+### Signed and Unsigned Integers (of all sizes)
+
+Large integer sizes can be disabled for build targets that do not support them.
+For example, if your target only supports up to 16 bit types, by defining the
+appropriate symbols Unity can be configured to omit 32 and 64 bit operations
+that would break compilation (see Unity documentation for more). Refer to
+Advanced Asserting later in this document for advice on dealing with other word
+sizes.
+
+##### `TEST_ASSERT_EQUAL_INT (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT8 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT16 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT32 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_INT64 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL (expected, actual)`
+
+##### `TEST_ASSERT_NOT_EQUAL (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT8 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT16 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT32 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_UINT64 (expected, actual)`
+
+
+### Unsigned Integers (of all sizes) in Hexadecimal
+
+All `_HEX` assertions are identical in function to unsigned integer assertions
+but produce failure messages with the `expected` and `actual` values formatted
+in hexadecimal. Unity output is big endian.
+
+##### `TEST_ASSERT_EQUAL_HEX (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX8 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX16 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX32 (expected, actual)`
+
+##### `TEST_ASSERT_EQUAL_HEX64 (expected, actual)`
+
+
+### Masked and Bit-level Assertions
+
+Masked and bit-level assertions produce output formatted in hexadecimal. Unity
+output is big endian.
+
+
+##### `TEST_ASSERT_BITS (mask, expected, actual)`
+
+Only compares the masked (i.e. high) bits of `expected` and `actual` parameters.
+
+
+##### `TEST_ASSERT_BITS_HIGH (mask, actual)`
+
+Asserts the masked bits of the `actual` parameter are high.
+
+
+##### `TEST_ASSERT_BITS_LOW (mask, actual)`
+
+Asserts the masked bits of the `actual` parameter are low.
+
+
+##### `TEST_ASSERT_BIT_HIGH (bit, actual)`
+
+Asserts the specified bit of the `actual` parameter is high.
+
+
+##### `TEST_ASSERT_BIT_LOW (bit, actual)`
+
+Asserts the specified bit of the `actual` parameter is low.
+
+### Integer Less Than / Greater Than
+
+These assertions verify that the `actual` parameter is less than or greater
+than `threshold` (exclusive). For example, if the threshold value is 0 for the
+greater than assertion will fail if it is 0 or less.
+
+##### `TEST_ASSERT_GREATER_THAN (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT8 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT16 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_INT32 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT8 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT16 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_UINT32 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_HEX8 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_HEX16 (threshold, actual)`
+
+##### `TEST_ASSERT_GREATER_THAN_HEX32 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT8 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT16 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_INT32 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT8 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT16 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_UINT32 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_HEX8 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_HEX16 (threshold, actual)`
+
+##### `TEST_ASSERT_LESS_THAN_HEX32 (threshold, actual)`
+
+
+### Integer Ranges (of all sizes)
+
+These assertions verify that the `expected` parameter is within +/- `delta`
+(inclusive) of the `actual` parameter. For example, if the expected value is 10
+and the delta is 3 then the assertion will fail for any value outside the range
+of 7 - 13.
+
+##### `TEST_ASSERT_INT_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT8_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT16_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT32_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_INT64_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT8_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT16_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT32_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_UINT64_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX8_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX16_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX32_WITHIN (delta, expected, actual)`
+
+##### `TEST_ASSERT_HEX64_WITHIN (delta, expected, actual)`
+
+
+### Structs and Strings
+
+##### `TEST_ASSERT_EQUAL_PTR (expected, actual)`
+
+Asserts that the pointers point to the same memory location.
+
+
+##### `TEST_ASSERT_EQUAL_STRING (expected, actual)`
+
+Asserts that the null terminated (`'\0'`)strings are identical. If strings are
+of different lengths or any portion of the strings before their terminators
+differ, the assertion fails. Two NULL strings (i.e. zero length) are considered
+equivalent.
+
+
+##### `TEST_ASSERT_EQUAL_MEMORY (expected, actual, len)`
+
+Asserts that the contents of the memory specified by the `expected` and `actual`
+pointers is identical. The size of the memory blocks in bytes is specified by
+the `len` parameter.
+
+
+### Arrays
+
+`expected` and `actual` parameters are both arrays. `num_elements` specifies the
+number of elements in the arrays to compare.
+
+`_HEX` assertions produce failure messages with expected and actual array
+contents formatted in hexadecimal.
+
+For array of strings comparison behavior, see comments for
+`TEST_ASSERT_EQUAL_STRING` in the preceding section.
+
+Assertions fail upon the first element in the compared arrays found not to
+match. Failure messages specify the array index of the failed comparison.
+
+##### `TEST_ASSERT_EQUAL_INT_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT8_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT16_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT32_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_INT64_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT8_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT16_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT32_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_UINT64_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX8_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX16_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX32_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_HEX64_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_PTR_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_STRING_ARRAY (expected, actual, num_elements)`
+
+##### `TEST_ASSERT_EQUAL_MEMORY_ARRAY (expected, actual, len, num_elements)`
+
+`len` is the memory in bytes to be compared at each array element.
+
+
+### Each Equal (Arrays to Single Value)
+
+`expected` are single values and `actual` are arrays. `num_elements` specifies
+the number of elements in the arrays to compare.
+
+`_HEX` assertions produce failure messages with expected and actual array
+contents formatted in hexadecimal.
+
+Assertions fail upon the first element in the compared arrays found not to
+match. Failure messages specify the array index of the failed comparison.
+
+#### `TEST_ASSERT_EACH_EQUAL_INT (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT8 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT16 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT32 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_INT64 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT8 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT16 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT32 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_UINT64 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX8 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX16 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX32 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_HEX64 (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_PTR (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_STRING (expected, actual, num_elements)`
+
+#### `TEST_ASSERT_EACH_EQUAL_MEMORY (expected, actual, len, num_elements)`
+
+`len` is the memory in bytes to be compared at each array element.
+
+
+### Floating Point (If enabled)
+
+##### `TEST_ASSERT_FLOAT_WITHIN (delta, expected, actual)`
+
+Asserts that the `actual` value is within +/- `delta` of the `expected` value.
+The nature of floating point representation is such that exact evaluations of
+equality are not guaranteed.
+
+
+##### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)`
+
+Asserts that the ?actual?value is "close enough to be considered equal" to the
+`expected` value. If you are curious about the details, refer to the Advanced
+Asserting section for more details on this. Omitting a user-specified delta in a
+floating point assertion is both a shorthand convenience and a requirement of
+code generation conventions for CMock.
+
+
+##### `TEST_ASSERT_EQUAL_FLOAT_ARRAY (expected, actual, num_elements)`
+
+See Array assertion section for details. Note that individual array element
+float comparisons are executed using T?EST_ASSERT_EQUAL_FLOAT?.That is, user
+specified delta comparison values requires a custom-implemented floating point
+array assertion.
+
+
+##### `TEST_ASSERT_FLOAT_IS_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NEG_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to negative infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NAN (actual)`
+
+Asserts that `actual` parameter is a Not A Number floating point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_DETERMINATE (actual)`
+
+Asserts that ?actual?parameter is a floating point representation usable for
+mathematical operations. That is, the `actual` parameter is neither positive
+infinity nor negative infinity nor Not A Number floating point representations.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_INF (actual)`
+
+Asserts that `actual` parameter is a value other than positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_NEG_INF (actual)`
+
+Asserts that `actual` parameter is a value other than negative infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_NAN (actual)`
+
+Asserts that `actual` parameter is a value other than Not A Number floating
+point representation.
+
+
+##### `TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE (actual)`
+
+Asserts that `actual` parameter is not usable for mathematical operations. That
+is, the `actual` parameter is either positive infinity or negative infinity or
+Not A Number floating point representations.
+
+
+### Double (If enabled)
+
+##### `TEST_ASSERT_DOUBLE_WITHIN (delta, expected, actual)`
+
+Asserts that the `actual` value is within +/- `delta` of the `expected` value.
+The nature of floating point representation is such that exact evaluations of
+equality are not guaranteed.
+
+
+##### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)`
+
+Asserts that the `actual` value is "close enough to be considered equal" to the
+`expected` value. If you are curious about the details, refer to the Advanced
+Asserting section for more details. Omitting a user-specified delta in a
+floating point assertion is both a shorthand convenience and a requirement of
+code generation conventions for CMock.
+
+
+##### `TEST_ASSERT_EQUAL_DOUBLE_ARRAY (expected, actual, num_elements)`
+
+See Array assertion section for details. Note that individual array element
+double comparisons are executed using `TEST_ASSERT_EQUAL_DOUBLE`.That is, user
+specified delta comparison values requires a custom implemented double array
+assertion.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NEG_INF (actual)`
+
+Asserts that `actual` parameter is equivalent to negative infinity floating point
+representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NAN (actual)`
+
+Asserts that `actual` parameter is a Not A Number floating point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_DETERMINATE (actual)`
+
+Asserts that `actual` parameter is a floating point representation usable for
+mathematical operations. That is, the ?actual?parameter is neither positive
+infinity nor negative infinity nor Not A Number floating point representations.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_INF (actual)`
+
+Asserts that `actual` parameter is a value other than positive infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF (actual)`
+
+Asserts that `actual` parameter is a value other than negative infinity floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_NAN (actual)`
+
+Asserts that `actual` parameter is a value other than Not A Number floating
+point representation.
+
+
+##### `TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE (actual)`
+
+Asserts that `actual` parameter is not usable for mathematical operations. That
+is, the `actual` parameter is either positive infinity or negative infinity or
+Not A Number floating point representations.
+
+
+## Advanced Asserting: Details On Tricky Assertions
+
+This section helps you understand how to deal with some of the trickier
+assertion situations you may run into. It will give you a glimpse into some of
+the under-the-hood details of Unity's assertion mechanisms. If you're one of
+those people who likes to know what is going on in the background, read on. If
+not, feel free to ignore the rest of this document until you need it.
+
+
+### How do the EQUAL assertions work for FLOAT and DOUBLE?
+
+As you may know, directly checking for equality between a pair of floats or a
+pair of doubles is sloppy at best and an outright no-no at worst. Floating point
+values can often be represented in multiple ways, particularly after a series of
+operations on a value. Initializing a variable to the value of 2.0 is likely to
+result in a floating point representation of 2 x 20,but a series of
+mathematical operations might result in a representation of 8 x 2-2
+that also evaluates to a value of 2. At some point repeated operations cause
+equality checks to fail.
+
+So Unity doesn't do direct floating point comparisons for equality. Instead, it
+checks if two floating point values are "really close." If you leave Unity
+running with defaults, "really close" means "within a significant bit or two."
+Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN`
+with the `delta` parameter calculated on the fly. For single precision, delta is
+the expected value multiplied by 0.00001, producing a very small proportional
+range around the expected value.
+
+If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So
+any value between 19,999.8 and 20,000.2 will satisfy the equality check. This
+works out to be roughly a single bit of range for a single-precision number, and
+that's just about as tight a tolerance as you can reasonably get from a floating
+point value.
+
+So what happens when it's zero? Zero - even more than other floating point
+values - can be represented many different ways. It doesn't matter if you have
+0 x 20 or 0 x 263.It's still zero, right? Luckily, if you
+subtract these values from each other, they will always produce a difference of
+zero, which will still fall between 0 plus or minus a delta of 0. So it still
+works!
+
+Double precision floating point numbers use a much smaller multiplier, again
+approximating a single bit of error.
+
+If you don't like these ranges and you want to make your floating point equality
+assertions less strict, you can change these multipliers to whatever you like by
+defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity
+documentation for more.
+
+
+### How do we deal with targets with non-standard int sizes?
+
+It's "fun" that C is a standard where something as fundamental as an integer
+varies by target. According to the C standard, an `int` is to be the target's
+natural register size, and it should be at least 16-bits and a multiple of a
+byte. It also guarantees an order of sizes:
+
+```C
+char <= short <= int <= long <= long long
+```
+
+Most often, `int` is 32-bits. In many cases in the embedded world, `int` is
+16-bits. There are rare microcontrollers out there that have 24-bit integers,
+and this remains perfectly standard C.
+
+To make things even more interesting, there are compilers and targets out there
+that have a hard choice to make. What if their natural register size is 10-bits
+or 12-bits? Clearly they can't fulfill _both_ the requirement to be at least
+16-bits AND the requirement to match the natural register size. In these
+situations, they often choose the natural register size, leaving us with
+something like this:
+
+```C
+char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit)
+```
+
+Um... yikes. It's obviously breaking a rule or two... but they had to break SOME
+rules, so they made a choice.
+
+When the C99 standard rolled around, it introduced alternate standard-size types.
+It also introduced macros for pulling in MIN/MAX values for your integer types.
+It's glorious! Unfortunately, many embedded compilers can't be relied upon to
+use the C99 types (Sometimes because they have weird register sizes as described
+above. Sometimes because they don't feel like it?).
+
+A goal of Unity from the beginning was to support every combination of
+microcontroller or microprocessor and C compiler. Over time, we've gotten really
+close to this. There are a few tricks that you should be aware of, though, if
+you're going to do this effectively on some of these more idiosyncratic targets.
+
+First, when setting up Unity for a new target, you're going to want to pay
+special attention to the macros for automatically detecting types
+(where available) or manually configuring them yourself. You can get information
+on both of these in Unity's documentation.
+
+What about the times where you suddenly need to deal with something odd, like a
+24-bit `int`? The simplest solution is to use the next size up. If you have a
+24-bit `int`, configure Unity to use 32-bit integers. If you have a 12-bit
+`int`, configure Unity to use 16 bits. There are two ways this is going to
+affect you:
+
+1. When Unity displays errors for you, it's going to pad the upper unused bits
+with zeros.
+2. You're going to have to be careful of assertions that perform signed
+operations, particularly `TEST_ASSERT_INT_WITHIN`.Such assertions might wrap
+your `int` in the wrong place, and you could experience false failures. You can
+always back down to a simple `TEST_ASSERT` and do the operations yourself.
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/tinyusb/test/vendor/ceedling/docs/UnityConfigurationGuide.md b/tinyusb/test/vendor/ceedling/docs/UnityConfigurationGuide.md
new file mode 100755
index 00000000..dace20c5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/UnityConfigurationGuide.md
@@ -0,0 +1,433 @@
+# Unity Configuration Guide
+
+## C Standards, Compilers and Microcontrollers
+
+The embedded software world contains its challenges. Compilers support different
+revisions of the C Standard. They ignore requirements in places, sometimes to
+make the language more usable in some special regard. Sometimes it's to simplify
+their support. Sometimes it's due to specific quirks of the microcontroller they
+are targeting. Simulators add another dimension to this menagerie.
+
+Unity is designed to run on almost anything that is targeted by a C compiler. It
+would be awesome if this could be done with zero configuration. While there are
+some targets that come close to this dream, it is sadly not universal. It is
+likely that you are going to need at least a couple of the configuration options
+described in this document.
+
+All of Unity's configuration options are `#defines`. Most of these are simple
+definitions. A couple are macros with arguments. They live inside the
+unity_internals.h header file. We don't necessarily recommend opening that file
+unless you really need to. That file is proof that a cross-platform library is
+challenging to build. From a more positive perspective, it is also proof that a
+great deal of complexity can be centralized primarily to one place to
+provide a more consistent and simple experience elsewhere.
+
+
+### Using These Options
+
+It doesn't matter if you're using a target-specific compiler and a simulator or
+a native compiler. In either case, you've got a couple choices for configuring
+these options:
+
+1. Because these options are specified via C defines, you can pass most of these
+options to your compiler through command line compiler flags. Even if you're
+using an embedded target that forces you to use their overbearing IDE for all
+configuration, there will be a place somewhere in your project to configure
+defines for your compiler.
+2. You can create a custom `unity_config.h` configuration file (present in your
+toolchain's search paths). In this file, you will list definitions and macros
+specific to your target. All you must do is define `UNITY_INCLUDE_CONFIG_H` and
+Unity will rely on `unity_config.h` for any further definitions it may need.
+
+
+## The Options
+
+### Integer Types
+
+If you've been a C developer for long, you probably already know that C's
+concept of an integer varies from target to target. The C Standard has rules
+about the `int` matching the register size of the target microprocessor. It has
+rules about the `int` and how its size relates to other integer types. An `int`
+on one target might be 16 bits while on another target it might be 64. There are
+more specific types in compilers compliant with C99 or later, but that's
+certainly not every compiler you are likely to encounter. Therefore, Unity has a
+number of features for helping to adjust itself to match your required integer
+sizes. It starts off by trying to do it automatically.
+
+
+##### `UNITY_EXCLUDE_STDINT_H`
+
+The first thing that Unity does to guess your types is check `stdint.h`.
+This file includes defines like `UINT_MAX` that Unity can use to
+learn a lot about your system. It's possible you don't want it to do this
+(um. why not?) or (more likely) it's possible that your system doesn't
+support `stdint.h`. If that's the case, you're going to want to define this.
+That way, Unity will know to skip the inclusion of this file and you won't
+be left with a compiler error.
+
+_Example:_
+ #define UNITY_EXCLUDE_STDINT_H
+
+
+##### `UNITY_EXCLUDE_LIMITS_H`
+
+The second attempt to guess your types is to check `limits.h`. Some compilers
+that don't support `stdint.h` could include `limits.h` instead. If you don't
+want Unity to check this file either, define this to make it skip the inclusion.
+
+_Example:_
+ #define UNITY_EXCLUDE_LIMITS_H
+
+
+If you've disabled both of the automatic options above, you're going to have to
+do the configuration yourself. Don't worry. Even this isn't too bad... there are
+just a handful of defines that you are going to specify if you don't like the
+defaults.
+
+
+##### `UNITY_INT_WIDTH`
+
+Define this to be the number of bits an `int` takes up on your system. The
+default, if not autodetected, is 32 bits.
+
+_Example:_
+ #define UNITY_INT_WIDTH 16
+
+
+##### `UNITY_LONG_WIDTH`
+
+Define this to be the number of bits a `long` takes up on your system. The
+default, if not autodetected, is 32 bits. This is used to figure out what kind
+of 64-bit support your system can handle. Does it need to specify a `long` or a
+`long long` to get a 64-bit value. On 16-bit systems, this option is going to be
+ignored.
+
+_Example:_
+ #define UNITY_LONG_WIDTH 16
+
+
+##### `UNITY_POINTER_WIDTH`
+
+Define this to be the number of bits a pointer takes up on your system. The
+default, if not autodetected, is 32-bits. If you're getting ugly compiler
+warnings about casting from pointers, this is the one to look at.
+
+_Example:_
+ #define UNITY_POINTER_WIDTH 64
+
+
+##### `UNITY_SUPPORT_64`
+
+Unity will automatically include 64-bit support if it auto-detects it, or if
+your `int`, `long`, or pointer widths are greater than 32-bits. Define this to
+enable 64-bit support if none of the other options already did it for you. There
+can be a significant size and speed impact to enabling 64-bit support on small
+targets, so don't define it if you don't need it.
+
+_Example:_
+ #define UNITY_SUPPORT_64
+
+
+### Floating Point Types
+
+In the embedded world, it's not uncommon for targets to have no support for
+floating point operations at all or to have support that is limited to only
+single precision. We are able to guess integer sizes on the fly because integers
+are always available in at least one size. Floating point, on the other hand, is
+sometimes not available at all. Trying to include `float.h` on these platforms
+would result in an error. This leaves manual configuration as the only option.
+
+
+##### `UNITY_INCLUDE_FLOAT`
+
+##### `UNITY_EXCLUDE_FLOAT`
+
+##### `UNITY_INCLUDE_DOUBLE`
+
+##### `UNITY_EXCLUDE_DOUBLE`
+
+By default, Unity guesses that you will want single precision floating point
+support, but not double precision. It's easy to change either of these using the
+include and exclude options here. You may include neither, either, or both, as
+suits your needs. For features that are enabled, the following floating point
+options also become available.
+
+_Example:_
+
+ //what manner of strange processor is this?
+ #define UNITY_EXCLUDE_FLOAT
+ #define UNITY_INCLUDE_DOUBLE
+
+
+##### `UNITY_EXCLUDE_FLOAT_PRINT`
+
+Unity aims for as small of a footprint as possible and avoids most standard
+library calls (some embedded platforms don’t have a standard library!). Because
+of this, its routines for printing integer values are minimalist and hand-coded.
+Therefore, the display of floating point values during a failure are optional.
+By default, Unity will print the actual results of floating point assertion
+failure (e.g. ”Expected 4.56 Was 4.68”). To not include this extra support, you
+can use this define to instead respond to a failed assertion with a message like
+”Values Not Within Delta”. If you would like verbose failure messages for floating
+point assertions, use these options to give more explicit failure messages.
+
+_Example:_
+ #define UNITY_EXCLUDE_FLOAT_PRINT
+
+
+##### `UNITY_FLOAT_TYPE`
+
+If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C
+floats. If your compiler supports a specialty floating point type, you can
+always override this behavior by using this definition.
+
+_Example:_
+ #define UNITY_FLOAT_TYPE float16_t
+
+
+##### `UNITY_DOUBLE_TYPE`
+
+If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard C
+doubles. If you would like to change this, you can specify something else by
+using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long double`
+could enable gargantuan floating point types on your 64-bit processor instead of
+the standard `double`.
+
+_Example:_
+ #define UNITY_DOUBLE_TYPE long double
+
+
+##### `UNITY_FLOAT_PRECISION`
+
+##### `UNITY_DOUBLE_PRECISION`
+
+If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as
+documented in the big daddy Unity Assertion Guide, you will learn that they are
+not really asserting that two values are equal but rather that two values are
+"close enough" to equal. "Close enough" is controlled by these precision
+configuration options. If you are working with 32-bit floats and/or 64-bit
+doubles (the normal on most processors), you should have no need to change these
+options. They are both set to give you approximately 1 significant bit in either
+direction. The float precision is 0.00001 while the double is 10-12.
+For further details on how this works, see the appendix of the Unity Assertion
+Guide.
+
+_Example:_
+ #define UNITY_FLOAT_PRECISION 0.001f
+
+
+### Toolset Customization
+
+In addition to the options listed above, there are a number of other options
+which will come in handy to customize Unity's behavior for your specific
+toolchain. It is possible that you may not need to touch any of these... but
+certain platforms, particularly those running in simulators, may need to jump
+through extra hoops to run properly. These macros will help in those
+situations.
+
+
+##### `UNITY_OUTPUT_CHAR(a)`
+
+##### `UNITY_OUTPUT_FLUSH()`
+
+##### `UNITY_OUTPUT_START()`
+
+##### `UNITY_OUTPUT_COMPLETE()`
+
+By default, Unity prints its results to `stdout` as it runs. This works
+perfectly fine in most situations where you are using a native compiler for
+testing. It works on some simulators as well so long as they have `stdout`
+routed back to the command line. There are times, however, where the simulator
+will lack support for dumping results or you will want to route results
+elsewhere for other reasons. In these cases, you should define the
+`UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time (as
+an `int`, since this is the parameter type of the standard C `putchar` function
+most commonly used). You may replace this with whatever function call you like.
+
+_Example:_
+Say you are forced to run your test suite on an embedded processor with no
+`stdout` option. You decide to route your test result output to a custom serial
+`RS232_putc()` function you wrote like thus:
+ #include "RS232_header.h"
+ ...
+ #define UNITY_OUTPUT_CHAR(a) RS232_putc(a)
+ #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0)
+ #define UNITY_OUTPUT_FLUSH() RS232_flush()
+ #define UNITY_OUTPUT_COMPLETE() RS232_close()
+
+_Note:_
+`UNITY_OUTPUT_FLUSH()` can be set to the standard out flush function simply by
+specifying `UNITY_USE_FLUSH_STDOUT`. No other defines are required.
+
+
+##### `UNITY_WEAK_ATTRIBUTE`
+
+##### `UNITY_WEAK_PRAGMA`
+
+##### `UNITY_NO_WEAK`
+
+For some targets, Unity can make the otherwise required setUp() and tearDown()
+functions optional. This is a nice convenience for test writers since setUp and
+tearDown don’t often actually do anything. If you’re using gcc or clang, this
+option is automatically defined for you. Other compilers can also support this
+behavior, if they support a C feature called weak functions. A weak function is
+a function that is compiled into your executable unless a non-weak version of
+the same function is defined elsewhere. If a non-weak version is found, the weak
+version is ignored as if it never existed. If your compiler supports this feature,
+you can let Unity know by defining UNITY_WEAK_ATTRIBUTE or UNITY_WEAK_PRAGMA as
+the function attributes that would need to be applied to identify a function as
+weak. If your compiler lacks support for weak functions, you will always need to
+define setUp and tearDown functions (though they can be and often will be just
+empty). You can also force Unity to NOT use weak functions by defining
+UNITY_NO_WEAK. The most common options for this feature are:
+
+_Example:_
+ #define UNITY_WEAK_ATTRIBUTE weak
+ #define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
+ #define UNITY_WEAK_PRAGMA
+ #define UNITY_NO_WEAK
+
+
+##### `UNITY_PTR_ATTRIBUTE`
+
+Some compilers require a custom attribute to be assigned to pointers, like
+`near` or `far`. In these cases, you can give Unity a safe default for these by
+defining this option with the attribute you would like.
+
+_Example:_
+ #define UNITY_PTR_ATTRIBUTE __attribute__((far))
+ #define UNITY_PTR_ATTRIBUTE near
+
+
+##### `UNITY_PRINT_EOL`
+
+By default, Unity outputs \n at the end of each line of output. This is easy
+to parse by the scripts, by Ceedling, etc, but it might not be ideal for YOUR
+system. Feel free to override this and to make it whatever you wish.
+
+_Example:_
+ #define UNITY_PRINT_EOL { UNITY_OUTPUT_CHAR('\r'); UNITY_OUTPUT_CHAR('\n') }
+
+
+
+##### `UNITY_EXCLUDE_DETAILS`
+
+This is an option for if you absolutely must squeeze every byte of memory out of
+your system. Unity stores a set of internal scratchpads which are used to pass
+extra detail information around. It's used by systems like CMock in order to
+report which function or argument flagged an error. If you're not using CMock and
+you're not using these details for other things, then you can exclude them.
+
+_Example:_
+ #define UNITY_EXCLUDE_DETAILS
+
+
+
+##### `UNITY_EXCLUDE_SETJMP`
+
+If your embedded system doesn't support the standard library setjmp, you can
+exclude Unity's reliance on this by using this define. This dropped dependence
+comes at a price, though. You will be unable to use custom helper functions for
+your tests, and you will be unable to use tools like CMock. Very likely, if your
+compiler doesn't support setjmp, you wouldn't have had the memory space for those
+things anyway, though... so this option exists for those situations.
+
+_Example:_
+ #define UNITY_EXCLUDE_SETJMP
+
+##### `UNITY_OUTPUT_COLOR`
+
+If you want to add color using ANSI escape codes you can use this define.
+t
+_Example:_
+ #define UNITY_OUTPUT_COLOR
+
+
+
+## Getting Into The Guts
+
+There will be cases where the options above aren't quite going to get everything
+perfect. They are likely sufficient for any situation where you are compiling
+and executing your tests with a native toolchain (e.g. clang on Mac). These
+options may even get you through the majority of cases encountered in working
+with a target simulator run from your local command line. But especially if you
+must run your test suite on your target hardware, your Unity configuration will
+require special help. This special help will usually reside in one of two
+places: the `main()` function or the `RUN_TEST` macro. Let's look at how these
+work.
+
+
+##### `main()`
+
+Each test module is compiled and run on its own, separate from the other test
+files in your project. Each test file, therefore, has a `main` function. This
+`main` function will need to contain whatever code is necessary to initialize
+your system to a workable state. This is particularly true for situations where
+you must set up a memory map or initialize a communication channel for the
+output of your test results.
+
+A simple main function looks something like this:
+
+ int main(void) {
+ UNITY_BEGIN();
+ RUN_TEST(test_TheFirst);
+ RUN_TEST(test_TheSecond);
+ RUN_TEST(test_TheThird);
+ return UNITY_END();
+ }
+
+You can see that our main function doesn't bother taking any arguments. For our
+most barebones case, we'll never have arguments because we just run all the
+tests each time. Instead, we start by calling `UNITY_BEGIN`. We run each test
+(in whatever order we wish). Finally, we call `UNITY_END`, returning its return
+value (which is the total number of failures).
+
+It should be easy to see that you can add code before any test cases are run or
+after all the test cases have completed. This allows you to do any needed
+system-wide setup or teardown that might be required for your special
+circumstances.
+
+
+##### `RUN_TEST`
+
+The `RUN_TEST` macro is called with each test case function. Its job is to
+perform whatever setup and teardown is necessary for executing a single test
+case function. This includes catching failures, calling the test module's
+`setUp()` and `tearDown()` functions, and calling `UnityConcludeTest()`. If
+using CMock or test coverage, there will be additional stubs in use here. A
+simple minimalist RUN_TEST macro looks something like this:
+
+ #define RUN_TEST(testfunc) \
+ UNITY_NEW_TEST(#testfunc) \
+ if (TEST_PROTECT()) { \
+ setUp(); \
+ testfunc(); \
+ } \
+ if (TEST_PROTECT() && (!TEST_IS_IGNORED)) \
+ tearDown(); \
+ UnityConcludeTest();
+
+So that's quite a macro, huh? It gives you a glimpse of what kind of stuff Unity
+has to deal with for every single test case. For each test case, we declare that
+it is a new test. Then we run `setUp` and our test function. These are run
+within a `TEST_PROTECT` block, the function of which is to handle failures that
+occur during the test. Then, assuming our test is still running and hasn't been
+ignored, we run `tearDown`. No matter what, our last step is to conclude this
+test before moving on to the next.
+
+Let's say you need to add a call to `fsync` to force all of your output data to
+flush to a file after each test. You could easily insert this after your
+`UnityConcludeTest` call. Maybe you want to write an xml tag before and after
+each result set. Again, you could do this by adding lines to this macro. Updates
+to this macro are for the occasions when you need an action before or after
+every single test case throughout your entire suite of tests.
+
+
+## Happy Porting
+
+The defines and macros in this guide should help you port Unity to just about
+any C target we can imagine. If you run into a snag or two, don't be afraid of
+asking for help on the forums. We love a good challenge!
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/tinyusb/test/vendor/ceedling/docs/UnityGettingStartedGuide.md b/tinyusb/test/vendor/ceedling/docs/UnityGettingStartedGuide.md
new file mode 100755
index 00000000..5e4427ce
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/UnityGettingStartedGuide.md
@@ -0,0 +1,192 @@
+# Unity - Getting Started
+
+## Welcome
+
+Congratulations. You're now the proud owner of your very own pile of bits! What
+are you going to do with all these ones and zeros? This document should be able
+to help you decide just that.
+
+Unity is a unit test framework. The goal has been to keep it small and
+functional. The core Unity test framework is three files: a single C file and a
+couple header files. These team up to provide functions and macros to make
+testing easier.
+
+Unity was designed to be cross-platform. It works hard to stick with C standards
+while still providing support for the many embedded C compilers that bend the
+rules. Unity has been used with many compilers, including GCC, IAR, Clang,
+Green Hills, Microchip, and MS Visual Studio. It's not much work to get it to
+work with a new target.
+
+
+### Overview of the Documents
+
+#### Unity Assertions reference
+
+This document will guide you through all the assertion options provided by
+Unity. This is going to be your unit testing bread and butter. You'll spend more
+time with assertions than any other part of Unity.
+
+
+#### Unity Assertions Cheat Sheet
+
+This document contains an abridged summary of the assertions described in the
+previous document. It's perfect for printing and referencing while you
+familiarize yourself with Unity's options.
+
+
+#### Unity Configuration Guide
+
+This document is the one to reference when you are going to use Unity with a new
+target or compiler. It'll guide you through the configuration options and will
+help you customize your testing experience to meet your needs.
+
+
+#### Unity Helper Scripts
+
+This document describes the helper scripts that are available for simplifying
+your testing workflow. It describes the collection of optional Ruby scripts
+included in the auto directory of your Unity installation. Neither Ruby nor
+these scripts are necessary for using Unity. They are provided as a convenience
+for those who wish to use them.
+
+
+#### Unity License
+
+What's an open source project without a license file? This brief document
+describes the terms you're agreeing to when you use this software. Basically, we
+want it to be useful to you in whatever context you want to use it, but please
+don't blame us if you run into problems.
+
+
+### Overview of the Folders
+
+If you have obtained Unity through Github or something similar, you might be
+surprised by just how much stuff you suddenly have staring you in the face.
+Don't worry, Unity itself is very small. The rest of it is just there to make
+your life easier. You can ignore it or use it at your convenience. Here's an
+overview of everything in the project.
+
+- `src` - This is the code you care about! This folder contains a C file and two
+header files. These three files _are_ Unity.
+- `docs` - You're reading this document, so it's possible you have found your way
+into this folder already. This is where all the handy documentation can be
+found.
+- `examples` - This contains a few examples of using Unity.
+- `extras` - These are optional add ons to Unity that are not part of the core
+project. If you've reached us through James Grenning's book, you're going to
+want to look here.
+- `test` - This is how Unity and its scripts are all tested. If you're just using
+Unity, you'll likely never need to go in here. If you are the lucky team member
+who gets to port Unity to a new toolchain, this is a good place to verify
+everything is configured properly.
+- `auto` - Here you will find helpful Ruby scripts for simplifying your test
+workflow. They are purely optional and are not required to make use of Unity.
+
+
+## How to Create A Test File
+
+Test files are C files. Most often you will create a single test file for each C
+module that you want to test. The test file should include unity.h and the
+header for your C module to be tested.
+
+Next, a test file will include a `setUp()` and `tearDown()` function. The setUp
+function can contain anything you would like to run before each test. The
+tearDown function can contain anything you would like to run after each test.
+Both functions accept no arguments and return nothing. You may leave either or
+both of these blank if you have no need for them. If you're using a compiler
+that is configured to make these functions optional, you may leave them off
+completely. Not sure? Give it a try. If you compiler complains that it can't
+find setUp or tearDown when it links, you'll know you need to at least include
+an empty function for these.
+
+The majority of the file will be a series of test functions. Test functions
+follow the convention of starting with the word "test_" or "spec_". You don't HAVE
+to name them this way, but it makes it clear what functions are tests for other
+developers. Also, the automated scripts that come with Unity or Ceedling will default
+to looking for test functions to be prefixed this way. Test functions take no arguments
+and return nothing. All test accounting is handled internally in Unity.
+
+Finally, at the bottom of your test file, you will write a `main()` function.
+This function will call `UNITY_BEGIN()`, then `RUN_TEST` for each test, and
+finally `UNITY_END()`.This is what will actually trigger each of those test
+functions to run, so it is important that each function gets its own `RUN_TEST`
+call.
+
+Remembering to add each test to the main function can get to be tedious. If you
+enjoy using helper scripts in your build process, you might consider making use
+of our handy generate_test_runner.rb script. This will create the main function
+and all the calls for you, assuming that you have followed the suggested naming
+conventions. In this case, there is no need for you to include the main function
+in your test file at all.
+
+When you're done, your test file will look something like this:
+
+```C
+#include "unity.h"
+#include "file_to_test.h"
+
+void setUp(void) {
+ // set stuff up here
+}
+
+void tearDown(void) {
+ // clean stuff up here
+}
+
+void test_function_should_doBlahAndBlah(void) {
+ //test stuff
+}
+
+void test_function_should_doAlsoDoBlah(void) {
+ //more test stuff
+}
+
+int main(void) {
+ UNITY_BEGIN();
+ RUN_TEST(test_function_should_doBlahAndBlah);
+ RUN_TEST(test_function_should_doAlsoDoBlah);
+ return UNITY_END();
+}
+```
+
+It's possible that you will need more customization than this, eventually.
+For that sort of thing, you're going to want to look at the configuration guide.
+This should be enough to get you going, though.
+
+
+## How to Build and Run A Test File
+
+This is the single biggest challenge to picking up a new unit testing framework,
+at least in a language like C or C++. These languages are REALLY good at getting
+you "close to the metal" (why is the phrase metal? Wouldn't it be more accurate
+to say "close to the silicon"?). While this feature is usually a good thing, it
+can make testing more challenging.
+
+You have two really good options for toolchains. Depending on where you're
+coming from, it might surprise you that neither of these options is running the
+unit tests on your hardware.
+There are many reasons for this, but here's a short version:
+- On hardware, you have too many constraints (processing power, memory, etc),
+- On hardware, you don't have complete control over all registers,
+- On hardware, unit testing is more challenging,
+- Unit testing isn't System testing. Keep them separate.
+
+Instead of running your tests on your actual hardware, most developers choose to
+develop them as native applications (using gcc or MSVC for example) or as
+applications running on a simulator. Either is a good option. Native apps have
+the advantages of being faster and easier to set up. Simulator apps have the
+advantage of working with the same compiler as your target application. The
+options for configuring these are discussed in the configuration guide.
+
+To get either to work, you might need to make a few changes to the file
+containing your register set (discussed later).
+
+In either case, a test is built by linking unity, the test file, and the C
+file(s) being tested. These files create an executable which can be run as the
+test set for that module. Then, this process is repeated for the next test file.
+This flexibility of separating tests into individual executables allows us to
+much more thoroughly unit test our system and it keeps all the test code out of
+our final release!
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/tinyusb/test/vendor/ceedling/docs/UnityHelperScriptsGuide.md b/tinyusb/test/vendor/ceedling/docs/UnityHelperScriptsGuide.md
new file mode 100755
index 00000000..12d68d30
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/docs/UnityHelperScriptsGuide.md
@@ -0,0 +1,260 @@
+# Unity Helper Scripts
+
+## With a Little Help From Our Friends
+
+Sometimes what it takes to be a really efficient C programmer is a little non-C.
+The Unity project includes a couple of Ruby scripts for making your life just a tad
+easier. They are completely optional. If you choose to use them, you'll need a
+copy of Ruby, of course. Just install whatever the latest version is, and it is
+likely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/).
+
+
+### `generate_test_runner.rb`
+
+Are you tired of creating your own `main` function in your test file? Do you
+keep forgetting to add a `RUN_TEST` call when you add a new test case to your
+suite? Do you want to use CMock or other fancy add-ons but don't want to figure
+out how to create your own `RUN_TEST` macro?
+
+Well then we have the perfect script for you!
+
+The `generate_test_runner` script processes a given test file and automatically
+creates a separate test runner file that includes ?main?to execute the test
+cases within the scanned test file. All you do then is add the generated runner
+to your list of files to be compiled and linked, and presto you're done!
+
+This script searches your test file for void function signatures having a
+function name beginning with "test" or "spec". It treats each of these
+functions as a test case and builds up a test suite of them. For example, the
+following includes three test cases:
+
+```C
+void testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void)
+{
+ ASSERT_TRUE(1);
+}
+void test_FunctionName_should_WorkProperlyAndReturn8(void) {
+ ASSERT_EQUAL_INT(8, FunctionName());
+}
+void spec_Function_should_DoWhatItIsSupposedToDo(void) {
+ ASSERT_NOT_NULL(Function(5));
+}
+```
+
+You can run this script a couple of ways. The first is from the command line:
+
+```Shell
+ruby generate_test_runner.rb TestFile.c NameOfRunner.c
+```
+
+Alternatively, if you include only the test file parameter, the script will copy
+the name of the test file and automatically append "_Runner" to the name of the
+generated file. The example immediately below will create TestFile_Runner.c.
+
+```Shell
+ruby generate_test_runner.rb TestFile.c
+```
+
+You can also add a [YAML](http://www.yaml.org/) file to configure extra options.
+Conveniently, this YAML file is of the same format as that used by Unity and
+CMock. So if you are using YAML files already, you can simply pass the very same
+file into the generator script.
+
+```Shell
+ruby generate_test_runner.rb TestFile.c my_config.yml
+```
+
+The contents of the YAML file `my_config.yml` could look something like the
+example below. If you're wondering what some of these options do, you're going
+to love the next section of this document.
+
+```YAML
+:unity:
+ :includes:
+ - stdio.h
+ - microdefs.h
+ :cexception: 1
+ :suit_setup: "blah = malloc(1024);"
+ :suite_teardown: "free(blah);"
+```
+
+If you would like to force your generated test runner to include one or more
+header files, you can just include those at the command line too. Just make sure
+these are _after_ the YAML file, if you are using one:
+
+```Shell
+ruby generate_test_runner.rb TestFile.c my_config.yml extras.h
+```
+
+Another option, particularly if you are already using Ruby to orchestrate your
+builds - or more likely the Ruby-based build tool Rake - is requiring this
+script directly. Anything that you would have specified in a YAML file can be
+passed to the script as part of a hash. Let's push the exact same requirement
+set as we did above but this time through Ruby code directly:
+
+```Ruby
+require "generate_test_runner.rb"
+options = {
+ :includes => ["stdio.h", "microdefs.h"],
+ :cexception => 1,
+ :suite_setup => "blah = malloc(1024);",
+ :suite_teardown => "free(blah);"
+}
+UnityTestRunnerGenerator.new.run(testfile, runner_name, options)
+```
+
+If you have multiple files to generate in a build script (such as a Rakefile),
+you might want to instantiate a generator object with your options and call it
+to generate each runner afterwards. Like thus:
+
+```Ruby
+gen = UnityTestRunnerGenerator.new(options)
+test_files.each do |f|
+ gen.run(f, File.basename(f,'.c')+"Runner.c"
+end
+```
+
+#### Options accepted by generate_test_runner.rb:
+
+The following options are available when executing `generate_test_runner`. You
+may pass these as a Ruby hash directly or specify them in a YAML file, both of
+which are described above. In the `examples` directory, Example 3's Rakefile
+demonstrates using a Ruby hash.
+
+
+##### `:includes`
+
+This option specifies an array of file names to be `#include`'d at the top of
+your runner C file. You might use it to reference custom types or anything else
+universally needed in your generated runners.
+
+
+##### `:suite_setup`
+
+Define this option with C code to be executed _before any_ test cases are run.
+
+Alternatively, if your C compiler supports weak symbols, you can leave this
+option unset and instead provide a `void suiteSetUp(void)` function in your test
+suite. The linker will look for this symbol and fall back to a Unity-provided
+stub if it is not found.
+
+
+##### `:suite_teardown`
+
+Define this option with C code to be executed _after all_ test cases have
+finished. An integer variable `num_failures` is available for diagnostics.
+The code should end with a `return` statement; the value returned will become
+the exit code of `main`. You can normally just return `num_failures`.
+
+Alternatively, if your C compiler supports weak symbols, you can leave this
+option unset and instead provide a `int suiteTearDown(int num_failures)`
+function in your test suite. The linker will look for this symbol and fall
+back to a Unity-provided stub if it is not found.
+
+
+##### `:enforce_strict_ordering`
+
+This option should be defined if you have the strict order feature enabled in
+CMock (see CMock documentation). This generates extra variables required for
+everything to run smoothly. If you provide the same YAML to the generator as
+used in CMock's configuration, you've already configured the generator properly.
+
+##### `:mock_prefix` and `:mock_suffix`
+
+Unity automatically generates calls to Init, Verify and Destroy for every file
+included in the main test file that starts with the given mock prefix and ends
+with the given mock suffix, file extension not included. By default, Unity
+assumes a `Mock` prefix and no suffix.
+
+##### `:plugins`
+
+This option specifies an array of plugins to be used (of course, the array can
+contain only a single plugin). This is your opportunity to enable support for
+CException support, which will add a check for unhandled exceptions in each
+test, reporting a failure if one is detected. To enable this feature using Ruby:
+
+```Ruby
+:plugins => [ :cexception ]
+```
+
+Or as a yaml file:
+
+```YAML
+:plugins:
+ -:cexception
+```
+
+If you are using CMock, it is very likely that you are already passing an array
+of plugins to CMock. You can just use the same array here. This script will just
+ignore the plugins that don't require additional support.
+
+
+### `unity_test_summary.rb`
+
+A Unity test file contains one or more test case functions. Each test case can
+pass, fail, or be ignored. Each test file is run individually producing results
+for its collection of test cases. A given project will almost certainly be
+composed of multiple test files. Therefore, the suite of tests is comprised of
+one or more test cases spread across one or more test files. This script
+aggregates individual test file results to generate a summary of all executed
+test cases. The output includes how many tests were run, how many were ignored,
+and how many failed. In addition, the output includes a listing of which
+specific tests were ignored and failed. A good example of the breadth and
+details of these results can be found in the `examples` directory. Intentionally
+ignored and failing tests in this project generate corresponding entries in the
+summary report.
+
+If you're interested in other (prettier?) output formats, check into the
+Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and
+CMock and supports xunit-style xml as well as other goodies.
+
+This script assumes the existence of files ending with the extensions
+`.testpass` and `.testfail`.The contents of these files includes the test
+results summary corresponding to each test file executed with the extension set
+according to the presence or absence of failures for that test file. The script
+searches a specified path for these files, opens each one it finds, parses the
+results, and aggregates and prints a summary. Calling it from the command line
+looks like this:
+
+```Shell
+ruby unity_test_summary.rb build/test/
+```
+
+You can optionally specify a root path as well. This is really helpful when you
+are using relative paths in your tools' setup, but you want to pull the summary
+into an IDE like Eclipse for clickable shortcuts.
+
+```Shell
+ruby unity_test_summary.rb build/test/ ~/projects/myproject/
+```
+
+Or, if you're more of a Windows sort of person:
+
+```Shell
+ruby unity_test_summary.rb build\teat\ C:\projects\myproject\
+```
+
+When configured correctly, you'll see a final summary, like so:
+
+```Shell
+--------------------------
+UNITY IGNORED TEST SUMMARY
+--------------------------
+blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE
+
+-------------------------
+UNITY FAILED TEST SUMMARY
+-------------------------
+blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0
+meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke"
+
+--------------------------
+OVERALL UNITY TEST SUMMARY
+--------------------------
+45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED
+```
+
+How convenient is that?
+
+
+*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling.rb b/tinyusb/test/vendor/ceedling/lib/ceedling.rb
new file mode 100755
index 00000000..7f340023
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling.rb
@@ -0,0 +1,99 @@
+##
+# This module defines the interface for interacting with and loading a project
+# with Ceedling.
+module Ceedling
+ ##
+ # Returns the location where the gem is installed.
+ # === Return
+ # _String_ - The location where the gem lives.
+ def self.location
+ File.join( File.dirname(__FILE__), '..')
+ end
+
+ ##
+ # Return the path to the "built-in" plugins.
+ # === Return
+ # _String_ - The path where the default plugins live.
+ def self.load_path
+ File.join( self.location, 'plugins')
+ end
+
+ ##
+ # Return the path to the Ceedling Rakefile
+ # === Return
+ # _String_
+ def self.rakefile
+ File.join( self.location, 'lib', 'ceedling', 'rakefile.rb' )
+ end
+
+ ##
+ # This method selects the project file that Ceedling will use by setting the
+ # CEEDLING_MAIN_PROJECT_FILE environment variable before loading the ceedling
+ # rakefile. A path supplied as an argument to this method will override the
+ # current value of the environment variable. If no path is supplied as an
+ # argument then the existing value of the environment variable is used. If
+ # the environment variable has not been set and no argument has been supplied
+ # then a default path of './project.yml' will be used.
+ #
+ # === Arguments
+ # +options+ _Hash_::
+ # A hash containing the options for ceedling. Currently the following
+ # options are supported:
+ # * +config+ - The path to the project YAML configuration file.
+ # * +root+ - The root of the project directory.
+ # * +prefix+ - A prefix to prepend to plugin names in order to determine the
+ # corresponding gem name.
+ # * +plugins+ - The list of ceedling plugins to load
+ def self.load_project(options = {})
+ # Make sure our path to the yaml file is setup
+ if options.has_key? :config
+ ENV['CEEDLING_MAIN_PROJECT_FILE'] = options[:config]
+ elsif ENV['CEEDLING_MAIN_PROJECT_FILE'].nil?
+ ENV['CEEDLING_MAIN_PROJECT_FILE'] = './project.yml'
+ end
+
+ # Register the plugins
+ if options.has_key? :plugins
+ options[:plugins].each do |plugin|
+ register_plugin( plugin, options[:prefix] )
+ end
+ end
+
+ # Define the root of the project if specified
+ Object.const_set('PROJECT_ROOT', options[:root]) if options.has_key? :root
+
+ # Load ceedling
+ load "#{self.rakefile}"
+ end
+
+ ##
+ # Register a plugin for ceedling to use when a project is loaded. This method
+ # *must* be called prior to calling the _load_project_ method.
+ #
+ # This method is intended to be used for loading plugins distributed via the
+ # RubyGems mechanism. As such, the following gem structure is assumed for
+ # plugins.
+ #
+ # * The gem name must be prefixed with 'ceedling-' followed by the plugin
+ # name (ex. 'ceedling-bullseye')
+ #
+ # * The contents of the plugin must be isntalled into a subdirectory of
+ # the gem with the same name as the plugin (ex. 'bullseye/')
+ #
+ # === Arguments
+ # +name+ _String_:: The name of the plugin to load.
+ # +prefix+ _String_::
+ # (optional, default = nil) The prefix to use for the full gem name.
+ def self.register_plugin(name, prefix=nil)
+ # Figure out the full name of the gem and location
+ prefix ||= 'ceedling-'
+ gem_name = prefix + name
+ gem_dir = Gem::Specification.find_by_name(gem_name).gem_dir()
+
+ # Register the plugin with Ceedling
+ require 'ceedling/defaults'
+ DEFAULT_CEEDLING_CONFIG[:plugins][:enabled] << name
+ DEFAULT_CEEDLING_CONFIG[:plugins][:load_paths] << gem_dir
+ end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/build_invoker_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/build_invoker_utils.rb
new file mode 100755
index 00000000..b7d57f8f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/build_invoker_utils.rb
@@ -0,0 +1,39 @@
+require 'ceedling/constants'
+
+##
+# Utilities for raiser and reporting errors during building.
+class BuildInvokerUtils
+
+ constructor :configurator, :streaminator
+
+ ##
+ # Processes exceptions and tries to display a useful message for the user.
+ #
+ # ==== Attriboops...utes
+ #
+ # * _exception_: The exception given by a rescue statement.
+ # * _context_: A symbol representing where in the build the exception
+ # occurs.
+ # * _test_build_: A bool to signify if the exception occurred while building
+ # from test or source.
+ #
+ def process_exception(exception, context, test_build=true)
+ if (exception.message =~ /Don't know how to build task '(.+)'/i)
+ error_header = "ERROR: Rake could not find file referenced in source"
+ error_header += " or test" if (test_build)
+ error_header += ": '#{$1}'. Possible stale dependency."
+
+ @streaminator.stderr_puts( error_header )
+
+ if (@configurator.project_use_deep_dependencies)
+ help_message = "Try fixing #include statements or adding missing file. Then run '#{REFRESH_TASK_ROOT}#{context.to_s}' task and try again."
+ @streaminator.stderr_puts( help_message )
+ end
+
+ raise ''
+ else
+ raise exception
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator.rb
new file mode 100755
index 00000000..519a4aab
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator.rb
@@ -0,0 +1,47 @@
+
+class Cacheinator
+
+ constructor :cacheinator_helper, :file_path_utils, :file_wrapper, :yaml_wrapper
+
+ def cache_test_config(hash)
+ @yaml_wrapper.dump( @file_path_utils.form_test_build_cache_path( INPUT_CONFIGURATION_CACHE_FILE), hash )
+ end
+
+ def cache_release_config(hash)
+ @yaml_wrapper.dump( @file_path_utils.form_release_build_cache_path( INPUT_CONFIGURATION_CACHE_FILE ), hash )
+ end
+
+
+ def diff_cached_test_file( filepath )
+ cached_filepath = @file_path_utils.form_test_build_cache_path( filepath )
+
+ if (@file_wrapper.exist?( cached_filepath ) and (!@file_wrapper.compare( filepath, cached_filepath )))
+ @file_wrapper.cp(filepath, cached_filepath, {:preserve => false})
+ return filepath
+ elsif (!@file_wrapper.exist?( cached_filepath ))
+ @file_wrapper.cp(filepath, cached_filepath, {:preserve => false})
+ return filepath
+ end
+
+ return cached_filepath
+ end
+
+ def diff_cached_test_config?(hash)
+ cached_filepath = @file_path_utils.form_test_build_cache_path(INPUT_CONFIGURATION_CACHE_FILE)
+
+ return @cacheinator_helper.diff_cached_config?( cached_filepath, hash )
+ end
+
+ def diff_cached_test_defines?(files)
+ cached_filepath = @file_path_utils.form_test_build_cache_path(DEFINES_DEPENDENCY_CACHE_FILE)
+
+ return @cacheinator_helper.diff_cached_defines?( cached_filepath, files )
+ end
+
+ def diff_cached_release_config?(hash)
+ cached_filepath = @file_path_utils.form_release_build_cache_path(INPUT_CONFIGURATION_CACHE_FILE)
+
+ return @cacheinator_helper.diff_cached_config?( cached_filepath, hash )
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator_helper.rb
new file mode 100755
index 00000000..2a161854
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/cacheinator_helper.rb
@@ -0,0 +1,31 @@
+
+class CacheinatorHelper
+
+ constructor :file_wrapper, :yaml_wrapper
+
+ def diff_cached_config?(cached_filepath, hash)
+ return true if ( not @file_wrapper.exist?(cached_filepath) )
+ return true if ( (@file_wrapper.exist?(cached_filepath)) and (!(@yaml_wrapper.load(cached_filepath) == hash)) )
+ return false
+ end
+
+ def diff_cached_defines?(cached_filepath, files)
+ current_defines = COLLECTION_DEFINES_TEST_AND_VENDOR.reject(&:empty?)
+
+ current_dependency = Hash[files.collect { |source| [source, current_defines.dup] }]
+ if not @file_wrapper.exist?(cached_filepath)
+ @yaml_wrapper.dump(cached_filepath, current_dependency)
+ return false
+ end
+
+ dependencies = @yaml_wrapper.load(cached_filepath)
+ if dependencies.values_at(*current_dependency.keys) != current_dependency.values
+ dependencies.merge!(current_dependency)
+ @yaml_wrapper.dump(cached_filepath, dependencies)
+ return true
+ end
+
+ return false
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/cmock_builder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/cmock_builder.rb
new file mode 100755
index 00000000..4a74aa84
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/cmock_builder.rb
@@ -0,0 +1,15 @@
+require 'cmock'
+
+class CmockBuilder
+
+ attr_accessor :cmock
+
+ def setup
+ @cmock = nil
+ end
+
+ def manufacture(cmock_config)
+ @cmock = CMock.new(cmock_config)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator.rb
new file mode 100755
index 00000000..b5ad8982
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator.rb
@@ -0,0 +1,363 @@
+require 'ceedling/defaults'
+require 'ceedling/constants'
+require 'ceedling/file_path_utils'
+require 'deep_merge'
+
+
+
+class Configurator
+
+ attr_reader :project_config_hash, :script_plugins, :rake_plugins
+ attr_accessor :project_logging, :project_debug, :project_verbosity, :sanity_checks
+
+ constructor(:configurator_setup, :configurator_builder, :configurator_plugins, :cmock_builder, :yaml_wrapper, :system_wrapper) do
+ @project_logging = false
+ @project_debug = false
+ @project_verbosity = Verbosity::NORMAL
+ @sanity_checks = TestResultsSanityChecks::NORMAL
+ end
+
+ def setup
+ # special copy of cmock config to provide to cmock for construction
+ @cmock_config_hash = {}
+
+ # note: project_config_hash is an instance variable so constants and accessors created
+ # in eval() statements in build() have something of proper scope and persistence to reference
+ @project_config_hash = {}
+ @project_config_hash_backup = {}
+
+ @script_plugins = []
+ @rake_plugins = []
+ end
+
+
+ def replace_flattened_config(config)
+ @project_config_hash.merge!(config)
+ @configurator_setup.build_constants_and_accessors(@project_config_hash, binding())
+ end
+
+
+ def store_config
+ @project_config_hash_backup = @project_config_hash.clone
+ end
+
+
+ def restore_config
+ @project_config_hash = @project_config_hash_backup
+ @configurator_setup.build_constants_and_accessors(@project_config_hash, binding())
+ end
+
+
+ def reset_defaults(config)
+ [:test_compiler,
+ :test_linker,
+ :test_fixture,
+ :test_includes_preprocessor,
+ :test_file_preprocessor,
+ :test_dependencies_generator,
+ :release_compiler,
+ :release_assembler,
+ :release_linker,
+ :release_dependencies_generator].each do |tool|
+ config[:tools].delete(tool) if (not (config[:tools][tool].nil?))
+ end
+ end
+
+
+ # The default values defined in defaults.rb (eg. DEFAULT_TOOLS_TEST) are populated
+ # into @param config
+ def populate_defaults(config)
+ new_config = DEFAULT_CEEDLING_CONFIG.deep_clone
+ new_config.deep_merge!(config)
+ config.replace(new_config)
+
+ @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_TEST )
+ @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_TEST_PREPROCESSORS ) if (config[:project][:use_test_preprocessor])
+ @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_TEST_DEPENDENCIES ) if (config[:project][:use_deep_dependencies])
+
+ @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_RELEASE ) if (config[:project][:release_build])
+ @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_RELEASE_ASSEMBLER ) if (config[:project][:release_build] and config[:release_build][:use_assembly])
+ @configurator_builder.populate_defaults( config, DEFAULT_TOOLS_RELEASE_DEPENDENCIES ) if (config[:project][:release_build] and config[:project][:use_deep_dependencies])
+ end
+
+
+ def populate_unity_defaults(config)
+ unity = config[:unity] || {}
+ @runner_config = unity.merge(@runner_config || config[:test_runner] || {})
+ end
+
+ def populate_cmock_defaults(config)
+ # cmock has its own internal defaults handling, but we need to set these specific values
+ # so they're present for the build environment to access;
+ # note: these need to end up in the hash given to initialize cmock for this to be successful
+ cmock = config[:cmock] || {}
+
+ # yes, we're duplicating the default mock_prefix in cmock, but it's because we need CMOCK_MOCK_PREFIX always available in Ceedling's environment
+ cmock[:mock_prefix] = 'Mock' if (cmock[:mock_prefix].nil?)
+
+ # just because strict ordering is the way to go
+ cmock[:enforce_strict_ordering] = true if (cmock[:enforce_strict_ordering].nil?)
+
+ cmock[:mock_path] = File.join(config[:project][:build_root], TESTS_BASE_PATH, 'mocks') if (cmock[:mock_path].nil?)
+ cmock[:verbosity] = @project_verbosity if (cmock[:verbosity].nil?)
+
+ cmock[:plugins] = [] if (cmock[:plugins].nil?)
+ cmock[:plugins].map! { |plugin| plugin.to_sym }
+ cmock[:plugins] << (:cexception) if (!cmock[:plugins].include?(:cexception) and (config[:project][:use_exceptions]))
+ cmock[:plugins].uniq!
+
+ cmock[:unity_helper] = false if (cmock[:unity_helper].nil?)
+
+ if (cmock[:unity_helper])
+ cmock[:unity_helper] = [cmock[:unity_helper]] if cmock[:unity_helper].is_a? String
+ cmock[:includes] += cmock[:unity_helper].map{|helper| File.basename(helper) }
+ cmock[:includes].uniq!
+ end
+
+ @runner_config = cmock.merge(@runner_config || config[:test_runner] || {})
+
+ @cmock_builder.manufacture(cmock)
+ end
+
+
+ def get_runner_config
+ @runner_config
+ end
+
+
+ # grab tool names from yaml and insert into tool structures so available for error messages
+ # set up default values
+ def tools_setup(config)
+ config[:tools].each_key do |name|
+ tool = config[:tools][name]
+
+ # populate name if not given
+ tool[:name] = name.to_s if (tool[:name].nil?)
+
+ # handle inline ruby string substitution in executable
+ if (tool[:executable] =~ RUBY_STRING_REPLACEMENT_PATTERN)
+ tool[:executable].replace(@system_wrapper.module_eval(tool[:executable]))
+ end
+
+ # populate stderr redirect option
+ tool[:stderr_redirect] = StdErrRedirect::NONE if (tool[:stderr_redirect].nil?)
+
+ # populate background execution option
+ tool[:background_exec] = BackgroundExec::NONE if (tool[:background_exec].nil?)
+
+ # populate optional option to control verification of executable in search paths
+ tool[:optional] = false if (tool[:optional].nil?)
+ end
+ end
+
+
+ def tools_supplement_arguments(config)
+ tools_name_prefix = 'tools_'
+ config[:tools].each_key do |name|
+ tool = @project_config_hash[(tools_name_prefix + name.to_s).to_sym]
+
+ # smoosh in extra arguments if specified at top-level of config (useful for plugins & default gcc tools)
+ # arguments are squirted in at _end_ of list
+ top_level_tool = (tools_name_prefix + name.to_s).to_sym
+ if (not config[top_level_tool].nil?)
+ # adding and flattening is not a good idea: might over-flatten if there's array nesting in tool args
+ tool[:arguments].concat config[top_level_tool][:arguments]
+ end
+ end
+ end
+
+
+ def find_and_merge_plugins(config)
+ # plugins must be loaded before generic path evaluation & magic that happen later;
+ # perform path magic here as discrete step
+ config[:plugins][:load_paths].each do |path|
+ path.replace(@system_wrapper.module_eval(path)) if (path =~ RUBY_STRING_REPLACEMENT_PATTERN)
+ FilePathUtils::standardize(path)
+ end
+
+ config[:plugins][:load_paths] << FilePathUtils::standardize(Ceedling.load_path)
+ config[:plugins][:load_paths].uniq!
+
+ paths_hash = @configurator_plugins.add_load_paths(config)
+
+ @rake_plugins = @configurator_plugins.find_rake_plugins(config, paths_hash)
+ @script_plugins = @configurator_plugins.find_script_plugins(config, paths_hash)
+ config_plugins = @configurator_plugins.find_config_plugins(config, paths_hash)
+ plugin_defaults = @configurator_plugins.find_plugin_defaults(config, paths_hash)
+
+ config_plugins.each do |plugin|
+ plugin_config = @yaml_wrapper.load(plugin)
+ config.deep_merge(plugin_config)
+ end
+
+ plugin_defaults.each do |defaults|
+ @configurator_builder.populate_defaults( config, @yaml_wrapper.load(defaults) )
+ end
+
+ # special plugin setting for results printing
+ config[:plugins][:display_raw_test_results] = true if (config[:plugins][:display_raw_test_results].nil?)
+
+ paths_hash.each_pair { |name, path| config[:plugins][name] = path }
+ end
+
+
+ def merge_imports(config)
+ if config[:import]
+ until config[:import].empty?
+ path = config[:import].shift
+ path = @system_wrapper.module_eval(path) if (path =~ RUBY_STRING_REPLACEMENT_PATTERN)
+ config.deep_merge!(@yaml_wrapper.load(path))
+ end
+ end
+ config.delete(:import)
+ end
+
+
+ def eval_environment_variables(config)
+ config[:environment].each do |hash|
+ key = hash.keys[0]
+ value = hash[key]
+ items = []
+
+ interstitial = ((key == :path) ? File::PATH_SEPARATOR : '')
+ items = ((value.class == Array) ? hash[key] : [value])
+
+ items.each { |item| item.replace( @system_wrapper.module_eval( item ) ) if (item =~ RUBY_STRING_REPLACEMENT_PATTERN) }
+ hash[key] = items.join( interstitial )
+
+ @system_wrapper.env_set( key.to_s.upcase, hash[key] )
+ end
+ end
+
+
+ def eval_paths(config)
+ # [:plugins]:[load_paths] already handled
+
+ paths = [ # individual paths that don't follow convention processed below
+ config[:project][:build_root],
+ config[:release_build][:artifacts]]
+
+ eval_path_list( paths )
+
+ config[:paths].each_pair { |collection, paths| eval_path_list( paths ) }
+
+ config[:files].each_pair { |collection, files| eval_path_list( files ) }
+
+ # all other paths at secondary hash key level processed by convention:
+ # ex. [:toplevel][:foo_path] & [:toplevel][:bar_paths] are evaluated
+ config.each_pair { |parent, child| eval_path_list( collect_path_list( child ) ) }
+ end
+
+
+ def standardize_paths(config)
+ # [:plugins]:[load_paths] already handled
+
+ paths = [ # individual paths that don't follow convention processed below
+ config[:project][:build_root],
+ config[:release_build][:artifacts]] # cmock path in case it was explicitly set in config
+
+ paths.flatten.each { |path| FilePathUtils::standardize( path ) }
+
+ config[:paths].each_pair do |collection, paths|
+ # ensure that list is an array (i.e. handle case of list being a single string,
+ # or a multidimensional array)
+ config[:paths][collection] = [paths].flatten.map{|path| FilePathUtils::standardize( path )}
+ end
+
+ config[:files].each_pair { |collection, files| files.each{ |path| FilePathUtils::standardize( path ) } }
+
+ config[:tools].each_pair { |tool, config| FilePathUtils::standardize( config[:executable] ) if (config.include? :executable) }
+
+ # all other paths at secondary hash key level processed by convention:
+ # ex. [:toplevel][:foo_path] & [:toplevel][:bar_paths] are standardized
+ config.each_pair do |parent, child|
+ collect_path_list( child ).each { |path| FilePathUtils::standardize( path ) }
+ end
+ end
+
+
+ def validate(config)
+ # collect felonies and go straight to jail
+ raise if (not @configurator_setup.validate_required_sections( config ))
+
+ # collect all misdemeanors, everybody on probation
+ blotter = []
+ blotter << @configurator_setup.validate_required_section_values( config )
+ blotter << @configurator_setup.validate_paths( config )
+ blotter << @configurator_setup.validate_tools( config )
+ blotter << @configurator_setup.validate_plugins( config )
+
+ raise if (blotter.include?( false ))
+ end
+
+
+ # create constants and accessors (attached to this object) from given hash
+ def build(config, *keys)
+ # create flattened & expanded configuration hash
+ built_config = @configurator_setup.build_project_config( config, @configurator_builder.flattenify( config ) )
+
+ @project_config_hash = built_config.clone
+ store_config()
+
+ @configurator_setup.build_constants_and_accessors(built_config, binding())
+
+ # top-level keys disappear when we flatten, so create global constants & accessors to any specified keys
+ keys.each do |key|
+ hash = { key => config[key] }
+ @configurator_setup.build_constants_and_accessors(hash, binding())
+ end
+ end
+
+
+ # add to constants and accessors as post build step
+ def build_supplement(config_base, config_more)
+ # merge in our post-build additions to base configuration hash
+ config_base.deep_merge!( config_more )
+
+ # flatten our addition hash
+ config_more_flattened = @configurator_builder.flattenify( config_more )
+
+ # merge our flattened hash with built hash from previous build
+ @project_config_hash.deep_merge!( config_more_flattened )
+ store_config()
+
+ # create more constants and accessors
+ @configurator_setup.build_constants_and_accessors(config_more_flattened, binding())
+
+ # recreate constants & update accessors with new merged, base values
+ config_more.keys.each do |key|
+ hash = { key => config_base[key] }
+ @configurator_setup.build_constants_and_accessors(hash, binding())
+ end
+ end
+
+
+ def insert_rake_plugins(plugins)
+ plugins.each do |plugin|
+ @project_config_hash[:project_rakefile_component_files] << plugin
+ end
+ end
+
+ ### private ###
+
+ private
+
+ def collect_path_list( container )
+ paths = []
+ container.each_key { |key| paths << container[key] if (key.to_s =~ /_path(s)?$/) } if (container.class == Hash)
+ return paths.flatten
+ end
+
+ def eval_path_list( paths )
+ if paths.kind_of?(Array)
+ paths = Array.new(paths)
+ end
+
+ paths.flatten.each do |path|
+ path.replace( @system_wrapper.module_eval( path ) ) if (path =~ RUBY_STRING_REPLACEMENT_PATTERN)
+ end
+ end
+
+
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_builder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_builder.rb
new file mode 100755
index 00000000..da8a816f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_builder.rb
@@ -0,0 +1,458 @@
+require 'rubygems'
+require 'rake' # for ext() method
+require 'ceedling/file_path_utils' # for class methods
+require 'ceedling/defaults'
+require 'ceedling/constants' # for Verbosity constants class & base file paths
+
+
+
+class ConfiguratorBuilder
+
+ constructor :file_system_utils, :file_wrapper, :system_wrapper
+
+
+ def build_global_constants(config)
+ config.each_pair do |key, value|
+ formatted_key = key.to_s.upcase
+ # undefine global constant if it already exists
+ Object.send(:remove_const, formatted_key.to_sym) if @system_wrapper.constants_include?(formatted_key)
+ # create global constant
+ Object.module_eval("#{formatted_key} = value")
+ end
+ end
+
+
+ def build_accessor_methods(config, context)
+ config.each_pair do |key, value|
+ # fill configurator object with accessor methods
+ eval("def #{key.to_s.downcase}() return @project_config_hash[:#{key.to_s}] end", context)
+ end
+ end
+
+
+ # create a flattened hash from the original configuration structure
+ def flattenify(config)
+ new_hash = {}
+
+ config.each_key do | parent |
+
+ # gracefully handle empty top-level entries
+ next if (config[parent].nil?)
+
+ case config[parent]
+ when Array
+ config[parent].each do |hash|
+ key = "#{parent.to_s.downcase}_#{hash.keys[0].to_s.downcase}".to_sym
+ new_hash[key] = hash[hash.keys[0]]
+ end
+ when Hash
+ config[parent].each_pair do | child, value |
+ key = "#{parent.to_s.downcase}_#{child.to_s.downcase}".to_sym
+ new_hash[key] = value
+ end
+ # handle entries with no children, only values
+ else
+ new_hash["#{parent.to_s.downcase}".to_sym] = config[parent]
+ end
+
+ end
+
+ return new_hash
+ end
+
+
+ def populate_defaults(config, defaults)
+ defaults.keys.sort.each do |section|
+ defaults[section].keys.sort.each do |entry|
+ config[section] = {} if config[section].nil?
+ config[section][entry] = defaults[section][entry].deep_clone if (config[section][entry].nil?)
+ end
+ end
+ end
+
+
+ def clean(in_hash)
+ # ensure that include files inserted into test runners have file extensions & proper ones at that
+ in_hash[:test_runner_includes].map!{|include| include.ext(in_hash[:extension_header])}
+ end
+
+
+ def set_build_paths(in_hash)
+ out_hash = {}
+
+ project_build_artifacts_root = File.join(in_hash[:project_build_root], 'artifacts')
+ project_build_tests_root = File.join(in_hash[:project_build_root], TESTS_BASE_PATH)
+ project_build_release_root = File.join(in_hash[:project_build_root], RELEASE_BASE_PATH)
+
+ paths = [
+ [:project_build_artifacts_root, project_build_artifacts_root, true ],
+ [:project_build_tests_root, project_build_tests_root, true ],
+ [:project_build_release_root, project_build_release_root, in_hash[:project_release_build] ],
+
+ [:project_test_artifacts_path, File.join(project_build_artifacts_root, TESTS_BASE_PATH), true ],
+ [:project_test_runners_path, File.join(project_build_tests_root, 'runners'), true ],
+ [:project_test_results_path, File.join(project_build_tests_root, 'results'), true ],
+ [:project_test_build_output_path, File.join(project_build_tests_root, 'out'), true ],
+ [:project_test_build_output_asm_path, File.join(project_build_tests_root, 'out', 'asm'), true ],
+ [:project_test_build_output_c_path, File.join(project_build_tests_root, 'out', 'c'), true ],
+ [:project_test_build_cache_path, File.join(project_build_tests_root, 'cache'), true ],
+ [:project_test_dependencies_path, File.join(project_build_tests_root, 'dependencies'), true ],
+
+ [:project_release_artifacts_path, File.join(project_build_artifacts_root, RELEASE_BASE_PATH), in_hash[:project_release_build] ],
+ [:project_release_build_cache_path, File.join(project_build_release_root, 'cache'), in_hash[:project_release_build] ],
+ [:project_release_build_output_path, File.join(project_build_release_root, 'out'), in_hash[:project_release_build] ],
+ [:project_release_build_output_asm_path, File.join(project_build_release_root, 'out', 'asm'), in_hash[:project_release_build] ],
+ [:project_release_build_output_c_path, File.join(project_build_release_root, 'out', 'c'), in_hash[:project_release_build] ],
+ [:project_release_dependencies_path, File.join(project_build_release_root, 'dependencies'), in_hash[:project_release_build] ],
+
+ [:project_log_path, File.join(in_hash[:project_build_root], 'logs'), true ],
+ [:project_temp_path, File.join(in_hash[:project_build_root], 'temp'), true ],
+
+ [:project_test_preprocess_includes_path, File.join(project_build_tests_root, 'preprocess/includes'), in_hash[:project_use_test_preprocessor] ],
+ [:project_test_preprocess_files_path, File.join(project_build_tests_root, 'preprocess/files'), in_hash[:project_use_test_preprocessor] ],
+ ]
+
+ out_hash[:project_build_paths] = []
+
+ # fetch already set mock path
+ out_hash[:project_build_paths] << in_hash[:cmock_mock_path] if (in_hash[:project_use_mocks])
+
+ paths.each do |path|
+ build_path_name = path[0]
+ build_path = path[1]
+ build_path_add_condition = path[2]
+
+ # insert path into build paths if associated with true condition
+ out_hash[:project_build_paths] << build_path if build_path_add_condition
+ # set path symbol name and path for each entry in paths array
+ out_hash[build_path_name] = build_path
+ end
+
+ return out_hash
+ end
+
+
+ def set_force_build_filepaths(in_hash)
+ out_hash = {}
+
+ out_hash[:project_test_force_rebuild_filepath] = File.join( in_hash[:project_test_dependencies_path], 'force_build' )
+ out_hash[:project_release_force_rebuild_filepath] = File.join( in_hash[:project_release_dependencies_path], 'force_build' ) if (in_hash[:project_release_build])
+
+ return out_hash
+ end
+
+
+ def set_rakefile_components(in_hash)
+ out_hash = {
+ :project_rakefile_component_files =>
+ [File.join(CEEDLING_LIB, 'ceedling', 'tasks_base.rake'),
+ File.join(CEEDLING_LIB, 'ceedling', 'tasks_filesystem.rake'),
+ File.join(CEEDLING_LIB, 'ceedling', 'tasks_tests.rake'),
+ File.join(CEEDLING_LIB, 'ceedling', 'tasks_vendor.rake'),
+ File.join(CEEDLING_LIB, 'ceedling', 'rules_tests.rake')]}
+
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_cmock.rake') if (in_hash[:project_use_mocks])
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_preprocess.rake') if (in_hash[:project_use_test_preprocessor])
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_tests_deep_dependencies.rake') if (in_hash[:project_use_deep_dependencies])
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_tests_deep_dependencies.rake') if (in_hash[:project_use_deep_dependencies])
+
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_release_deep_dependencies.rake') if (in_hash[:project_release_build] and in_hash[:project_use_deep_dependencies])
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'rules_release.rake') if (in_hash[:project_release_build])
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_release_deep_dependencies.rake') if (in_hash[:project_release_build] and in_hash[:project_use_deep_dependencies])
+ out_hash[:project_rakefile_component_files] << File.join(CEEDLING_LIB, 'ceedling', 'tasks_release.rake') if (in_hash[:project_release_build])
+
+ return out_hash
+ end
+
+
+ def set_release_target(in_hash)
+ return {} if (not in_hash[:project_release_build])
+
+ release_target_file = ((in_hash[:release_build_output].nil?) ? (DEFAULT_RELEASE_TARGET_NAME.ext(in_hash[:extension_executable])) : in_hash[:release_build_output])
+ release_map_file = ((in_hash[:release_build_output].nil?) ? (DEFAULT_RELEASE_TARGET_NAME.ext(in_hash[:extension_map])) : in_hash[:release_build_output].ext(in_hash[:extension_map]))
+
+ return {
+ # tempted to make a helper method in file_path_utils? stop right there, pal. you'll introduce a cyclical dependency
+ :project_release_build_target => File.join(in_hash[:project_build_release_root], release_target_file),
+ :project_release_build_map => File.join(in_hash[:project_build_release_root], release_map_file)
+ }
+ end
+
+
+ def collect_project_options(in_hash)
+ options = []
+
+ in_hash[:project_options_paths].each do |path|
+ options << @file_wrapper.directory_listing( File.join(path, '*.yml') )
+ end
+
+ return {
+ :collection_project_options => options.flatten
+ }
+ end
+
+
+ def expand_all_path_globs(in_hash)
+ out_hash = {}
+ path_keys = []
+
+ in_hash.each_key do |key|
+ next if (not key.to_s[0..4] == 'paths')
+ path_keys << key
+ end
+
+ # sorted to provide assured order of traversal in test calls on mocks
+ path_keys.sort.each do |key|
+ out_hash["collection_#{key.to_s}".to_sym] = @file_system_utils.collect_paths( in_hash[key] )
+ end
+
+ return out_hash
+ end
+
+
+ def collect_source_and_include_paths(in_hash)
+ return {
+ :collection_paths_source_and_include =>
+ ( in_hash[:collection_paths_source] +
+ in_hash[:collection_paths_include] ).select {|x| File.directory?(x)}
+ }
+ end
+
+
+ def collect_source_include_vendor_paths(in_hash)
+ extra_paths = []
+ extra_paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions])
+
+ return {
+ :collection_paths_source_include_vendor =>
+ in_hash[:collection_paths_source_and_include] +
+ extra_paths
+ }
+ end
+
+
+ def collect_test_support_source_include_paths(in_hash)
+ return {
+ :collection_paths_test_support_source_include =>
+ (in_hash[:collection_paths_test] +
+ in_hash[:collection_paths_support] +
+ in_hash[:collection_paths_source] +
+ in_hash[:collection_paths_include] ).select {|x| File.directory?(x)}
+ }
+ end
+
+
+ def collect_vendor_paths(in_hash)
+ return {:collection_paths_vendor => get_vendor_paths(in_hash)}
+ end
+
+
+ def collect_test_support_source_include_vendor_paths(in_hash)
+ return {
+ :collection_paths_test_support_source_include_vendor =>
+ in_hash[:collection_paths_test_support_source_include] +
+ get_vendor_paths(in_hash)
+ }
+ end
+
+
+ def collect_tests(in_hash)
+ all_tests = @file_wrapper.instantiate_file_list
+
+ in_hash[:collection_paths_test].each do |path|
+ all_tests.include( File.join(path, "#{in_hash[:project_test_file_prefix]}*#{in_hash[:extension_source]}") )
+ end
+
+ @file_system_utils.revise_file_list( all_tests, in_hash[:files_test] )
+
+ return {:collection_all_tests => all_tests}
+ end
+
+
+ def collect_assembly(in_hash)
+ all_assembly = @file_wrapper.instantiate_file_list
+
+ return {:collection_all_assembly => all_assembly} if ((not in_hash[:release_build_use_assembly]) && (not in_hash[:test_build_use_assembly]))
+
+ # Sprinkle in all assembly files we can find in the source folders
+ in_hash[:collection_paths_source].each do |path|
+ all_assembly.include( File.join(path, "*#{in_hash[:extension_assembly]}") )
+ end
+
+ # Also add all assembly files we can find in the support folders
+ in_hash[:collection_paths_support].each do |path|
+ all_assembly.include( File.join(path, "*#{in_hash[:extension_assembly]}") )
+ end
+
+ # Also add files that we are explicitly adding via :files:assembly: section
+ @file_system_utils.revise_file_list( all_assembly, in_hash[:files_assembly] )
+
+ return {:collection_all_assembly => all_assembly}
+ end
+
+
+ def collect_source(in_hash)
+ all_source = @file_wrapper.instantiate_file_list
+ in_hash[:collection_paths_source].each do |path|
+ if File.exists?(path) and not File.directory?(path)
+ all_source.include( path )
+ else
+ all_source.include( File.join(path, "*#{in_hash[:extension_source]}") )
+ end
+ end
+ @file_system_utils.revise_file_list( all_source, in_hash[:files_source] )
+
+ return {:collection_all_source => all_source}
+ end
+
+
+ def collect_headers(in_hash)
+ all_headers = @file_wrapper.instantiate_file_list
+
+ paths =
+ in_hash[:collection_paths_test] +
+ in_hash[:collection_paths_support] +
+ in_hash[:collection_paths_source] +
+ in_hash[:collection_paths_include]
+
+ paths.each do |path|
+ all_headers.include( File.join(path, "*#{in_hash[:extension_header]}") )
+ end
+
+ @file_system_utils.revise_file_list( all_headers, in_hash[:files_include] )
+
+ return {:collection_all_headers => all_headers}
+ end
+
+
+ def collect_release_existing_compilation_input(in_hash)
+ release_input = @file_wrapper.instantiate_file_list
+
+ paths =
+ in_hash[:collection_paths_source] +
+ in_hash[:collection_paths_include]
+
+ paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions])
+
+ paths.each do |path|
+ release_input.include( File.join(path, "*#{in_hash[:extension_header]}") )
+ if File.exists?(path) and not File.directory?(path)
+ release_input.include( path )
+ else
+ release_input.include( File.join(path, "*#{in_hash[:extension_source]}") )
+ end
+ end
+
+ @file_system_utils.revise_file_list( release_input, in_hash[:files_source] )
+ @file_system_utils.revise_file_list( release_input, in_hash[:files_include] )
+ # finding assembly files handled explicitly through other means
+
+ return {:collection_release_existing_compilation_input => release_input}
+ end
+
+
+ def collect_all_existing_compilation_input(in_hash)
+ all_input = @file_wrapper.instantiate_file_list
+
+ paths =
+ in_hash[:collection_paths_test] +
+ in_hash[:collection_paths_support] +
+ in_hash[:collection_paths_source] +
+ in_hash[:collection_paths_include] +
+ [File.join(in_hash[:unity_vendor_path], UNITY_LIB_PATH)]
+
+ paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions])
+ paths << File.join(in_hash[:cmock_vendor_path], CMOCK_LIB_PATH) if (in_hash[:project_use_mocks])
+
+ paths.each do |path|
+ all_input.include( File.join(path, "*#{in_hash[:extension_header]}") )
+ if File.exists?(path) and not File.directory?(path)
+ all_input.include( path )
+ else
+ all_input.include( File.join(path, "*#{in_hash[:extension_source]}") )
+ all_input.include( File.join(path, "*#{in_hash[:extension_assembly]}") ) if (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY)
+ end
+ end
+
+ @file_system_utils.revise_file_list( all_input, in_hash[:files_test] )
+ @file_system_utils.revise_file_list( all_input, in_hash[:files_support] )
+ @file_system_utils.revise_file_list( all_input, in_hash[:files_source] )
+ @file_system_utils.revise_file_list( all_input, in_hash[:files_include] )
+ # finding assembly files handled explicitly through other means
+
+ return {:collection_all_existing_compilation_input => all_input}
+ end
+
+
+ def collect_test_and_vendor_defines(in_hash)
+ test_defines = in_hash[:defines_test].clone
+
+ test_defines.concat(in_hash[:unity_defines])
+ test_defines.concat(in_hash[:cmock_defines]) if (in_hash[:project_use_mocks])
+ test_defines.concat(in_hash[:cexception_defines]) if (in_hash[:project_use_exceptions])
+
+ return {:collection_defines_test_and_vendor => test_defines}
+ end
+
+
+ def collect_release_and_vendor_defines(in_hash)
+ release_defines = in_hash[:defines_release].clone
+
+ release_defines.concat(in_hash[:cexception_defines]) if (in_hash[:project_use_exceptions])
+
+ return {:collection_defines_release_and_vendor => release_defines}
+ end
+
+
+ def collect_release_artifact_extra_link_objects(in_hash)
+ objects = []
+
+ # no build paths here so plugins can remap if necessary (i.e. path mapping happens at runtime)
+ objects << CEXCEPTION_C_FILE.ext( in_hash[:extension_object] ) if (in_hash[:project_use_exceptions])
+
+ return {:collection_release_artifact_extra_link_objects => objects}
+ end
+
+
+ def collect_test_fixture_extra_link_objects(in_hash)
+ # Note: Symbols passed to compiler at command line can change Unity and CException behavior / configuration;
+ # we also handle those dependencies elsewhere in compilation dependencies
+
+ objects = [UNITY_C_FILE]
+
+ in_hash[:files_support].each { |file| objects << File.basename(file) }
+
+ # we don't include paths here because use of plugins or mixing different compilers may require different build paths
+ objects << CEXCEPTION_C_FILE if (in_hash[:project_use_exceptions])
+ objects << CMOCK_C_FILE if (in_hash[:project_use_mocks])
+
+ # if we're using mocks & a unity helper is defined & that unity helper includes a source file component (not only a header of macros),
+ # then link in the unity_helper object file too
+ if ( in_hash[:project_use_mocks] and in_hash[:cmock_unity_helper] )
+ in_hash[:cmock_unity_helper].each do |helper|
+ if @file_wrapper.exist?(helper.ext(in_hash[:extension_source]))
+ objects << File.basename(helper)
+ end
+ end
+ end
+
+ # no build paths here so plugins can remap if necessary (i.e. path mapping happens at runtime)
+ objects.map! { |object| object.ext(in_hash[:extension_object]) }
+
+ return { :collection_test_fixture_extra_link_objects => objects }
+ end
+
+
+ private
+
+ def get_vendor_paths(in_hash)
+ vendor_paths = []
+ vendor_paths << File.join(in_hash[:unity_vendor_path], UNITY_LIB_PATH)
+ vendor_paths << File.join(in_hash[:cexception_vendor_path], CEXCEPTION_LIB_PATH) if (in_hash[:project_use_exceptions])
+ vendor_paths << File.join(in_hash[:cmock_vendor_path], CMOCK_LIB_PATH) if (in_hash[:project_use_mocks])
+ vendor_paths << in_hash[:cmock_mock_path] if (in_hash[:project_use_mocks])
+
+ return vendor_paths
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_plugins.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_plugins.rb
new file mode 100755
index 00000000..70ca884a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_plugins.rb
@@ -0,0 +1,111 @@
+require 'ceedling/constants'
+
+class ConfiguratorPlugins
+
+ constructor :stream_wrapper, :file_wrapper, :system_wrapper
+ attr_reader :rake_plugins, :script_plugins
+
+ def setup
+ @rake_plugins = []
+ @script_plugins = []
+ end
+
+
+ def add_load_paths(config)
+ plugin_paths = {}
+
+ config[:plugins][:enabled].each do |plugin|
+ config[:plugins][:load_paths].each do |root|
+ path = File.join(root, plugin)
+
+ is_script_plugin = ( not @file_wrapper.directory_listing( File.join( path, 'lib', '*.rb' ) ).empty? )
+ is_rake_plugin = ( not @file_wrapper.directory_listing( File.join( path, '*.rake' ) ).empty? )
+
+ if is_script_plugin or is_rake_plugin
+ plugin_paths[(plugin + '_path').to_sym] = path
+
+ if is_script_plugin
+ @system_wrapper.add_load_path( File.join( path, 'lib') )
+ end
+ break
+ end
+ end
+ end
+
+ return plugin_paths
+ end
+
+
+ # gather up and return .rake filepaths that exist on-disk
+ def find_rake_plugins(config, plugin_paths)
+ @rake_plugins = []
+ plugins_with_path = []
+
+ config[:plugins][:enabled].each do |plugin|
+ if path = plugin_paths[(plugin + '_path').to_sym]
+ rake_plugin_path = File.join(path, "#{plugin}.rake")
+ if (@file_wrapper.exist?(rake_plugin_path))
+ plugins_with_path << rake_plugin_path
+ @rake_plugins << plugin
+ end
+ end
+ end
+
+ return plugins_with_path
+ end
+
+
+ # gather up and return just names of .rb classes that exist on-disk
+ def find_script_plugins(config, plugin_paths)
+ @script_plugins = []
+
+ config[:plugins][:enabled].each do |plugin|
+ if path = plugin_paths[(plugin + '_path').to_sym]
+ script_plugin_path = File.join(path, "lib", "#{plugin}.rb")
+
+ if @file_wrapper.exist?(script_plugin_path)
+ @script_plugins << plugin
+ end
+ end
+ end
+
+ return @script_plugins
+ end
+
+
+ # gather up and return configuration .yml filepaths that exist on-disk
+ def find_config_plugins(config, plugin_paths)
+ plugins_with_path = []
+
+ config[:plugins][:enabled].each do |plugin|
+ if path = plugin_paths[(plugin + '_path').to_sym]
+ config_plugin_path = File.join(path, "config", "#{plugin}.yml")
+
+ if @file_wrapper.exist?(config_plugin_path)
+ plugins_with_path << config_plugin_path
+ end
+ end
+ end
+
+ return plugins_with_path
+ end
+
+
+ # gather up and return default .yml filepaths that exist on-disk
+ def find_plugin_defaults(config, plugin_paths)
+ defaults_with_path = []
+
+ config[:plugins][:enabled].each do |plugin|
+ if path = plugin_paths[(plugin + '_path').to_sym]
+ default_path = File.join(path, 'config', 'defaults.yml')
+
+ if @file_wrapper.exist?(default_path)
+ defaults_with_path << default_path
+ end
+ end
+ end
+
+ return defaults_with_path
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_setup.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_setup.rb
new file mode 100755
index 00000000..1d029b06
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_setup.rb
@@ -0,0 +1,127 @@
+
+# add sort-ability to symbol so we can order keys array in hash for test-ability
+class Symbol
+ include Comparable
+
+ def <=>(other)
+ self.to_s <=> other.to_s
+ end
+end
+
+
+class ConfiguratorSetup
+
+ constructor :configurator_builder, :configurator_validator, :configurator_plugins, :stream_wrapper
+
+
+ def build_project_config(config, flattened_config)
+ ### flesh out config
+ @configurator_builder.clean(flattened_config)
+
+ ### add to hash values we build up from configuration & file system contents
+ flattened_config.merge!(@configurator_builder.set_build_paths(flattened_config))
+ flattened_config.merge!(@configurator_builder.set_force_build_filepaths(flattened_config))
+ flattened_config.merge!(@configurator_builder.set_rakefile_components(flattened_config))
+ flattened_config.merge!(@configurator_builder.set_release_target(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_project_options(flattened_config))
+
+ ### iterate through all entries in paths section and expand any & all globs to actual paths
+ flattened_config.merge!(@configurator_builder.expand_all_path_globs(flattened_config))
+
+ flattened_config.merge!(@configurator_builder.collect_vendor_paths(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_source_and_include_paths(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_source_include_vendor_paths(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_test_support_source_include_paths(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_test_support_source_include_vendor_paths(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_tests(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_assembly(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_source(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_headers(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_release_existing_compilation_input(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_all_existing_compilation_input(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_test_and_vendor_defines(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_release_and_vendor_defines(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_release_artifact_extra_link_objects(flattened_config))
+ flattened_config.merge!(@configurator_builder.collect_test_fixture_extra_link_objects(flattened_config))
+
+ return flattened_config
+ end
+
+
+ def build_constants_and_accessors(config, context)
+ @configurator_builder.build_global_constants(config)
+ @configurator_builder.build_accessor_methods(config, context)
+ end
+
+
+ def validate_required_sections(config)
+ validation = []
+ validation << @configurator_validator.exists?(config, :project)
+ validation << @configurator_validator.exists?(config, :paths)
+
+ return false if (validation.include?(false))
+ return true
+ end
+
+ def validate_required_section_values(config)
+ validation = []
+ validation << @configurator_validator.exists?(config, :project, :build_root)
+ validation << @configurator_validator.exists?(config, :paths, :test)
+ validation << @configurator_validator.exists?(config, :paths, :source)
+
+ return false if (validation.include?(false))
+ return true
+ end
+
+ def validate_paths(config)
+ validation = []
+
+ if config[:cmock][:unity_helper]
+ config[:cmock][:unity_helper].each do |path|
+ validation << @configurator_validator.validate_filepath_simple( path, :cmock, :unity_helper )
+ end
+ end
+
+ config[:project][:options_paths].each do |path|
+ validation << @configurator_validator.validate_filepath_simple( path, :project, :options_paths )
+ end
+
+ config[:plugins][:load_paths].each do |path|
+ validation << @configurator_validator.validate_filepath_simple( path, :plugins, :load_paths )
+ end
+
+ config[:paths].keys.sort.each do |key|
+ validation << @configurator_validator.validate_path_list(config, :paths, key)
+ end
+
+ return false if (validation.include?(false))
+ return true
+ end
+
+ def validate_tools(config)
+ validation = []
+
+ config[:tools].keys.sort.each do |key|
+ validation << @configurator_validator.exists?(config, :tools, key, :executable)
+ validation << @configurator_validator.validate_executable_filepath(config, :tools, key, :executable) if (not config[:tools][key][:optional])
+ validation << @configurator_validator.validate_tool_stderr_redirect(config, :tools, key)
+ end
+
+ return false if (validation.include?(false))
+ return true
+ end
+
+ def validate_plugins(config)
+ missing_plugins =
+ Set.new( config[:plugins][:enabled] ) -
+ Set.new( @configurator_plugins.rake_plugins ) -
+ Set.new( @configurator_plugins.script_plugins )
+
+ missing_plugins.each do |plugin|
+ @stream_wrapper.stderr_puts("ERROR: Ceedling plugin '#{plugin}' contains no rake or ruby class entry point. (Misspelled or missing files?)")
+ end
+
+ return ( (missing_plugins.size > 0) ? false : true )
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_validator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_validator.rb
new file mode 100755
index 00000000..fc021012
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/configurator_validator.rb
@@ -0,0 +1,193 @@
+require 'rubygems'
+require 'rake' # for ext()
+require 'ceedling/constants'
+require 'ceedling/tool_executor' # for argument replacement pattern
+require 'ceedling/file_path_utils' # for glob handling class methods
+
+
+class ConfiguratorValidator
+
+ constructor :file_wrapper, :stream_wrapper, :system_wrapper
+
+ # walk into config hash verify existence of data at key depth
+ def exists?(config, *keys)
+ hash = retrieve_value(config, keys)
+ exist = !hash[:value].nil?
+
+ if (not exist)
+ # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator
+ @stream_wrapper.stderr_puts("ERROR: Required config file entry #{format_key_sequence(keys, hash[:depth])} does not exist.")
+ end
+
+ return exist
+ end
+
+
+ # walk into config hash. verify directory path(s) at given key depth
+ def validate_path_list(config, *keys)
+ hash = retrieve_value(config, keys)
+ list = hash[:value]
+
+ # return early if we couldn't walk into hash and find a value
+ return false if (list.nil?)
+
+ path_list = []
+ exist = true
+
+ case list
+ when String then path_list << list
+ when Array then path_list = list
+ end
+
+ path_list.each do |path|
+ base_path = FilePathUtils::extract_path(path) # lop off add/subtract notation & glob specifiers
+
+ if (not @file_wrapper.exist?(base_path))
+ # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator
+ @stream_wrapper.stderr_puts("ERROR: Config path #{format_key_sequence(keys, hash[:depth])}['#{base_path}'] does not exist on disk.")
+ exist = false
+ end
+ end
+
+ return exist
+ end
+
+
+ # simple path verification
+ def validate_filepath_simple(path, *keys)
+ validate_path = path
+
+ if (not @file_wrapper.exist?(validate_path))
+ # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator
+ @stream_wrapper.stderr_puts("ERROR: Config path '#{validate_path}' associated with #{format_key_sequence(keys, keys.size)} does not exist on disk.")
+ return false
+ end
+
+ return true
+ end
+
+ # walk into config hash. verify specified file exists.
+ def validate_filepath(config, *keys)
+ hash = retrieve_value(config, keys)
+ filepath = hash[:value]
+
+ # return early if we couldn't walk into hash and find a value
+ return false if (filepath.nil?)
+
+ # skip everything if we've got an argument replacement pattern
+ return true if (filepath =~ TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN)
+
+ if (not @file_wrapper.exist?(filepath))
+
+ # See if we can deal with it internally.
+ if GENERATED_DIR_PATH.include?(filepath)
+ # we already made this directory before let's make it again.
+ FileUtils.mkdir_p File.join(File.dirname(__FILE__), filepath)
+ @stream_wrapper.stderr_puts("WARNING: Generated filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist on disk. Recreating")
+
+ else
+ # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator
+ @stream_wrapper.stderr_puts("ERROR: Config filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist on disk.")
+ return false
+ end
+ end
+
+ return true
+ end
+
+ # walk into config hash. verify specified file exists.
+ def validate_executable_filepath(config, *keys)
+ exe_extension = config[:extension][:executable]
+ hash = retrieve_value(config, keys)
+ filepath = hash[:value]
+
+ # return early if we couldn't walk into hash and find a value
+ return false if (filepath.nil?)
+
+ # skip everything if we've got an argument replacement pattern
+ return true if (filepath =~ TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN)
+
+ # if there's no path included, verify file exists somewhere in system search paths
+ if (not filepath.include?('/'))
+ exists = false
+
+ @system_wrapper.search_paths.each do |path|
+ if (@file_wrapper.exist?( File.join(path, filepath)) )
+ exists = true
+ break
+ end
+
+ if (@file_wrapper.exist?( (File.join(path, filepath)).ext( exe_extension ) ))
+ exists = true
+ break
+ elsif (@system_wrapper.windows? and @file_wrapper.exist?( (File.join(path, filepath)).ext( EXTENSION_WIN_EXE ) ))
+ exists = true
+ break
+ end
+ end
+
+ if (not exists)
+ # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator
+ @stream_wrapper.stderr_puts("ERROR: Config filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist in system search paths.")
+ return false
+ end
+
+ # if there is a path included, check that explicit filepath exists
+ else
+ if (not @file_wrapper.exist?(filepath))
+ # no verbosity checking since this is lowest level anyhow & verbosity checking depends on configurator
+ @stream_wrapper.stderr_puts("ERROR: Config filepath #{format_key_sequence(keys, hash[:depth])}['#{filepath}'] does not exist on disk.")
+ return false
+ end
+ end
+
+ return true
+ end
+
+ def validate_tool_stderr_redirect(config, tools, tool)
+ redirect = config[tools][tool][:stderr_redirect]
+ if (redirect.class == Symbol)
+ # map constants and force to array of strings for runtime universality across ruby versions
+ if (not StdErrRedirect.constants.map{|constant| constant.to_s}.include?(redirect.to_s.upcase))
+ error = "ERROR: [:#{tools}][:#{tool}][:stderr_redirect][:#{redirect}] is not a recognized option " +
+ "{#{StdErrRedirect.constants.map{|constant| ':' + constant.to_s.downcase}.join(', ')}}."
+ @stream_wrapper.stderr_puts(error)
+ return false
+ end
+ end
+
+ return true
+ end
+
+ private #########################################
+
+
+ def retrieve_value(config, keys)
+ value = nil
+ hash = config
+ depth = 0
+
+ # walk into hash & extract value at requested key sequence
+ keys.each do |symbol|
+ depth += 1
+ if (not hash[symbol].nil?)
+ hash = hash[symbol]
+ value = hash
+ else
+ value = nil
+ break
+ end
+ end
+
+ return {:value => value, :depth => depth}
+ end
+
+
+ def format_key_sequence(keys, depth)
+ walked_keys = keys.slice(0, depth)
+ formatted_keys = walked_keys.map{|key| "[:#{key.to_s}]"}
+
+ return formatted_keys.join
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/constants.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/constants.rb
new file mode 100755
index 00000000..993ce8db
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/constants.rb
@@ -0,0 +1,97 @@
+
+class Verbosity
+ SILENT = 0 # as silent as possible (though there are some messages that must be spit out)
+ ERRORS = 1 # only errors
+ COMPLAIN = 2 # spit out errors and warnings/notices
+ NORMAL = 3 # errors, warnings/notices, standard status messages
+ OBNOXIOUS = 4 # all messages including extra verbose output (used for lite debugging / verification)
+ DEBUG = 5 # special extra verbose output for hardcore debugging
+end
+
+
+class TestResultsSanityChecks
+ NONE = 0 # no sanity checking of test results
+ NORMAL = 1 # perform non-problematic checks
+ THOROUGH = 2 # perform checks that require inside knowledge of system workings
+end
+
+
+class StdErrRedirect
+ NONE = :none
+ AUTO = :auto
+ WIN = :win
+ UNIX = :unix
+ TCSH = :tcsh
+end
+
+
+class BackgroundExec
+ NONE = :none
+ AUTO = :auto
+ WIN = :win
+ UNIX = :unix
+end
+
+unless defined?(PROJECT_ROOT)
+ PROJECT_ROOT = Dir.pwd()
+end
+
+GENERATED_DIR_PATH = [['vendor', 'ceedling'], 'src', "test", ['test', 'support'], 'build'].each{|p| File.join(*p)}
+
+EXTENSION_WIN_EXE = '.exe'
+EXTENSION_NONWIN_EXE = '.out'
+
+
+CEXCEPTION_ROOT_PATH = 'c_exception'
+CEXCEPTION_LIB_PATH = "#{CEXCEPTION_ROOT_PATH}/lib"
+CEXCEPTION_C_FILE = 'CException.c'
+CEXCEPTION_H_FILE = 'CException.h'
+
+UNITY_ROOT_PATH = 'unity'
+UNITY_LIB_PATH = "#{UNITY_ROOT_PATH}/src"
+UNITY_C_FILE = 'unity.c'
+UNITY_H_FILE = 'unity.h'
+UNITY_INTERNALS_H_FILE = 'unity_internals.h'
+
+CMOCK_ROOT_PATH = 'cmock'
+CMOCK_LIB_PATH = "#{CMOCK_ROOT_PATH}/src"
+CMOCK_C_FILE = 'cmock.c'
+CMOCK_H_FILE = 'cmock.h'
+
+
+DEFAULT_CEEDLING_MAIN_PROJECT_FILE = 'project.yml' unless defined?(DEFAULT_CEEDLING_MAIN_PROJECT_FILE) # main project file
+DEFAULT_CEEDLING_USER_PROJECT_FILE = 'user.yml' unless defined?(DEFAULT_CEEDLING_USER_PROJECT_FILE) # supplemental user config file
+
+INPUT_CONFIGURATION_CACHE_FILE = 'input.yml' unless defined?(INPUT_CONFIGURATION_CACHE_FILE) # input configuration file dump
+DEFINES_DEPENDENCY_CACHE_FILE = 'defines_dependency.yml' unless defined?(DEFINES_DEPENDENCY_CACHE_FILE) # preprocessor definitions for files
+
+TEST_ROOT_NAME = 'test' unless defined?(TEST_ROOT_NAME)
+TEST_TASK_ROOT = TEST_ROOT_NAME + ':' unless defined?(TEST_TASK_ROOT)
+TEST_SYM = TEST_ROOT_NAME.to_sym unless defined?(TEST_SYM)
+
+RELEASE_ROOT_NAME = 'release' unless defined?(RELEASE_ROOT_NAME)
+RELEASE_TASK_ROOT = RELEASE_ROOT_NAME + ':' unless defined?(RELEASE_TASK_ROOT)
+RELEASE_SYM = RELEASE_ROOT_NAME.to_sym unless defined?(RELEASE_SYM)
+
+REFRESH_ROOT_NAME = 'refresh' unless defined?(REFRESH_ROOT_NAME)
+REFRESH_TASK_ROOT = REFRESH_ROOT_NAME + ':' unless defined?(REFRESH_TASK_ROOT)
+REFRESH_SYM = REFRESH_ROOT_NAME.to_sym unless defined?(REFRESH_SYM)
+
+UTILS_ROOT_NAME = 'utils' unless defined?(UTILS_ROOT_NAME)
+UTILS_TASK_ROOT = UTILS_ROOT_NAME + ':' unless defined?(UTILS_TASK_ROOT)
+UTILS_SYM = UTILS_ROOT_NAME.to_sym unless defined?(UTILS_SYM)
+
+OPERATION_COMPILE_SYM = :compile unless defined?(OPERATION_COMPILE_SYM)
+OPERATION_ASSEMBLE_SYM = :assemble unless defined?(OPERATION_ASSEMBLE_SYM)
+OPERATION_LINK_SYM = :link unless defined?(OPERATION_LINK_SYM)
+
+
+RUBY_STRING_REPLACEMENT_PATTERN = /#\{.+\}/
+RUBY_EVAL_REPLACEMENT_PATTERN = /^\{(.+)\}$/
+TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN = /(\$\{(\d+)\})/
+TEST_STDOUT_STATISTICS_PATTERN = /\n-+\s*(\d+)\s+Tests\s+(\d+)\s+Failures\s+(\d+)\s+Ignored\s+(OK|FAIL)\s*/i
+
+NULL_FILE_PATH = '/dev/null'
+
+TESTS_BASE_PATH = TEST_ROOT_NAME
+RELEASE_BASE_PATH = RELEASE_ROOT_NAME
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/defaults.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/defaults.rb
new file mode 100755
index 00000000..9e391fa0
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/defaults.rb
@@ -0,0 +1,418 @@
+require 'ceedling/constants'
+require 'ceedling/system_wrapper'
+require 'ceedling/file_path_utils'
+
+#this should be defined already, but not always during system specs
+CEEDLING_VENDOR = File.expand_path(File.dirname(__FILE__) + '/../../vendor') unless defined? CEEDLING_VENDOR
+CEEDLING_PLUGINS = [] unless defined? CEEDLING_PLUGINS
+
+DEFAULT_TEST_COMPILER_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_test_compiler'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze,
+ {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze,
+ "-DGNU_COMPILER".freeze,
+ "-g".freeze,
+ "-c \"${1}\"".freeze,
+ "-o \"${2}\"".freeze,
+ # gcc's list file output options are complex; no use of ${3} parameter in default config
+ "-MMD".freeze,
+ "-MF \"${4}\"".freeze,
+ ].freeze
+ }
+
+DEFAULT_TEST_LINKER_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_test_linker'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ "\"${1}\"".freeze,
+ "-o \"${2}\"".freeze,
+ "".freeze,
+ "${4}".freeze
+ ].freeze
+ }
+
+DEFAULT_TEST_FIXTURE_TOOL = {
+ :executable => '${1}'.freeze,
+ :name => 'default_test_fixture'.freeze,
+ :stderr_redirect => StdErrRedirect::AUTO.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [].freeze
+ }
+
+DEFAULT_TEST_INCLUDES_PREPROCESSOR_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_test_includes_preprocessor'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ '-E'.freeze, # OSX clang
+ '-MM'.freeze,
+ '-MG'.freeze,
+ # avoid some possibility of deep system lib header file complications by omitting vendor paths
+ # if cpp is run on *nix system, escape spaces in paths; if cpp on windows just use the paths collection as is
+ # {"-I\"$\"" => "{SystemWrapper.windows? ? COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE : COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE.map{|path| path.gsub(\/ \/, \'\\\\ \') }}"}.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze,
+ {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze,
+ {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze,
+ "-DGNU_COMPILER".freeze, # OSX clang
+ '-w'.freeze,
+ # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX
+ "\"${1}\"".freeze
+ ].freeze
+ }
+
+DEFAULT_TEST_FILE_PREPROCESSOR_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_test_file_preprocessor'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ '-E'.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze,
+ {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze,
+ {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze,
+ "-DGNU_COMPILER".freeze,
+ # '-nostdinc'.freeze, # disabled temporarily due to stdio access violations on OSX
+ "\"${1}\"".freeze,
+ "-o \"${2}\"".freeze
+ ].freeze
+ }
+
+# Disable the -MD flag for OSX LLVM Clang, since unsupported
+if RUBY_PLATFORM =~ /darwin/ && `gcc --version 2> /dev/null` =~ /Apple LLVM version .* \(clang/m # OSX w/LLVM Clang
+ MD_FLAG = '' # Clang doesn't support the -MD flag
+else
+ MD_FLAG = '-MD'
+end
+
+DEFAULT_TEST_DEPENDENCIES_GENERATOR_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_test_dependencies_generator'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ '-E'.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR'}.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE'}.freeze,
+ {"-D$" => 'COLLECTION_DEFINES_TEST_AND_VENDOR'}.freeze,
+ {"-D$" => 'DEFINES_TEST_PREPROCESS'}.freeze,
+ "-DGNU_COMPILER".freeze,
+ "-MT \"${3}\"".freeze,
+ '-MM'.freeze,
+ MD_FLAG.freeze,
+ '-MG'.freeze,
+ "-MF \"${2}\"".freeze,
+ "-c \"${1}\"".freeze,
+ # '-nostdinc'.freeze,
+ ].freeze
+ }
+
+DEFAULT_RELEASE_DEPENDENCIES_GENERATOR_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_release_dependencies_generator'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ '-E'.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR'}.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE'}.freeze,
+ {"-D$" => 'COLLECTION_DEFINES_RELEASE_AND_VENDOR'}.freeze,
+ {"-D$" => 'DEFINES_RELEASE_PREPROCESS'}.freeze,
+ "-DGNU_COMPILER".freeze,
+ "-MT \"${3}\"".freeze,
+ '-MM'.freeze,
+ MD_FLAG.freeze,
+ '-MG'.freeze,
+ "-MF \"${2}\"".freeze,
+ "-c \"${1}\"".freeze,
+ # '-nostdinc'.freeze,
+ ].freeze
+ }
+
+
+DEFAULT_RELEASE_COMPILER_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_release_compiler'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR'}.freeze,
+ {"-I\"$\"" => 'COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE'}.freeze,
+ {"-D$" => 'COLLECTION_DEFINES_RELEASE_AND_VENDOR'}.freeze,
+ "-DGNU_COMPILER".freeze,
+ "-c \"${1}\"".freeze,
+ "-o \"${2}\"".freeze,
+ # gcc's list file output options are complex; no use of ${3} parameter in default config
+ "-MMD".freeze,
+ "-MF \"${4}\"".freeze,
+ ].freeze
+ }
+
+DEFAULT_RELEASE_ASSEMBLER_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('as').freeze,
+ :name => 'default_release_assembler'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ {"-I\"$\"" => 'COLLECTION_PATHS_SOURCE_AND_INCLUDE'}.freeze,
+ "\"${1}\"".freeze,
+ "-o \"${2}\"".freeze,
+ ].freeze
+ }
+
+DEFAULT_RELEASE_LINKER_TOOL = {
+ :executable => FilePathUtils.os_executable_ext('gcc').freeze,
+ :name => 'default_release_linker'.freeze,
+ :stderr_redirect => StdErrRedirect::NONE.freeze,
+ :background_exec => BackgroundExec::NONE.freeze,
+ :optional => false.freeze,
+ :arguments => [
+ "\"${1}\"".freeze,
+ "-o \"${2}\"".freeze,
+ "".freeze,
+ "${4}".freeze
+ ].freeze
+ }
+
+
+DEFAULT_TOOLS_TEST = {
+ :tools => {
+ :test_compiler => DEFAULT_TEST_COMPILER_TOOL,
+ :test_linker => DEFAULT_TEST_LINKER_TOOL,
+ :test_fixture => DEFAULT_TEST_FIXTURE_TOOL,
+ }
+ }
+
+DEFAULT_TOOLS_TEST_PREPROCESSORS = {
+ :tools => {
+ :test_includes_preprocessor => DEFAULT_TEST_INCLUDES_PREPROCESSOR_TOOL,
+ :test_file_preprocessor => DEFAULT_TEST_FILE_PREPROCESSOR_TOOL,
+ }
+ }
+
+DEFAULT_TOOLS_TEST_DEPENDENCIES = {
+ :tools => {
+ :test_dependencies_generator => DEFAULT_TEST_DEPENDENCIES_GENERATOR_TOOL,
+ }
+ }
+
+
+DEFAULT_TOOLS_RELEASE = {
+ :tools => {
+ :release_compiler => DEFAULT_RELEASE_COMPILER_TOOL,
+ :release_linker => DEFAULT_RELEASE_LINKER_TOOL,
+ }
+ }
+
+DEFAULT_TOOLS_RELEASE_ASSEMBLER = {
+ :tools => {
+ :release_assembler => DEFAULT_RELEASE_ASSEMBLER_TOOL,
+ }
+ }
+
+DEFAULT_TOOLS_RELEASE_DEPENDENCIES = {
+ :tools => {
+ :release_dependencies_generator => DEFAULT_RELEASE_DEPENDENCIES_GENERATOR_TOOL,
+ }
+ }
+
+
+DEFAULT_RELEASE_TARGET_NAME = 'project'
+
+DEFAULT_CEEDLING_CONFIG = {
+ :project => {
+ # :build_root must be set by user
+ :use_exceptions => true,
+ :use_mocks => true,
+ :compile_threads => 1,
+ :test_threads => 1,
+ :use_test_preprocessor => false,
+ :use_deep_dependencies => false,
+ :generate_deep_dependencies => true, # only applicable if use_deep_dependencies is true
+ :test_file_prefix => 'test_',
+ :options_paths => [],
+ :release_build => false,
+ },
+
+ :release_build => {
+ # :output is set while building configuration -- allows smart default system-dependent file extension handling
+ :use_assembly => false,
+ :artifacts => [],
+ },
+
+ :paths => {
+ :test => [], # must be populated by user
+ :source => [], # must be populated by user
+ :support => [],
+ :include => [],
+ :test_toolchain_include => [],
+ :release_toolchain_include => [],
+ },
+
+ :files => {
+ :test => [],
+ :source => [],
+ :assembly => [],
+ :support => [],
+ :include => [],
+ },
+
+ # unlike other top-level entries, environment's value is an array to preserve order
+ :environment => [
+ # when evaluated, this provides wider text field for rake task comments
+ {:rake_columns => '120'},
+ ],
+
+ :defines => {
+ :test => [],
+ :test_preprocess => [],
+ :release => [],
+ :release_preprocess => [],
+ :use_test_definition => false,
+ },
+
+ :libraries => {
+ :test => [],
+ :test_preprocess => [],
+ :release => [],
+ :release_preprocess => [],
+ },
+
+ :flags => {},
+
+ :extension => {
+ :header => '.h',
+ :source => '.c',
+ :assembly => '.s',
+ :object => '.o',
+ :executable => ( SystemWrapper.windows? ? EXTENSION_WIN_EXE : EXTENSION_NONWIN_EXE ),
+ :map => '.map',
+ :list => '.lst',
+ :testpass => '.pass',
+ :testfail => '.fail',
+ :dependencies => '.d',
+ },
+
+ :unity => {
+ :vendor_path => CEEDLING_VENDOR,
+ :defines => []
+ },
+
+ :cmock => {
+ :vendor_path => CEEDLING_VENDOR,
+ :defines => [],
+ :includes => []
+ },
+
+ :cexception => {
+ :vendor_path => CEEDLING_VENDOR,
+ :defines => []
+ },
+
+ :test_runner => {
+ :includes => [],
+ :file_suffix => '_runner',
+ },
+
+ # all tools populated while building up config structure
+ :tools => {},
+
+ # empty argument lists for default tools
+ # (these can be overridden in project file to add arguments to tools without totally redefining tools)
+ :test_compiler => { :arguments => [] },
+ :test_linker => { :arguments => [] },
+ :test_fixture => {
+ :arguments => [],
+ :link_objects => [], # compiled object files to always be linked in (e.g. cmock.o if using mocks)
+ },
+ :test_includes_preprocessor => { :arguments => [] },
+ :test_file_preprocessor => { :arguments => [] },
+ :test_dependencies_generator => { :arguments => [] },
+ :release_compiler => { :arguments => [] },
+ :release_linker => { :arguments => [] },
+ :release_assembler => { :arguments => [] },
+ :release_dependencies_generator => { :arguments => [] },
+
+ :plugins => {
+ :load_paths => CEEDLING_PLUGINS,
+ :enabled => [],
+ }
+ }.freeze
+
+
+DEFAULT_TESTS_RESULTS_REPORT_TEMPLATE = %q{
+% ignored = hash[:results][:counts][:ignored]
+% failed = hash[:results][:counts][:failed]
+% stdout_count = hash[:results][:counts][:stdout]
+% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '')
+% banner_width = 25 + header_prepend.length # widest message
+
+% if (stdout_count > 0)
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'TEST OUTPUT')%>
+% hash[:results][:stdout].each do |string|
+% string[:collection].each do |item|
+<%=string[:source][:path]%><%=File::SEPARATOR%><%=string[:source][:file]%>: "<%=item%>"
+% end
+% end
+
+% end
+% if (ignored > 0)
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'IGNORED TEST SUMMARY')%>
+% hash[:results][:ignores].each do |ignore|
+% ignore[:collection].each do |item|
+<%=ignore[:source][:path]%><%=File::SEPARATOR%><%=ignore[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%>
+% if (item[:message].length > 0)
+: "<%=item[:message]%>"
+% else
+<%="\n"%>
+% end
+% end
+% end
+
+% end
+% if (failed > 0)
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'FAILED TEST SUMMARY')%>
+% hash[:results][:failures].each do |failure|
+% failure[:collection].each do |item|
+<%=failure[:source][:path]%><%=File::SEPARATOR%><%=failure[:source][:file]%>:<%=item[:line]%>:<%=item[:test]%>
+% if (item[:message].length > 0)
+: "<%=item[:message]%>"
+% else
+<%="\n"%>
+% end
+% end
+% end
+
+% end
+% total_string = hash[:results][:counts][:total].to_s
+% format_string = "%#{total_string.length}i"
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'OVERALL TEST SUMMARY')%>
+% if (hash[:results][:counts][:total] > 0)
+TESTED: <%=hash[:results][:counts][:total].to_s%>
+PASSED: <%=sprintf(format_string, hash[:results][:counts][:passed])%>
+FAILED: <%=sprintf(format_string, failed)%>
+IGNORED: <%=sprintf(format_string, ignored)%>
+% else
+
+No tests executed.
+% end
+
+}
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/dependinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/dependinator.rb
new file mode 100755
index 00000000..ebd12377
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/dependinator.rb
@@ -0,0 +1,98 @@
+
+class Dependinator
+
+ constructor :configurator, :project_config_manager, :test_includes_extractor, :file_path_utils, :rake_wrapper, :file_wrapper
+
+ def touch_force_rebuild_files
+ @file_wrapper.touch( @configurator.project_test_force_rebuild_filepath )
+ @file_wrapper.touch( @configurator.project_release_force_rebuild_filepath ) if (@configurator.project_release_build)
+ end
+
+
+
+ def load_release_object_deep_dependencies(dependencies_list)
+ dependencies_list.each do |dependencies_file|
+ if File.exists?(dependencies_file)
+ @rake_wrapper.load_dependencies( dependencies_file )
+ end
+ end
+ end
+
+
+ def enhance_release_file_dependencies(files)
+ files.each do |filepath|
+ @rake_wrapper[filepath].enhance( [@configurator.project_release_force_rebuild_filepath] ) if (@project_config_manager.release_config_changed)
+ end
+ end
+
+
+
+ def load_test_object_deep_dependencies(files_list)
+ dependencies_list = @file_path_utils.form_test_dependencies_filelist(files_list)
+ dependencies_list.each do |dependencies_file|
+ if File.exists?(dependencies_file)
+ @rake_wrapper.load_dependencies(dependencies_file)
+ end
+ end
+ end
+
+
+ def enhance_runner_dependencies(runner_filepath)
+ @rake_wrapper[runner_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed ||
+ @project_config_manager.test_defines_changed)
+ end
+
+
+ def enhance_shallow_include_lists_dependencies(include_lists)
+ include_lists.each do |include_list_filepath|
+ @rake_wrapper[include_list_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed ||
+ @project_config_manager.test_defines_changed)
+ end
+ end
+
+
+ def enhance_preprocesed_file_dependencies(files)
+ files.each do |filepath|
+ @rake_wrapper[filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed ||
+ @project_config_manager.test_defines_changed)
+ end
+ end
+
+
+ def enhance_mock_dependencies(mocks_list)
+ # if input configuration or ceedling changes, make sure these guys get rebuilt
+ mocks_list.each do |mock_filepath|
+ @rake_wrapper[mock_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed ||
+ @project_config_manager.test_defines_changed)
+ @rake_wrapper[mock_filepath].enhance( @configurator.cmock_unity_helper ) if (@configurator.cmock_unity_helper)
+ end
+ end
+
+
+ def enhance_dependencies_dependencies(dependencies)
+ dependencies.each do |dependencies_filepath|
+ @rake_wrapper[dependencies_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed ||
+ @project_config_manager.test_defines_changed)
+ end
+ end
+
+
+ def enhance_test_build_object_dependencies(objects)
+ objects.each do |object_filepath|
+ @rake_wrapper[object_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed ||
+ @project_config_manager.test_defines_changed)
+ end
+ end
+
+
+ def enhance_results_dependencies(result_filepath)
+ @rake_wrapper[result_filepath].enhance( [@configurator.project_test_force_rebuild_filepath] ) if (@project_config_manager.test_config_changed ||
+ @project_config_manager.test_defines_changed)
+ end
+
+
+ def setup_test_executable_dependencies(test, objects)
+ @rake_wrapper.create_file_task( @file_path_utils.form_test_executable_filepath(test), objects )
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/erb_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/erb_wrapper.rb
new file mode 100755
index 00000000..8d70b6d2
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/erb_wrapper.rb
@@ -0,0 +1,9 @@
+require 'erb'
+
+class ErbWrapper
+ def generate_file(template, data, output_file)
+ File.open(output_file, "w") do |f|
+ f << ERB.new(template, 0, "<>").result(binding)
+ end
+ end
+end \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder.rb
new file mode 100755
index 00000000..53775b7b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder.rb
@@ -0,0 +1,149 @@
+require 'rubygems'
+require 'rake' # for adding ext() method to string
+require 'thread'
+
+
+class FileFinder
+ SEMAPHORE = Mutex.new
+
+ constructor :configurator, :file_finder_helper, :cacheinator, :file_path_utils, :file_wrapper, :yaml_wrapper
+
+ def prepare_search_sources
+ @all_test_source_and_header_file_collection =
+ @configurator.collection_all_tests +
+ @configurator.collection_all_source +
+ @configurator.collection_all_headers
+ end
+
+
+ def find_header_file(mock_file)
+ header = File.basename(mock_file).sub(/#{@configurator.cmock_mock_prefix}/, '').ext(@configurator.extension_header)
+
+ found_path = @file_finder_helper.find_file_in_collection(header, @configurator.collection_all_headers, :error)
+
+ return found_path
+ end
+
+
+ def find_header_input_for_mock_file(mock_file)
+ found_path = find_header_file(mock_file)
+ mock_input = found_path
+
+ if (@configurator.project_use_test_preprocessor)
+ mock_input = @cacheinator.diff_cached_test_file( @file_path_utils.form_preprocessed_file_filepath( found_path ) )
+ end
+
+ return mock_input
+ end
+
+
+ def find_source_from_test(test, complain)
+ test_prefix = @configurator.project_test_file_prefix
+ source_paths = @configurator.collection_all_source
+
+ source = File.basename(test).sub(/#{test_prefix}/, '')
+
+ # we don't blow up if a test file has no corresponding source file
+ return @file_finder_helper.find_file_in_collection(source, source_paths, complain)
+ end
+
+
+ def find_test_from_runner_path(runner_path)
+ extension_source = @configurator.extension_source
+
+ test_file = File.basename(runner_path).sub(/#{@configurator.test_runner_file_suffix}#{'\\'+extension_source}/, extension_source)
+
+ found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error)
+
+ return found_path
+ end
+
+
+ def find_test_input_for_runner_file(runner_path)
+ found_path = find_test_from_runner_path(runner_path)
+ runner_input = found_path
+
+ if (@configurator.project_use_test_preprocessor)
+ runner_input = @cacheinator.diff_cached_test_file( @file_path_utils.form_preprocessed_file_filepath( found_path ) )
+ end
+
+ return runner_input
+ end
+
+
+ def find_test_from_file_path(file_path)
+ test_file = File.basename(file_path).ext(@configurator.extension_source)
+
+ found_path = @file_finder_helper.find_file_in_collection(test_file, @configurator.collection_all_tests, :error)
+
+ return found_path
+ end
+
+
+ def find_test_or_source_or_header_file(file_path)
+ file = File.basename(file_path)
+ return @file_finder_helper.find_file_in_collection(file, @all_test_source_and_header_file_collection, :error)
+ end
+
+
+ def find_compilation_input_file(file_path, complain=:error, release=false)
+ found_file = nil
+
+ source_file = File.basename(file_path).ext(@configurator.extension_source)
+
+ # We only collect files that already exist when we start up.
+ # FileLists can produce undesired results for dynamically generated files depending on when they're accessed.
+ # So collect mocks and runners separately and right now.
+
+ SEMAPHORE.synchronize {
+
+ if (source_file =~ /#{@configurator.test_runner_file_suffix}/)
+ found_file =
+ @file_finder_helper.find_file_in_collection(
+ source_file,
+ @file_wrapper.directory_listing( File.join(@configurator.project_test_runners_path, '*') ),
+ complain)
+
+ elsif (@configurator.project_use_mocks and (source_file =~ /#{@configurator.cmock_mock_prefix}/))
+ found_file =
+ @file_finder_helper.find_file_in_collection(
+ source_file,
+ @file_wrapper.directory_listing( File.join(@configurator.cmock_mock_path, '*') ),
+ complain)
+
+ elsif release
+ found_file =
+ @file_finder_helper.find_file_in_collection(
+ source_file,
+ @configurator.collection_release_existing_compilation_input,
+ complain)
+ else
+ temp_complain = (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) ? :ignore : complain
+ found_file =
+ @file_finder_helper.find_file_in_collection(
+ source_file,
+ @configurator.collection_all_existing_compilation_input,
+ temp_complain)
+ found_file ||= find_assembly_file(file_path, false) if (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY)
+ end
+ }
+ return found_file
+ end
+
+
+ def find_source_file(file_path, complain)
+ source_file = File.basename(file_path).ext(@configurator.extension_source)
+ return @file_finder_helper.find_file_in_collection(source_file, @configurator.collection_all_source, complain)
+ end
+
+
+ def find_assembly_file(file_path, complain = :error)
+ assembly_file = File.basename(file_path).ext(@configurator.extension_assembly)
+ return @file_finder_helper.find_file_in_collection(assembly_file, @configurator.collection_all_assembly, complain)
+ end
+
+ def find_file_from_list(file_path, file_list, complain)
+ return @file_finder_helper.find_file_in_collection(file_path, file_list, complain)
+ end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder_helper.rb
new file mode 100755
index 00000000..0a31b44b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_finder_helper.rb
@@ -0,0 +1,54 @@
+require 'fileutils'
+require 'ceedling/constants' # for Verbosity enumeration
+
+class FileFinderHelper
+
+ constructor :streaminator
+
+
+ def find_file_in_collection(file_name, file_list, complain, extra_message="")
+ file_to_find = nil
+
+ file_list.each do |item|
+ base_file = File.basename(item)
+
+ # case insensitive comparison
+ if (base_file.casecmp(file_name) == 0)
+ # case sensitive check
+ if (base_file == file_name)
+ file_to_find = item
+ break
+ else
+ blow_up(file_name, "However, a filename having different capitalization was found: '#{item}'.")
+ end
+ end
+
+ end
+
+ case (complain)
+ when :error then blow_up(file_name, extra_message) if (file_to_find.nil?)
+ when :warn then gripe(file_name, extra_message) if (file_to_find.nil?)
+ #when :ignore then
+ end
+
+ return file_to_find
+ end
+
+ private
+
+ def blow_up(file_name, extra_message="")
+ error = "ERROR: Found no file '#{file_name}' in search paths."
+ error += ' ' if (extra_message.length > 0)
+ @streaminator.stderr_puts(error + extra_message, Verbosity::ERRORS)
+ raise
+ end
+
+ def gripe(file_name, extra_message="")
+ warning = "WARNING: Found no file '#{file_name}' in search paths."
+ warning += ' ' if (extra_message.length > 0)
+ @streaminator.stderr_puts(warning + extra_message, Verbosity::COMPLAIN)
+ end
+
+end
+
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_path_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_path_utils.rb
new file mode 100755
index 00000000..607039fd
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_path_utils.rb
@@ -0,0 +1,200 @@
+require 'rubygems'
+require 'rake' # for ext()
+require 'fileutils'
+require 'ceedling/system_wrapper'
+
+# global utility methods (for plugins, project files, etc.)
+def ceedling_form_filepath(destination_path, original_filepath, new_extension=nil)
+ filename = File.basename(original_filepath)
+ filename.replace(filename.ext(new_extension)) if (!new_extension.nil?)
+ return File.join( destination_path.gsub(/\\/, '/'), filename )
+end
+
+class FilePathUtils
+
+ GLOB_MATCHER = /[\*\?\{\}\[\]]/
+
+ constructor :configurator, :file_wrapper
+
+
+ ######### class methods ##########
+
+ # standardize path to use '/' path separator & have no trailing path separator
+ def self.standardize(path)
+ path.strip!
+ path.gsub!(/\\/, '/')
+ path.chomp!('/')
+ return path
+ end
+
+ def self.os_executable_ext(executable)
+ return executable.ext('.exe') if SystemWrapper.windows?
+ return executable
+ end
+
+ # extract directory path from between optional add/subtract aggregation modifiers and up to glob specifiers
+ # note: slightly different than File.dirname in that /files/foo remains /files/foo and does not become /files
+ def self.extract_path(path)
+ path = path.sub(/^(\+|-):/, '')
+
+ # find first occurrence of path separator followed by directory glob specifier: *, ?, {, }, [, ]
+ find_index = (path =~ GLOB_MATCHER)
+
+ # no changes needed (lop off final path separator)
+ return path.chomp('/') if (find_index.nil?)
+
+ # extract up to first glob specifier
+ path = path[0..(find_index-1)]
+
+ # lop off everything up to and including final path separator
+ find_index = path.rindex('/')
+ return path[0..(find_index-1)] if (not find_index.nil?)
+
+ # return string up to first glob specifier if no path separator found
+ return path
+ end
+
+ # return whether the given path is to be aggregated (no aggregation modifier defaults to same as +:)
+ def self.add_path?(path)
+ return (path =~ /^-:/).nil?
+ end
+
+ # get path (and glob) lopping off optional +: / -: prefixed aggregation modifiers
+ def self.extract_path_no_aggregation_operators(path)
+ return path.sub(/^(\+|-):/, '')
+ end
+
+ # all the globs that may be in a path string work fine with one exception;
+ # to recurse through all subdirectories, the glob is dir/**/** but our paths use
+ # convention of only dir/**
+ def self.reform_glob(path)
+ return path if (path =~ /\/\*\*$/).nil?
+ return path + '/**'
+ end
+
+ ######### instance methods ##########
+
+ def form_temp_path(filepath, prefix='')
+ return File.join( @configurator.project_temp_path, prefix + File.basename(filepath) )
+ end
+
+ ### release ###
+ def form_release_build_cache_path(filepath)
+ return File.join( @configurator.project_release_build_cache_path, File.basename(filepath) )
+ end
+
+ def form_release_dependencies_filepath(filepath)
+ return File.join( @configurator.project_release_dependencies_path, File.basename(filepath).ext(@configurator.extension_dependencies) )
+ end
+
+ def form_release_build_c_object_filepath(filepath)
+ return File.join( @configurator.project_release_build_output_c_path, File.basename(filepath).ext(@configurator.extension_object) )
+ end
+
+ def form_release_build_asm_object_filepath(filepath)
+ return File.join( @configurator.project_release_build_output_asm_path, File.basename(filepath).ext(@configurator.extension_object) )
+ end
+
+ def form_release_build_c_objects_filelist(files)
+ return (@file_wrapper.instantiate_file_list(files)).pathmap("#{@configurator.project_release_build_output_c_path}/%n#{@configurator.extension_object}")
+ end
+
+ def form_release_build_asm_objects_filelist(files)
+ return (@file_wrapper.instantiate_file_list(files)).pathmap("#{@configurator.project_release_build_output_asm_path}/%n#{@configurator.extension_object}")
+ end
+
+ def form_release_build_c_list_filepath(filepath)
+ return File.join( @configurator.project_release_build_output_c_path, File.basename(filepath).ext(@configurator.extension_list) )
+ end
+
+ def form_release_dependencies_filelist(files)
+ return (@file_wrapper.instantiate_file_list(files)).pathmap("#{@configurator.project_release_dependencies_path}/%n#{@configurator.extension_dependencies}")
+ end
+
+ ### tests ###
+ def form_test_build_cache_path(filepath)
+ return File.join( @configurator.project_test_build_cache_path, File.basename(filepath) )
+ end
+
+ def form_test_dependencies_filepath(filepath)
+ return File.join( @configurator.project_test_dependencies_path, File.basename(filepath).ext(@configurator.extension_dependencies) )
+ end
+
+ def form_pass_results_filepath(filepath)
+ return File.join( @configurator.project_test_results_path, File.basename(filepath).ext(@configurator.extension_testpass) )
+ end
+
+ def form_fail_results_filepath(filepath)
+ return File.join( @configurator.project_test_results_path, File.basename(filepath).ext(@configurator.extension_testfail) )
+ end
+
+ def form_runner_filepath_from_test(filepath)
+ return File.join( @configurator.project_test_runners_path, File.basename(filepath, @configurator.extension_source)) + @configurator.test_runner_file_suffix + @configurator.extension_source
+ end
+
+ def form_test_filepath_from_runner(filepath)
+ return filepath.sub(/#{TEST_RUNNER_FILE_SUFFIX}/, '')
+ end
+
+ def form_runner_object_filepath_from_test(filepath)
+ return (form_test_build_c_object_filepath(filepath)).sub(/(#{@configurator.extension_object})$/, "#{@configurator.test_runner_file_suffix}\\1")
+ end
+
+ def form_test_build_c_object_filepath(filepath)
+ return File.join( @configurator.project_test_build_output_c_path, File.basename(filepath).ext(@configurator.extension_object) )
+ end
+
+ def form_test_build_asm_object_filepath(filepath)
+ return File.join( @configurator.project_test_build_output_asm_path, File.basename(filepath).ext(@configurator.extension_object) )
+ end
+
+ def form_test_executable_filepath(filepath)
+ return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_executable) )
+ end
+
+ def form_test_build_map_filepath(filepath)
+ return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_map) )
+ end
+
+ def form_test_build_list_filepath(filepath)
+ return File.join( @configurator.project_test_build_output_path, File.basename(filepath).ext(@configurator.extension_list) )
+ end
+
+ def form_preprocessed_file_filepath(filepath)
+ return File.join( @configurator.project_test_preprocess_files_path, File.basename(filepath) )
+ end
+
+ def form_preprocessed_includes_list_filepath(filepath)
+ return File.join( @configurator.project_test_preprocess_includes_path, File.basename(filepath) )
+ end
+
+ def form_test_build_objects_filelist(sources)
+ return (@file_wrapper.instantiate_file_list(sources)).pathmap("#{@configurator.project_test_build_output_c_path}/%n#{@configurator.extension_object}")
+ end
+
+ def form_preprocessed_mockable_headers_filelist(mocks)
+ list = @file_wrapper.instantiate_file_list(mocks)
+ headers = list.map do |file|
+ module_name = File.basename(file).sub(/^#{@configurator.cmock_mock_prefix}/, '').sub(/\.[a-zA-Z]+$/,'')
+ "#{@configurator.project_test_preprocess_files_path}/#{module_name}#{@configurator.extension_header}"
+ end
+ return headers
+ end
+
+ def form_mocks_source_filelist(mocks)
+ list = (@file_wrapper.instantiate_file_list(mocks))
+ sources = list.map{|file| "#{@configurator.cmock_mock_path}/#{file}#{@configurator.extension_source}"}
+ return sources
+ end
+
+ def form_test_dependencies_filelist(files)
+ list = @file_wrapper.instantiate_file_list(files)
+ return list.pathmap("#{@configurator.project_test_dependencies_path}/%n#{@configurator.extension_dependencies}")
+ end
+
+ def form_pass_results_filelist(path, files)
+ list = @file_wrapper.instantiate_file_list(files)
+ return list.pathmap("#{path}/%n#{@configurator.extension_testpass}")
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_utils.rb
new file mode 100755
index 00000000..97e5856f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_utils.rb
@@ -0,0 +1,69 @@
+require 'rubygems'
+require 'rake'
+require 'set'
+require 'fileutils'
+require 'ceedling/file_path_utils'
+
+
+class FileSystemUtils
+
+ constructor :file_wrapper
+
+ # build up path list from input of one or more strings or arrays of (+/-) paths & globs
+ def collect_paths(*paths)
+ raw = [] # all paths and globs
+ plus = Set.new # all paths to expand and add
+ minus = Set.new # all paths to remove from plus set
+
+ # assemble all globs and simple paths, reforming our glob notation to ruby globs
+ paths.each do |paths_container|
+ case (paths_container)
+ when String then raw << (FilePathUtils::reform_glob(paths_container))
+ when Array then paths_container.each {|path| raw << (FilePathUtils::reform_glob(path))}
+ else raise "Don't know how to handle #{paths_container.class}"
+ end
+ end
+
+ # iterate through each path and glob
+ raw.each do |path|
+
+ dirs = [] # container for only (expanded) paths
+
+ # if a glob, expand it and slurp up all non-file paths
+ if path.include?('*')
+ # grab base directory only if globs are snug up to final path separator
+ if (path =~ /\/\*+$/)
+ dirs << FilePathUtils.extract_path(path)
+ end
+
+ # grab expanded sub-directory globs
+ expanded = @file_wrapper.directory_listing( FilePathUtils.extract_path_no_aggregation_operators(path) )
+ expanded.each do |entry|
+ dirs << entry if @file_wrapper.directory?(entry)
+ end
+
+ # else just grab simple path
+ # note: we could just run this through glob expansion but such an
+ # approach doesn't handle a path not yet on disk)
+ else
+ dirs << FilePathUtils.extract_path_no_aggregation_operators(path)
+ end
+
+ # add dirs to the appropriate set based on path aggregation modifier if present
+ FilePathUtils.add_path?(path) ? plus.merge(dirs) : minus.merge(dirs)
+ end
+
+ return (plus - minus).to_a.uniq
+ end
+
+
+ # given a file list, add to it or remove from it
+ def revise_file_list(list, revisions)
+ revisions.each do |revision|
+ # include or exclude file or glob to file list
+ file = FilePathUtils.extract_path_no_aggregation_operators( revision )
+ FilePathUtils.add_path?(revision) ? list.include(file) : list.exclude(file)
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_wrapper.rb
new file mode 100755
index 00000000..807cbd23
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_system_wrapper.rb
@@ -0,0 +1,10 @@
+
+class FileSystemWrapper
+
+ def cd(path)
+ FileUtils.cd path do
+ yield
+ end
+ end
+
+end \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/file_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/file_wrapper.rb
new file mode 100755
index 00000000..1680ca52
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/file_wrapper.rb
@@ -0,0 +1,83 @@
+require 'rubygems'
+require 'rake' # for FileList
+require 'fileutils'
+require 'ceedling/constants'
+
+
+class FileWrapper
+
+ def get_expanded_path(path)
+ return File.expand_path(path)
+ end
+
+ def basename(path, extension=nil)
+ return File.basename(path, extension) if extension
+ return File.basename(path)
+ end
+
+ def exist?(filepath)
+ return true if (filepath == NULL_FILE_PATH)
+ return File.exist?(filepath)
+ end
+
+ def directory?(path)
+ return File.directory?(path)
+ end
+
+ def dirname(path)
+ return File.dirname(path)
+ end
+
+ def directory_listing(glob)
+ return Dir.glob(glob, File::FNM_PATHNAME)
+ end
+
+ def rm_f(filepath, options={})
+ FileUtils.rm_f(filepath, options)
+ end
+
+ def rm_r(filepath, options={})
+ FileUtils.rm_r(filepath, options={})
+ end
+
+ def cp(source, destination, options={})
+ FileUtils.cp(source, destination, options)
+ end
+
+ def compare(from, to)
+ return FileUtils.compare_file(from, to)
+ end
+
+ def open(filepath, flags)
+ File.open(filepath, flags) do |file|
+ yield(file)
+ end
+ end
+
+ def read(filepath)
+ return File.read(filepath)
+ end
+
+ def touch(filepath, options={})
+ FileUtils.touch(filepath, options)
+ end
+
+ def write(filepath, contents, flags='w')
+ File.open(filepath, flags) do |file|
+ file.write(contents)
+ end
+ end
+
+ def readlines(filepath)
+ return File.readlines(filepath)
+ end
+
+ def instantiate_file_list(files=[])
+ return FileList.new(files)
+ end
+
+ def mkdir(folder)
+ return FileUtils.mkdir_p(folder)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/flaginator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/flaginator.rb
new file mode 100755
index 00000000..31d62c46
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/flaginator.rb
@@ -0,0 +1,74 @@
+require 'rubygems'
+require 'rake' # for ext()
+require 'fileutils'
+require 'ceedling/constants'
+
+
+# :flags:
+# :release:
+# :compile:
+# :'test_.+'
+# - -pedantic # add '-pedantic' to every test file
+# :*: # add '-foo' to compilation of all files not main.c
+# - -foo
+# :main: # add '-Wall' to compilation of main.c
+# - -Wall
+# :test:
+# :link:
+# :test_main: # add '--bar --baz' to linking of test_main.exe
+# - --bar
+# - --baz
+
+def partition(hash, &predicate)
+ hash.partition(&predicate).map(&:to_h)
+end
+
+class Flaginator
+
+ constructor :configurator
+
+ def get_flag(hash, file_name)
+ file_key = file_name.to_sym
+
+ # 1. try literals
+ literals, magic = partition(hash) { |k, v| k.to_s =~ /^\w+$/ }
+ return literals[file_key] if literals.include?(file_key)
+
+ any, regex = partition(magic) { |k, v| (k == :'*') || (k == :'.*') } # glob or regex wild card
+
+ # 2. try regexes
+ find_res = regex.find { |k, v| file_name =~ /^#{k.to_s}$/ }
+ return find_res[1] if find_res
+
+ # 3. try anything
+ find_res = any.find { |k, v| file_name =~ /.*/ }
+ return find_res[1] if find_res
+
+ # 4. well, we've tried
+ return []
+ end
+
+ def flag_down( operation, context, file )
+ # create configurator accessor method
+ accessor = ('flags_' + context.to_s).to_sym
+
+ # create simple filename key from whatever filename provided
+ file_name = File.basename( file ).ext('')
+ file_key = File.basename( file ).ext('').to_sym
+
+ # if no entry in configuration for flags for this context, bail out
+ return [] if not @configurator.respond_to?( accessor )
+
+ # get flags sub hash associated with this context
+ flags = @configurator.send( accessor )
+
+ # if operation not represented in flags hash, bail out
+ return [] if not flags.include?( operation )
+
+ # redefine flags to sub hash associated with the operation
+ flags = flags[operation]
+
+ return get_flag(flags, file_name)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator.rb
new file mode 100755
index 00000000..828a0c02
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator.rb
@@ -0,0 +1,183 @@
+require 'ceedling/constants'
+
+class Generator
+
+ constructor :configurator,
+ :generator_helper,
+ :preprocessinator,
+ :cmock_builder,
+ :generator_test_runner,
+ :generator_test_results,
+ :flaginator,
+ :test_includes_extractor,
+ :tool_executor,
+ :file_finder,
+ :file_path_utils,
+ :streaminator,
+ :plugin_manager,
+ :file_wrapper
+
+
+ def generate_shallow_includes_list(context, file)
+ @streaminator.stdout_puts("Generating include list for #{File.basename(file)}...", Verbosity::NORMAL)
+ @preprocessinator.preprocess_shallow_includes(file)
+ end
+
+ def generate_preprocessed_file(context, file)
+ @streaminator.stdout_puts("Preprocessing #{File.basename(file)}...", Verbosity::NORMAL)
+ @preprocessinator.preprocess_file(file)
+ end
+
+ def generate_dependencies_file(tool, context, source, object, dependencies)
+ @streaminator.stdout_puts("Generating dependencies for #{File.basename(source)}...", Verbosity::NORMAL)
+
+ command =
+ @tool_executor.build_command_line(
+ tool,
+ [], # extra per-file command line parameters
+ source,
+ dependencies,
+ object)
+
+ @tool_executor.exec( command[:line], command[:options] )
+ end
+
+ def generate_mock(context, header_filepath)
+ arg_hash = {:header_file => header_filepath, :context => context}
+ @plugin_manager.pre_mock_generate( arg_hash )
+
+ begin
+ @cmock_builder.cmock.setup_mocks( arg_hash[:header_file] )
+ rescue
+ raise
+ ensure
+ @plugin_manager.post_mock_generate( arg_hash )
+ end
+ end
+
+ # test_filepath may be either preprocessed test file or original test file
+ def generate_test_runner(context, test_filepath, runner_filepath)
+ arg_hash = {:context => context, :test_file => test_filepath, :runner_file => runner_filepath}
+ @plugin_manager.pre_runner_generate(arg_hash)
+
+ # collect info we need
+ module_name = File.basename(arg_hash[:test_file])
+ test_cases = @generator_test_runner.find_test_cases( @file_finder.find_test_from_runner_path(runner_filepath) )
+ mock_list = @test_includes_extractor.lookup_raw_mock_list(arg_hash[:test_file])
+
+ @streaminator.stdout_puts("Generating runner for #{module_name}...", Verbosity::NORMAL)
+
+ test_file_includes = [] # Empty list for now, since apparently unused
+
+ # build runner file
+ begin
+ @generator_test_runner.generate(module_name, runner_filepath, test_cases, mock_list, test_file_includes)
+ rescue
+ raise
+ ensure
+ @plugin_manager.post_runner_generate(arg_hash)
+ end
+ end
+
+ def generate_object_file(tool, operation, context, source, object, list='', dependencies='')
+ shell_result = {}
+ arg_hash = {:tool => tool, :operation => operation, :context => context, :source => source, :object => object, :list => list, :dependencies => dependencies}
+ @plugin_manager.pre_compile_execute(arg_hash)
+
+ @streaminator.stdout_puts("Compiling #{File.basename(arg_hash[:source])}...", Verbosity::NORMAL)
+ command =
+ @tool_executor.build_command_line( arg_hash[:tool],
+ @flaginator.flag_down( operation, context, source ),
+ arg_hash[:source],
+ arg_hash[:object],
+ arg_hash[:list],
+ arg_hash[:dependencies])
+
+ @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG)
+
+ begin
+ shell_result = @tool_executor.exec( command[:line], command[:options] )
+ rescue ShellExecutionException => ex
+ shell_result = ex.shell_result
+ raise ex
+ ensure
+ arg_hash[:shell_result] = shell_result
+ @plugin_manager.post_compile_execute(arg_hash)
+ end
+ end
+
+ def generate_executable_file(tool, context, objects, executable, map='', libraries=[])
+ shell_result = {}
+ arg_hash = { :tool => tool,
+ :context => context,
+ :objects => objects,
+ :executable => executable,
+ :map => map,
+ :libraries => libraries
+ }
+
+ @plugin_manager.pre_link_execute(arg_hash)
+
+ @streaminator.stdout_puts("Linking #{File.basename(arg_hash[:executable])}...", Verbosity::NORMAL)
+ command =
+ @tool_executor.build_command_line( arg_hash[:tool],
+ @flaginator.flag_down( OPERATION_LINK_SYM, context, executable ),
+ arg_hash[:objects],
+ arg_hash[:executable],
+ arg_hash[:map],
+ arg_hash[:libraries]
+ )
+ @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG)
+
+ begin
+ shell_result = @tool_executor.exec( command[:line], command[:options] )
+ rescue ShellExecutionException => ex
+ notice = "\n" +
+ "NOTICE: If the linker reports missing symbols, the following may be to blame:\n" +
+ " 1. Test lacks #include statements corresponding to needed source files.\n" +
+ " 2. Project search paths do not contain source files corresponding to #include statements in the test.\n"
+
+ if (@configurator.project_use_mocks)
+ notice += " 3. Test does not #include needed mocks.\n\n"
+ else
+ notice += "\n"
+ end
+
+ @streaminator.stderr_puts(notice, Verbosity::COMPLAIN)
+ shell_result = ex.shell_result
+ raise ''
+ ensure
+ arg_hash[:shell_result] = shell_result
+ @plugin_manager.post_link_execute(arg_hash)
+ end
+ end
+
+ def generate_test_results(tool, context, executable, result)
+ arg_hash = {:tool => tool, :context => context, :executable => executable, :result_file => result}
+ @plugin_manager.pre_test_fixture_execute(arg_hash)
+
+ @streaminator.stdout_puts("Running #{File.basename(arg_hash[:executable])}...", Verbosity::NORMAL)
+
+ # Unity's exit code is equivalent to the number of failed tests, so we tell @tool_executor not to fail out if there are failures
+ # so that we can run all tests and collect all results
+ command = @tool_executor.build_command_line(arg_hash[:tool], [], arg_hash[:executable])
+ @streaminator.stdout_puts("Command: #{command}", Verbosity::DEBUG)
+ command[:options][:boom] = false
+ shell_result = @tool_executor.exec( command[:line], command[:options] )
+
+ #Don't Let The Failure Count Make Us Believe Things Aren't Working
+ shell_result[:exit_code] = 0
+ @generator_helper.test_results_error_handler(executable, shell_result)
+
+ processed = @generator_test_results.process_and_write_results( shell_result,
+ arg_hash[:result_file],
+ @file_finder.find_test_from_file_path(arg_hash[:executable]) )
+
+ arg_hash[:result_file] = processed[:result_file]
+ arg_hash[:results] = processed[:results]
+ arg_hash[:shell_result] = shell_result # for raw output display if no plugins for formatted display
+
+ @plugin_manager.post_test_fixture_execute(arg_hash)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_helper.rb
new file mode 100755
index 00000000..34315609
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_helper.rb
@@ -0,0 +1,40 @@
+require 'ceedling/constants'
+
+
+class GeneratorHelper
+
+ constructor :streaminator
+
+
+ def test_results_error_handler(executable, shell_result)
+ notice = ''
+ error = false
+
+ if (shell_result[:output].nil? or shell_result[:output].strip.empty?)
+ error = true
+ # mirror style of generic tool_executor failure output
+ notice = "\n" +
+ "ERROR: Test executable \"#{File.basename(executable)}\" failed.\n" +
+ "> Produced no output to $stdout.\n"
+ elsif ((shell_result[:output] =~ TEST_STDOUT_STATISTICS_PATTERN).nil?)
+ error = true
+ # mirror style of generic tool_executor failure output
+ notice = "\n" +
+ "ERROR: Test executable \"#{File.basename(executable)}\" failed.\n" +
+ "> Produced no final test result counts in $stdout:\n" +
+ "#{shell_result[:output].strip}\n"
+ end
+
+ if (error)
+ # since we told the tool executor to ignore the exit code, handle it explicitly here
+ notice += "> And exited with status: [#{shell_result[:exit_code]}] (count of failed tests).\n" if (shell_result[:exit_code] != nil)
+ notice += "> And then likely crashed.\n" if (shell_result[:exit_code] == nil)
+
+ notice += "> This is often a symptom of a bad memory access in source or test code.\n\n"
+
+ @streaminator.stderr_puts(notice, Verbosity::COMPLAIN)
+ raise
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results.rb
new file mode 100755
index 00000000..1d0c5201
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results.rb
@@ -0,0 +1,89 @@
+require 'rubygems'
+require 'rake' # for .ext()
+require 'ceedling/constants'
+
+class GeneratorTestResults
+
+ constructor :configurator, :generator_test_results_sanity_checker, :yaml_wrapper
+
+ def process_and_write_results(unity_shell_result, results_file, test_file)
+ output_file = results_file
+
+ results = get_results_structure
+
+ results[:source][:path] = File.dirname(test_file)
+ results[:source][:file] = File.basename(test_file)
+ results[:time] = unity_shell_result[:time] unless unity_shell_result[:time].nil?
+
+ # process test statistics
+ if (unity_shell_result[:output] =~ TEST_STDOUT_STATISTICS_PATTERN)
+ results[:counts][:total] = $1.to_i
+ results[:counts][:failed] = $2.to_i
+ results[:counts][:ignored] = $3.to_i
+ results[:counts][:passed] = (results[:counts][:total] - results[:counts][:failed] - results[:counts][:ignored])
+ end
+
+ # remove test statistics lines
+ output_string = unity_shell_result[:output].sub(TEST_STDOUT_STATISTICS_PATTERN, '')
+
+ output_string.lines do |line|
+ # process unity output
+ case line
+ when /(:IGNORE)/
+ elements = extract_line_elements(line, results[:source][:file])
+ results[:ignores] << elements[0]
+ results[:stdout] << elements[1] if (!elements[1].nil?)
+ when /(:PASS$)/
+ elements = extract_line_elements(line, results[:source][:file])
+ results[:successes] << elements[0]
+ results[:stdout] << elements[1] if (!elements[1].nil?)
+ when /(:FAIL)/
+ elements = extract_line_elements(line, results[:source][:file])
+ results[:failures] << elements[0]
+ results[:stdout] << elements[1] if (!elements[1].nil?)
+ else # collect up all other
+ results[:stdout] << line.chomp
+ end
+ end
+
+ @generator_test_results_sanity_checker.verify(results, unity_shell_result[:exit_code])
+
+ output_file = results_file.ext(@configurator.extension_testfail) if (results[:counts][:failed] > 0)
+
+ @yaml_wrapper.dump(output_file, results)
+
+ return { :result_file => output_file, :result => results }
+ end
+
+ private
+
+ def get_results_structure
+ return {
+ :source => {:path => '', :file => ''},
+ :successes => [],
+ :failures => [],
+ :ignores => [],
+ :counts => {:total => 0, :passed => 0, :failed => 0, :ignored => 0},
+ :stdout => [],
+ :time => 0.0
+ }
+ end
+
+ def extract_line_elements(line, filename)
+ # handle anything preceding filename in line as extra output to be collected
+ stdout = nil
+ stdout_regex = /(.+)#{Regexp.escape(filename)}.+/i
+
+ if (line =~ stdout_regex)
+ stdout = $1.clone
+ line.sub!(/#{Regexp.escape(stdout)}/, '')
+ end
+
+ # collect up test results minus and extra output
+ elements = (line.strip.split(':'))[1..-1]
+
+ return {:test => elements[1], :line => elements[0].to_i, :message => (elements[3..-1].join(':')).strip}, stdout if elements.size >= 3
+ return {:test => '???', :line => -1, :message => nil} #fallback safe option. TODO better handling
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results_sanity_checker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results_sanity_checker.rb
new file mode 100755
index 00000000..0b518325
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_results_sanity_checker.rb
@@ -0,0 +1,65 @@
+require 'rubygems'
+require 'rake' # for ext() method
+require 'ceedling/constants'
+
+
+class GeneratorTestResultsSanityChecker
+
+ constructor :configurator, :streaminator
+
+ def verify(results, unity_exit_code)
+
+ # do no sanity checking if it's disabled
+ return if (@configurator.sanity_checks == TestResultsSanityChecks::NONE)
+ raise "results nil or empty" if results.nil? || results.empty?
+
+ ceedling_ignores_count = results[:ignores].size
+ ceedling_failures_count = results[:failures].size
+ ceedling_tests_summation = (ceedling_ignores_count + ceedling_failures_count + results[:successes].size)
+
+ # Exit code handling is not a sanity check that can always be performed because
+ # command line simulators may or may not pass through Unity's exit code
+ if (@configurator.sanity_checks >= TestResultsSanityChecks::THOROUGH)
+ # many platforms limit exit codes to a maximum of 255
+ if ((ceedling_failures_count != unity_exit_code) and (unity_exit_code < 255))
+ sanity_check_warning(results[:source][:file], "Unity's exit code (#{unity_exit_code}) does not match Ceedling's summation of failed test cases (#{ceedling_failures_count}).")
+ end
+
+ if ((ceedling_failures_count < 255) and (unity_exit_code == 255))
+ sanity_check_warning(results[:source][:file], "Ceedling's summation of failed test cases (#{ceedling_failures_count}) is less than Unity's exit code (255 or more).")
+ end
+ end
+
+ if (ceedling_ignores_count != results[:counts][:ignored])
+ sanity_check_warning(results[:source][:file], "Unity's final ignore count (#{results[:counts][:ignored]}) does not match Ceedling's summation of ignored test cases (#{ceedling_ignores_count}).")
+ end
+
+ if (ceedling_failures_count != results[:counts][:failed])
+ sanity_check_warning(results[:source][:file], "Unity's final fail count (#{results[:counts][:failed]}) does not match Ceedling's summation of failed test cases (#{ceedling_failures_count}).")
+ end
+
+ if (ceedling_tests_summation != results[:counts][:total])
+ sanity_check_warning(results[:source][:file], "Unity's final test count (#{results[:counts][:total]}) does not match Ceedling's summation of all test cases (#{ceedling_tests_summation}).")
+ end
+
+ end
+
+ private
+
+ def sanity_check_warning(file, message)
+ unless defined?(CEEDLING_IGNORE_SANITY_CHECK)
+ notice = "\n" +
+ "ERROR: Internal sanity check for test fixture '#{file.ext(@configurator.extension_executable)}' finds that #{message}\n" +
+ " Possible causes:\n" +
+ " 1. Your test + source dereferenced a null pointer.\n" +
+ " 2. Your test + source indexed past the end of a buffer.\n" +
+ " 3. Your test + source committed a memory access violation.\n" +
+ " 4. Your test fixture produced an exit code of 0 despite execution ending prematurely.\n" +
+ " Sanity check failures of test results are usually a symptom of interrupted test execution.\n\n"
+
+ @streaminator.stderr_puts( notice )
+ raise
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_runner.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_runner.rb
new file mode 100755
index 00000000..6999faf9
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/generator_test_runner.rb
@@ -0,0 +1,56 @@
+
+class GeneratorTestRunner
+
+ constructor :configurator, :file_path_utils, :file_wrapper
+
+ def find_test_cases(test_file)
+
+ #Pull in Unity's Test Runner Generator
+ require 'generate_test_runner.rb'
+ @test_runner_generator ||= UnityTestRunnerGenerator.new( @configurator.get_runner_config )
+
+ if (@configurator.project_use_test_preprocessor)
+
+ #redirect to use the preprocessor file if we're doing that sort of thing
+ pre_test_file = @file_path_utils.form_preprocessed_file_filepath(test_file)
+
+ #actually look for the tests using Unity's test runner generator
+ contents = @file_wrapper.read(pre_test_file)
+ tests_and_line_numbers = @test_runner_generator.find_tests(contents)
+ @test_runner_generator.find_setup_and_teardown(contents)
+
+ #look up the line numbers in the original file
+ source_lines = @file_wrapper.read(test_file).split("\n")
+ source_index = 0;
+ tests_and_line_numbers.size.times do |i|
+ source_lines[source_index..-1].each_with_index do |line, index|
+ if (line =~ /#{tests_and_line_numbers[i][:test]}/)
+ source_index += index
+ tests_and_line_numbers[i][:line_number] = source_index + 1
+ break
+ end
+ end
+ end
+ else
+ #Just look for the tests using Unity's test runner generator
+ contents = @file_wrapper.read(test_file)
+ tests_and_line_numbers = @test_runner_generator.find_tests(contents)
+ @test_runner_generator.find_setup_and_teardown(contents)
+ end
+
+ return tests_and_line_numbers
+ end
+
+ def generate(module_name, runner_filepath, test_cases, mock_list, test_file_includes=[])
+ require 'generate_test_runner.rb'
+
+ #actually build the test runner using Unity's test runner generator
+ #(there is no need to use preprocessor here because we've already looked up test cases and are passing them in here)
+ @test_runner_generator ||= UnityTestRunnerGenerator.new( @configurator.get_runner_config )
+ @test_runner_generator.generate( module_name,
+ runner_filepath,
+ test_cases,
+ mock_list,
+ test_file_includes)
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/loginator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/loginator.rb
new file mode 100755
index 00000000..92276e1d
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/loginator.rb
@@ -0,0 +1,31 @@
+
+class Loginator
+
+ constructor :configurator, :project_file_loader, :project_config_manager, :file_wrapper, :system_wrapper
+
+
+ def setup_log_filepath
+ config_files = []
+ config_files << @project_file_loader.main_file
+ config_files << @project_file_loader.user_file
+ config_files.concat( @project_config_manager.options_files )
+ config_files.compact!
+ config_files.map! { |file| file.ext('') }
+
+ log_name = config_files.join( '_' )
+
+ @project_log_filepath = File.join( @configurator.project_log_path, log_name.ext('.log') )
+ end
+
+
+ def log(string, heading=nil)
+ return if (not @configurator.project_logging)
+
+ output = "\n[#{@system_wrapper.time_now}]"
+ output += " :: #{heading}" if (not heading.nil?)
+ output += "\n#{string.strip}\n"
+
+ @file_wrapper.write(@project_log_filepath, output, 'a')
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/makefile.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/makefile.rb
new file mode 100755
index 00000000..c3d7496d
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/makefile.rb
@@ -0,0 +1,46 @@
+
+# modified version of Rake's provided make-style dependency loader
+# customizations:
+# (1) handles windows drives in paths -- colons don't confuse task demarcation
+# (2) handles spaces in directory paths
+
+module Rake
+
+ # Makefile loader to be used with the import file loader.
+ class MakefileLoader
+
+ # Load the makefile dependencies in +fn+.
+ def load(fn)
+ open(fn) do |mf|
+ lines = mf.read
+ lines.gsub!(/#[^\n]*\n/m, "") # remove comments
+ lines.gsub!(/\\\n/, ' ') # string together line continuations into single line
+ lines.split("\n").each do |line|
+ process_line(line)
+ end
+ end
+ end
+
+ private
+
+ # Process one logical line of makefile data.
+ def process_line(line)
+ # split on presence of task demaractor followed by space (i.e don't get confused by a colon in a win path)
+ file_tasks, args = line.split(/:\s/)
+
+ return if args.nil?
+
+ # split at non-escaped space boundary between files (i.e. escaped spaces in paths are left alone)
+ dependents = args.split(/\b\s+/)
+ # replace escaped spaces and clean up any extra whitespace
+ dependents.map! { |path| path.gsub(/\\ /, ' ').strip }
+
+ file_tasks.strip.split.each do |file_task|
+ file file_task => dependents
+ end
+ end
+ end
+
+ # Install the handler
+ Rake.application.add_loader('mf', MakefileLoader.new)
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/objects.yml b/tinyusb/test/vendor/ceedling/lib/ceedling/objects.yml
new file mode 100755
index 00000000..2e2e9b9d
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/objects.yml
@@ -0,0 +1,310 @@
+
+file_wrapper:
+
+file_system_wrapper:
+
+stream_wrapper:
+
+rake_wrapper:
+
+yaml_wrapper:
+
+system_wrapper:
+
+cmock_builder:
+
+reportinator:
+
+rake_utils:
+ compose:
+ - rake_wrapper
+
+system_utils:
+ compose:
+ - system_wrapper
+
+file_path_utils:
+ compose:
+ - configurator
+ - file_wrapper
+
+file_system_utils:
+ compose: file_wrapper
+
+project_file_loader:
+ compose:
+ - yaml_wrapper
+ - stream_wrapper
+ - system_wrapper
+ - file_wrapper
+
+project_config_manager:
+ compose:
+ - cacheinator
+ - configurator
+ - yaml_wrapper
+ - file_wrapper
+
+cacheinator:
+ compose:
+ - cacheinator_helper
+ - file_path_utils
+ - file_wrapper
+ - yaml_wrapper
+
+cacheinator_helper:
+ compose:
+ - file_wrapper
+ - yaml_wrapper
+
+tool_executor:
+ compose:
+ - configurator
+ - tool_executor_helper
+ - streaminator
+ - system_wrapper
+
+tool_executor_helper:
+ compose:
+ - streaminator
+ - system_utils
+ - system_wrapper
+
+configurator:
+ compose:
+ - configurator_setup
+ - configurator_plugins
+ - configurator_builder
+ - cmock_builder
+ - yaml_wrapper
+ - system_wrapper
+
+configurator_setup:
+ compose:
+ - configurator_builder
+ - configurator_validator
+ - configurator_plugins
+ - stream_wrapper
+
+configurator_plugins:
+ compose:
+ - stream_wrapper
+ - file_wrapper
+ - system_wrapper
+
+configurator_validator:
+ compose:
+ - file_wrapper
+ - stream_wrapper
+ - system_wrapper
+
+configurator_builder:
+ compose:
+ - file_system_utils
+ - file_wrapper
+ - system_wrapper
+
+loginator:
+ compose:
+ - configurator
+ - project_file_loader
+ - project_config_manager
+ - file_wrapper
+ - system_wrapper
+
+streaminator:
+ compose:
+ - streaminator_helper
+ - verbosinator
+ - loginator
+ - stream_wrapper
+
+streaminator_helper:
+
+setupinator:
+
+plugin_builder:
+
+plugin_manager:
+ compose:
+ - configurator
+ - plugin_manager_helper
+ - streaminator
+ - reportinator
+ - system_wrapper
+
+plugin_manager_helper:
+
+plugin_reportinator:
+ compose:
+ - plugin_reportinator_helper
+ - plugin_manager
+ - reportinator
+
+plugin_reportinator_helper:
+ compose:
+ - configurator
+ - streaminator
+ - yaml_wrapper
+ - file_wrapper
+
+verbosinator:
+ compose: configurator
+
+file_finder:
+ compose:
+ - configurator
+ - file_finder_helper
+ - cacheinator
+ - file_path_utils
+ - file_wrapper
+ - yaml_wrapper
+
+file_finder_helper:
+ compose: streaminator
+
+test_includes_extractor:
+ compose:
+ - configurator
+ - yaml_wrapper
+ - file_wrapper
+
+task_invoker:
+ compose:
+ - dependinator
+ - rake_utils
+ - rake_wrapper
+ - project_config_manager
+
+flaginator:
+ compose:
+ - configurator
+
+generator:
+ compose:
+ - configurator
+ - generator_helper
+ - preprocessinator
+ - cmock_builder
+ - generator_test_runner
+ - generator_test_results
+ - flaginator
+ - test_includes_extractor
+ - tool_executor
+ - file_finder
+ - file_path_utils
+ - streaminator
+ - plugin_manager
+ - file_wrapper
+
+generator_helper:
+ compose:
+ - streaminator
+
+generator_test_results:
+ compose:
+ - configurator
+ - generator_test_results_sanity_checker
+ - yaml_wrapper
+
+generator_test_results_sanity_checker:
+ compose:
+ - configurator
+ - streaminator
+
+generator_test_runner:
+ compose:
+ - configurator
+ - file_path_utils
+ - file_wrapper
+
+dependinator:
+ compose:
+ - configurator
+ - project_config_manager
+ - test_includes_extractor
+ - file_path_utils
+ - rake_wrapper
+ - file_wrapper
+
+preprocessinator:
+ compose:
+ - preprocessinator_helper
+ - preprocessinator_includes_handler
+ - preprocessinator_file_handler
+ - task_invoker
+ - file_path_utils
+ - yaml_wrapper
+
+preprocessinator_helper:
+ compose:
+ - configurator
+ - test_includes_extractor
+ - task_invoker
+ - file_finder
+ - file_path_utils
+
+preprocessinator_includes_handler:
+ compose:
+ - configurator
+ - tool_executor
+ - task_invoker
+ - file_path_utils
+ - yaml_wrapper
+ - file_wrapper
+
+preprocessinator_file_handler:
+ compose:
+ - preprocessinator_extractor
+ - configurator
+ - tool_executor
+ - file_path_utils
+ - file_wrapper
+
+preprocessinator_extractor:
+
+test_invoker:
+ compose:
+ - configurator
+ - test_invoker_helper
+ - plugin_manager
+ - streaminator
+ - preprocessinator
+ - task_invoker
+ - dependinator
+ - project_config_manager
+ - build_invoker_utils
+ - file_path_utils
+ - file_wrapper
+
+test_invoker_helper:
+ compose:
+ - configurator
+ - task_invoker
+ - test_includes_extractor
+ - file_finder
+ - file_path_utils
+ - file_wrapper
+
+release_invoker:
+ compose:
+ - configurator
+ - release_invoker_helper
+ - build_invoker_utils
+ - dependinator
+ - task_invoker
+ - file_path_utils
+ - file_wrapper
+
+release_invoker_helper:
+ compose:
+ - configurator
+ - dependinator
+ - task_invoker
+
+build_invoker_utils:
+ compose:
+ - configurator
+ - streaminator
+
+erb_wrapper:
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/par_map.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/par_map.rb
new file mode 100755
index 00000000..98198a2c
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/par_map.rb
@@ -0,0 +1,19 @@
+
+
+def par_map(n, things, &block)
+ queue = Queue.new
+ things.each { |thing| queue << thing }
+ threads = (1..n).collect do
+ Thread.new do
+ begin
+ while true
+ yield queue.pop(true)
+ end
+ rescue ThreadError
+
+ end
+ end
+ end
+ threads.each { |t| t.join }
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin.rb
new file mode 100755
index 00000000..f20b3a3b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin.rb
@@ -0,0 +1,80 @@
+
+class String
+ # reformat a multiline string to have given number of whitespace columns;
+ # helpful for formatting heredocs
+ def left_margin(margin=0)
+ non_whitespace_column = 0
+ new_lines = []
+
+ # find first line with non-whitespace and count left columns of whitespace
+ self.each_line do |line|
+ if (line =~ /^\s*\S/)
+ non_whitespace_column = $&.length - 1
+ break
+ end
+ end
+
+ # iterate through each line, chopping off leftmost whitespace columns and add back the desired whitespace margin
+ self.each_line do |line|
+ columns = []
+ margin.times{columns << ' '}
+ # handle special case of line being narrower than width to be lopped off
+ if (non_whitespace_column < line.length)
+ new_lines << "#{columns.join}#{line[non_whitespace_column..-1]}"
+ else
+ new_lines << "\n"
+ end
+ end
+
+ return new_lines.join
+ end
+end
+
+class Plugin
+ attr_reader :name, :environment
+ attr_accessor :plugin_objects
+
+ def initialize(system_objects, name)
+ @environment = []
+ @ceedling = system_objects
+ @name = name
+ self.setup
+ end
+
+ def setup; end
+
+ # mock generation
+ def pre_mock_generate(arg_hash); end
+ def post_mock_generate(arg_hash); end
+
+ # test runner generation
+ def pre_runner_generate(arg_hash); end
+ def post_runner_generate(arg_hash); end
+
+ # compilation (test or source)
+ def pre_compile_execute(arg_hash); end
+ def post_compile_execute(arg_hash); end
+
+ # linking (test or source)
+ def pre_link_execute(arg_hash); end
+ def post_link_execute(arg_hash); end
+
+ # test fixture execution
+ def pre_test_fixture_execute(arg_hash); end
+ def post_test_fixture_execute(arg_hash); end
+
+ # test task
+ def pre_test(test); end
+ def post_test(test); end
+
+ # release task
+ def pre_release; end
+ def post_release; end
+
+ # whole shebang (any use of Ceedling)
+ def pre_build; end
+ def post_build; end
+
+ def summary; end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_builder.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_builder.rb
new file mode 100755
index 00000000..1269141f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_builder.rb
@@ -0,0 +1,53 @@
+require 'ceedling/plugin'
+
+class PluginBuilder
+
+ attr_accessor :plugin_objects
+
+ def construct_plugin(plugin_name, object_map_yaml, system_objects)
+ # @streaminator.stdout_puts("Constructing plugin #{plugin_name}...", Verbosity::OBNOXIOUS)
+ object_map = {}
+ @plugin_objects = {}
+ @system_objects = system_objects
+
+ if object_map_yaml
+ @object_map = YAML.load(object_map_yaml)
+ @object_map.each_key do |obj|
+ construct_object(obj)
+ end
+ else
+ raise "Invalid object map for plugin #{plugin_name}!"
+ end
+
+ return @plugin_objects
+ end
+
+ private
+
+ def camelize(underscored_name)
+ return underscored_name.gsub(/(_|^)([a-z0-9])/) {$2.upcase}
+ end
+
+ def construct_object(obj)
+ if @plugin_objects[obj].nil?
+ if @object_map[obj] && @object_map[obj]['compose']
+ @object_map[obj]['compose'].each do |dep|
+ construct_object(dep)
+ end
+ end
+ build_object(obj)
+ end
+ end
+
+ def build_object(new_object)
+ if @plugin_objects[new_object.to_sym].nil?
+ # @streaminator.stdout_puts("Building plugin object #{new_object}", Verbosity::OBNOXIOUS)
+ require new_object
+ class_name = camelize(new_object)
+ new_instance = eval("#{class_name}.new(@system_objects, class_name.to_s)")
+ new_instance.plugin_objects = @plugin_objects
+ @plugin_objects[new_object.to_sym] = new_instance
+ end
+ end
+
+end \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager.rb
new file mode 100755
index 00000000..0468f2fc
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager.rb
@@ -0,0 +1,107 @@
+require 'ceedling/constants'
+
+class PluginManager
+
+ constructor :configurator, :plugin_manager_helper, :streaminator, :reportinator, :system_wrapper
+
+ def setup
+ @build_fail_registry = []
+ @plugin_objects = [] # so we can preserve order
+ end
+
+ def load_plugin_scripts(script_plugins, system_objects)
+ environment = []
+
+ script_plugins.each do |plugin|
+ # protect against instantiating object multiple times due to processing config multiple times (option files, etc)
+ next if (@plugin_manager_helper.include?(@plugin_objects, plugin))
+ begin
+ @system_wrapper.require_file( "#{plugin}.rb" )
+ object = @plugin_manager_helper.instantiate_plugin_script( camelize(plugin), system_objects, plugin )
+ @plugin_objects << object
+ environment += object.environment
+
+ # add plugins to hash of all system objects
+ system_objects[plugin.downcase.to_sym] = object
+ rescue
+ puts "Exception raised while trying to load plugin: #{plugin}"
+ raise
+ end
+ end
+
+ yield( { :environment => environment } ) if (environment.size > 0)
+ end
+
+ def plugins_failed?
+ return (@build_fail_registry.size > 0)
+ end
+
+ def print_plugin_failures
+ if (@build_fail_registry.size > 0)
+ report = @reportinator.generate_banner('BUILD FAILURE SUMMARY')
+
+ @build_fail_registry.each do |failure|
+ report += "#{' - ' if (@build_fail_registry.size > 1)}#{failure}\n"
+ end
+
+ report += "\n"
+
+ @streaminator.stderr_puts(report, Verbosity::ERRORS)
+ end
+ end
+
+ def register_build_failure(message)
+ @build_fail_registry << message if (message and not message.empty?)
+ end
+
+ #### execute all plugin methods ####
+
+ def pre_mock_generate(arg_hash); execute_plugins(:pre_mock_generate, arg_hash); end
+ def post_mock_generate(arg_hash); execute_plugins(:post_mock_generate, arg_hash); end
+
+ def pre_runner_generate(arg_hash); execute_plugins(:pre_runner_generate, arg_hash); end
+ def post_runner_generate(arg_hash); execute_plugins(:post_runner_generate, arg_hash); end
+
+ def pre_compile_execute(arg_hash); execute_plugins(:pre_compile_execute, arg_hash); end
+ def post_compile_execute(arg_hash); execute_plugins(:post_compile_execute, arg_hash); end
+
+ def pre_link_execute(arg_hash); execute_plugins(:pre_link_execute, arg_hash); end
+ def post_link_execute(arg_hash); execute_plugins(:post_link_execute, arg_hash); end
+
+ def pre_test_fixture_execute(arg_hash); execute_plugins(:pre_test_fixture_execute, arg_hash); end
+ def post_test_fixture_execute(arg_hash)
+ # special arbitration: raw test results are printed or taken over by plugins handling the job
+ @streaminator.stdout_puts(arg_hash[:shell_result][:output]) if (@configurator.plugins_display_raw_test_results)
+ execute_plugins(:post_test_fixture_execute, arg_hash)
+ end
+
+ def pre_test(test); execute_plugins(:pre_test, test); end
+ def post_test(test); execute_plugins(:post_test, test); end
+
+ def pre_release; execute_plugins(:pre_release); end
+ def post_release; execute_plugins(:post_release); end
+
+ def pre_build; execute_plugins(:pre_build); end
+ def post_build; execute_plugins(:post_build); end
+ def post_error; execute_plugins(:post_error); end
+
+ def summary; execute_plugins(:summary); end
+
+ private ####################################
+
+ def camelize(underscored_name)
+ return underscored_name.gsub(/(_|^)([a-z0-9])/) {$2.upcase}
+ end
+
+ def execute_plugins(method, *args)
+ @plugin_objects.each do |plugin|
+ begin
+ plugin.send(method, *args) if plugin.respond_to?(method)
+ rescue
+ puts "Exception raised in plugin: #{plugin.name}, in method #{method}"
+ raise
+ end
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager_helper.rb
new file mode 100755
index 00000000..b18248a6
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_manager_helper.rb
@@ -0,0 +1,19 @@
+
+class PluginManagerHelper
+
+ def include?(plugins, name)
+ include = false
+ plugins.each do |plugin|
+ if (plugin.name == name)
+ include = true
+ break
+ end
+ end
+ return include
+ end
+
+ def instantiate_plugin_script(plugin, system_objects, name)
+ return eval("#{plugin}.new(system_objects, name)")
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator.rb
new file mode 100755
index 00000000..8d83727b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator.rb
@@ -0,0 +1,76 @@
+require 'ceedling/constants'
+require 'ceedling/defaults'
+
+class PluginReportinator
+
+ constructor :plugin_reportinator_helper, :plugin_manager, :reportinator
+
+ def setup
+ @test_results_template = nil
+ end
+
+
+ def set_system_objects(system_objects)
+ @plugin_reportinator_helper.ceedling = system_objects
+ end
+
+
+ def fetch_results(results_path, test, options={:boom => false})
+ return @plugin_reportinator_helper.fetch_results( File.join(results_path, test), options )
+ end
+
+
+ def generate_banner(message)
+ return @reportinator.generate_banner(message)
+ end
+
+
+ def assemble_test_results(results_list, options={:boom => false})
+ aggregated_results = get_results_structure
+
+ results_list.each do |result_path|
+ results = @plugin_reportinator_helper.fetch_results( result_path, options )
+ @plugin_reportinator_helper.process_results(aggregated_results, results)
+ end
+
+ return aggregated_results
+ end
+
+
+ def register_test_results_template(template)
+ @test_results_template = template if (@test_results_template.nil?)
+ end
+
+
+ def run_test_results_report(hash, verbosity=Verbosity::NORMAL, &block)
+ run_report( $stdout,
+ ((@test_results_template.nil?) ? DEFAULT_TESTS_RESULTS_REPORT_TEMPLATE : @test_results_template),
+ hash,
+ verbosity,
+ &block )
+ end
+
+
+ def run_report(stream, template, hash=nil, verbosity=Verbosity::NORMAL)
+ failure = nil
+ failure = yield() if block_given?
+
+ @plugin_manager.register_build_failure( failure )
+
+ @plugin_reportinator_helper.run_report( stream, template, hash, verbosity )
+ end
+
+ private ###############################
+
+ def get_results_structure
+ return {
+ :successes => [],
+ :failures => [],
+ :ignores => [],
+ :stdout => [],
+ :counts => {:total => 0, :passed => 0, :failed => 0, :ignored => 0, :stdout => 0},
+ :time => 0.0
+ }
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb
new file mode 100755
index 00000000..322a530b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/plugin_reportinator_helper.rb
@@ -0,0 +1,51 @@
+require 'erb'
+require 'rubygems'
+require 'rake' # for ext()
+require 'ceedling/constants'
+
+class PluginReportinatorHelper
+
+ attr_writer :ceedling
+
+ constructor :configurator, :streaminator, :yaml_wrapper, :file_wrapper
+
+ def fetch_results(results_path, options)
+ pass_path = File.join(results_path.ext( @configurator.extension_testpass ))
+ fail_path = File.join(results_path.ext( @configurator.extension_testfail ))
+
+ if (@file_wrapper.exist?(fail_path))
+ return @yaml_wrapper.load(fail_path)
+ elsif (@file_wrapper.exist?(pass_path))
+ return @yaml_wrapper.load(pass_path)
+ else
+ if (options[:boom])
+ @streaminator.stderr_puts("Could find no test results for '#{File.basename(results_path).ext(@configurator.extension_source)}'", Verbosity::ERRORS)
+ raise
+ end
+ end
+
+ return {}
+ end
+
+
+ def process_results(aggregate_results, results)
+ return if (results.empty?)
+ aggregate_results[:successes] << { :source => results[:source].clone, :collection => results[:successes].clone } if (results[:successes].size > 0)
+ aggregate_results[:failures] << { :source => results[:source].clone, :collection => results[:failures].clone } if (results[:failures].size > 0)
+ aggregate_results[:ignores] << { :source => results[:source].clone, :collection => results[:ignores].clone } if (results[:ignores].size > 0)
+ aggregate_results[:stdout] << { :source => results[:source].clone, :collection => results[:stdout].clone } if (results[:stdout].size > 0)
+ aggregate_results[:counts][:total] += results[:counts][:total]
+ aggregate_results[:counts][:passed] += results[:counts][:passed]
+ aggregate_results[:counts][:failed] += results[:counts][:failed]
+ aggregate_results[:counts][:ignored] += results[:counts][:ignored]
+ aggregate_results[:counts][:stdout] += results[:stdout].size
+ aggregate_results[:time] += results[:time]
+ end
+
+
+ def run_report(stream, template, hash, verbosity)
+ output = ERB.new(template, 0, "%<>")
+ @streaminator.stream_puts(stream, output.result(binding()), verbosity)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator.rb
new file mode 100755
index 00000000..f07750dd
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator.rb
@@ -0,0 +1,42 @@
+
+class Preprocessinator
+
+ attr_reader :preprocess_file_proc
+
+ constructor :preprocessinator_helper, :preprocessinator_includes_handler, :preprocessinator_file_handler, :task_invoker, :file_path_utils, :yaml_wrapper
+
+
+ def setup
+ # fashion ourselves callbacks @preprocessinator_helper can use
+ @preprocess_includes_proc = Proc.new { |filepath| self.preprocess_shallow_includes(filepath) }
+ @preprocess_file_proc = Proc.new { |filepath| self.preprocess_file(filepath) }
+ end
+
+
+ def preprocess_test_and_invoke_test_mocks(test)
+ @preprocessinator_helper.preprocess_includes(test, @preprocess_includes_proc)
+
+ mocks_list = @preprocessinator_helper.assemble_mocks_list(test)
+
+ @preprocessinator_helper.preprocess_mockable_headers(mocks_list, @preprocess_file_proc)
+
+ @task_invoker.invoke_test_mocks(mocks_list)
+
+ @preprocessinator_helper.preprocess_test_file(test, @preprocess_file_proc)
+
+ return mocks_list
+ end
+
+ def preprocess_shallow_includes(filepath)
+ includes = @preprocessinator_includes_handler.extract_includes(filepath)
+
+ @preprocessinator_includes_handler.write_shallow_includes_list(
+ @file_path_utils.form_preprocessed_includes_list_filepath(filepath), includes)
+ end
+
+ def preprocess_file(filepath)
+ @preprocessinator_includes_handler.invoke_shallow_includes_list(filepath)
+ @preprocessinator_file_handler.preprocess_file( filepath, @yaml_wrapper.load(@file_path_utils.form_preprocessed_includes_list_filepath(filepath)) )
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb
new file mode 100755
index 00000000..49509a8b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb
@@ -0,0 +1,30 @@
+class PreprocessinatorExtractor
+ def extract_base_file_from_preprocessed_expansion(filepath)
+ # preprocessing by way of toolchain preprocessor expands macros, eliminates
+ # comments, strips out #ifdef code, etc. however, it also expands in place
+ # each #include'd file. so, we must extract only the lines of the file
+ # that belong to the file originally preprocessed
+
+ # iterate through all lines and alternate between extract and ignore modes
+ # all lines between a '#'line containing file name of our filepath and the
+ # next '#'line should be extracted
+
+ base_name = File.basename(filepath)
+ not_pragma = /^#(?!pragma\b)/ # preprocessor directive that's not a #pragma
+ pattern = /^#.*(\s|\/|\\|\")#{Regexp.escape(base_name)}/
+ found_file = false # have we found the file we care about?
+
+ lines = []
+ File.readlines(filepath).each do |line|
+ if found_file and not line =~ not_pragma
+ lines << line
+ else
+ found_file = false
+ end
+
+ found_file = true if line =~ pattern
+ end
+
+ return lines
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb
new file mode 100755
index 00000000..b6b5efbc
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb
@@ -0,0 +1,21 @@
+
+
+class PreprocessinatorFileHandler
+
+ constructor :preprocessinator_extractor, :configurator, :tool_executor, :file_path_utils, :file_wrapper
+
+
+ def preprocess_file(filepath, includes)
+ preprocessed_filepath = @file_path_utils.form_preprocessed_file_filepath(filepath)
+
+ command = @tool_executor.build_command_line(@configurator.tools_test_file_preprocessor, [], filepath, preprocessed_filepath)
+ @tool_executor.exec(command[:line], command[:options])
+
+ contents = @preprocessinator_extractor.extract_base_file_from_preprocessed_expansion(preprocessed_filepath)
+
+ includes.each{|include| contents.unshift("#include \"#{include}\"")}
+
+ @file_wrapper.write(preprocessed_filepath, contents.join("\n"))
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb
new file mode 100755
index 00000000..1419a561
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb
@@ -0,0 +1,46 @@
+
+
+class PreprocessinatorHelper
+
+ constructor :configurator, :test_includes_extractor, :task_invoker, :file_finder, :file_path_utils
+
+
+ def preprocess_includes(test, preprocess_includes_proc)
+ if (@configurator.project_use_test_preprocessor)
+ preprocessed_includes_list = @file_path_utils.form_preprocessed_includes_list_filepath(test)
+ preprocess_includes_proc.call( @file_finder.find_test_from_file_path(preprocessed_includes_list) )
+ @test_includes_extractor.parse_includes_list(preprocessed_includes_list)
+ else
+ @test_includes_extractor.parse_test_file(test)
+ end
+ end
+
+ def assemble_mocks_list(test)
+ return @file_path_utils.form_mocks_source_filelist( @test_includes_extractor.lookup_raw_mock_list(test) )
+ end
+
+ def preprocess_mockable_headers(mock_list, preprocess_file_proc)
+ if (@configurator.project_use_test_preprocessor)
+ preprocess_files_smartly(
+ @file_path_utils.form_preprocessed_mockable_headers_filelist(mock_list),
+ preprocess_file_proc ) { |file| @file_finder.find_header_file(file) }
+ end
+ end
+
+ def preprocess_test_file(test, preprocess_file_proc)
+ return if (!@configurator.project_use_test_preprocessor)
+
+ preprocess_file_proc.call(test)
+ end
+
+ private ############################
+
+ def preprocess_files_smartly(file_list, preprocess_file_proc)
+ if (@configurator.project_use_deep_dependencies)
+ @task_invoker.invoke_test_preprocessed_files(file_list)
+ else
+ file_list.each { |file| preprocess_file_proc.call( yield(file) ) }
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb
new file mode 100755
index 00000000..703c84f3
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/preprocessinator_includes_handler.rb
@@ -0,0 +1,181 @@
+
+
+class PreprocessinatorIncludesHandler
+
+ constructor :configurator, :tool_executor, :task_invoker, :file_path_utils, :yaml_wrapper, :file_wrapper
+ @@makefile_cache = {}
+
+ # shallow includes: only those headers a source file explicitly includes
+
+ def invoke_shallow_includes_list(filepath)
+ @task_invoker.invoke_test_shallow_include_lists( [@file_path_utils.form_preprocessed_includes_list_filepath(filepath)] )
+ end
+
+ ##
+ # Ask the preprocessor for a make-style dependency rule of only the headers
+ # the source file immediately includes.
+ #
+ # === Arguments
+ # +filepath+ _String_:: Path to the test file to process.
+ #
+ # === Return
+ # _String_:: The text of the dependency rule generated by the preprocessor.
+ def form_shallow_dependencies_rule(filepath)
+ if @@makefile_cache.has_key?(filepath)
+ return @@makefile_cache[filepath]
+ end
+ # change filename (prefix of '_') to prevent preprocessor from finding
+ # include files in temp directory containing file it's scanning
+ temp_filepath = @file_path_utils.form_temp_path(filepath, '_')
+
+ # read the file and replace all include statements with a decorated version
+ # (decorating the names creates file names that don't exist, thus preventing
+ # the preprocessor from snaking out and discovering the entire include path
+ # that winds through the code). The decorated filenames indicate files that
+ # are included directly by the test file.
+ contents = @file_wrapper.read(filepath)
+
+ if !contents.valid_encoding?
+ contents = contents.encode("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8')
+ end
+
+ contents.gsub!( /^\s*#include\s+[\"<]\s*(\S+)\s*[\">]/, "#include \"\\1\"\n#include \"@@@@\\1\"" )
+ contents.gsub!( /^\s*TEST_FILE\(\s*\"\s*(\S+)\s*\"\s*\)/, "#include \"\\1\"\n#include \"@@@@\\1\"")
+ @file_wrapper.write( temp_filepath, contents )
+
+ # extract the make-style dependency rule telling the preprocessor to
+ # ignore the fact that it can't find the included files
+ command = @tool_executor.build_command_line(@configurator.tools_test_includes_preprocessor, [], temp_filepath)
+ shell_result = @tool_executor.exec(command[:line], command[:options])
+
+ @@makefile_cache[filepath] = shell_result[:output]
+ return shell_result[:output]
+ end
+
+ ##
+ # Extract the headers that are directly included by a source file using the
+ # provided, annotated Make dependency rule.
+ #
+ # === Arguments
+ # +filepath+ _String_:: C source or header file to extract includes for.
+ #
+ # === Return
+ # _Array_ of _String_:: Array of the direct dependencies for the source file.
+ def extract_includes(filepath)
+ to_process = [filepath]
+ ignore_list = []
+ list = []
+
+ include_paths = @configurator.project_config_hash[:collection_paths_include]
+ include_paths = [] if include_paths.nil?
+ include_paths.map! {|path| File.expand_path(path)}
+
+ while to_process.length > 0
+ target = to_process.shift()
+ ignore_list << target
+ # puts "[HELL] Processing: \t\t#{target}"
+ new_deps, new_to_process = extract_includes_helper(target, include_paths, ignore_list)
+ list += new_deps
+ to_process += new_to_process
+ if (!@configurator.project_config_hash.has_key?(:project_auto_link_deep_dependencies) or
+ !@configurator.project_config_hash[:project_auto_link_deep_dependencies])
+ break
+ else
+ list = list.uniq()
+ to_process = to_process.uniq()
+ end
+ end
+
+ return list
+ end
+
+ def extract_includes_helper(filepath, include_paths, ignore_list)
+ # Extract the dependencies from the make rule
+ hdr_ext = @configurator.extension_header
+ make_rule = self.form_shallow_dependencies_rule(filepath)
+ dependencies = make_rule.split.find_all {|path| path.end_with?(hdr_ext) }.uniq
+ dependencies.map! {|hdr| hdr.gsub('\\','/') }
+
+ # Separate the real files form the annotated ones and remove the '@@@@'
+ annotated_headers, real_headers = dependencies.partition {|hdr| hdr =~ /^@@@@/ }
+ annotated_headers.map! {|hdr| hdr.gsub('@@@@','') }
+ # Matching annotated_headers values against real_headers to ensure that
+ # annotated_headers contain full path entries (as returned by make rule)
+ annotated_headers.map! {|hdr| real_headers.find {|real_hdr| !real_hdr.match(/(.*\/)?#{Regexp.escape(hdr)}/).nil? } }
+ annotated_headers = annotated_headers.compact
+
+ # Find which of our annotated headers are "real" dependencies. This is
+ # intended to weed out dependencies that have been removed due to build
+ # options defined in the project yaml and/or in the headers themselves.
+ list = annotated_headers.find_all do |annotated_header|
+ # find the index of the "real" include that matches the annotated one.
+ idx = real_headers.find_index do |real_header|
+ real_header =~ /^(.*\/)?#{Regexp.escape(annotated_header)}$/
+ end
+ # If we found a real include, delete it from the array and return it,
+ # otherwise return nil. Since nil is falsy this has the effect of making
+ # find_all return only the annotated headers for which a real include was
+ # found/deleted
+ idx ? real_headers.delete_at(idx) : nil
+ end.compact
+
+ # Extract direct dependencies that were also added
+ src_ext = @configurator.extension_source
+ sdependencies = make_rule.split.find_all {|path| path.end_with?(src_ext) }.uniq
+ sdependencies.map! {|hdr| hdr.gsub('\\','/') }
+ list += sdependencies
+
+ to_process = []
+
+ if @configurator.project_config_hash.has_key?(:project_auto_link_deep_dependencies) && @configurator.project_config_hash[:project_auto_link_deep_dependencies]
+ # Creating list of mocks
+ mocks = annotated_headers.find_all do |annotated_header|
+ File.basename(annotated_header) =~ /^#{@configurator.project_config_hash[:cmock_mock_prefix]}.*$/
+ end.compact
+
+ # Creating list of headers that should be recursively pre-processed
+ # Skipping mocks and unity.h
+ headers_to_deep_link = annotated_headers.select do |annotated_header|
+ !(mocks.include? annotated_header) and (annotated_header.match(/^(.*\/)?unity\.h$/).nil?)
+ end
+ headers_to_deep_link.map! {|hdr| File.expand_path(hdr)}
+
+ mocks.each do |mock|
+ dirname = File.dirname(mock)
+ #basename = File.basename(mock).delete_prefix(@configurator.project_config_hash[:cmock_mock_prefix])
+ basename = File.basename(mock).sub(@configurator.project_config_hash[:cmock_mock_prefix], '')
+ if dirname != "."
+ ignore_list << File.join(dirname, basename)
+ else
+ ignore_list << basename
+ end
+ end.compact
+
+ # Filtering list of final includes to only include mocks and anything that is NOT in the ignore_list
+ list = list.select do |item|
+ mocks.include? item or !(ignore_list.any? { |ignore_item| !item.match(/^(.*\/)?#{Regexp.escape(ignore_item)}$/).nil? })
+ end
+
+ headers_to_deep_link.each do |hdr|
+ if (ignore_list.none? {|ignore_header| hdr.match(/^(.*\/)?#{Regexp.escape(ignore_header)}$/)} and
+ include_paths.none? {|include_path| hdr =~ /^#{include_path}\.*/})
+ if File.exist?(hdr)
+ to_process << hdr
+ #source_file = hdr.delete_suffix(hdr_ext) + src_ext
+ source_file = hdr.chomp(hdr_ext) + src_ext
+ if source_file != hdr and File.exist?(source_file)
+ to_process << source_file
+ end
+ end
+ end
+ end
+ end
+
+ return list, to_process
+
+ end
+
+ def write_shallow_includes_list(filepath, list)
+ @yaml_wrapper.dump(filepath, list)
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/project_config_manager.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/project_config_manager.rb
new file mode 100755
index 00000000..31f7e3a6
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/project_config_manager.rb
@@ -0,0 +1,46 @@
+require 'ceedling/constants'
+
+
+class ProjectConfigManager
+
+ attr_reader :options_files, :release_config_changed, :test_config_changed, :test_defines_changed
+ attr_accessor :config_hash
+
+ constructor :cacheinator, :configurator, :yaml_wrapper, :file_wrapper
+
+
+ def setup
+ @options_files = []
+ @release_config_changed = false
+ @test_config_changed = false
+ @test_defines_changed = false
+ end
+
+
+ def merge_options(config_hash, option_filepath)
+ @options_files << File.basename( option_filepath )
+ config_hash.deep_merge!( @yaml_wrapper.load( option_filepath ) )
+ end
+
+
+
+ def process_release_config_change
+ # has project configuration changed since last release build
+ @release_config_changed = @cacheinator.diff_cached_release_config?( @config_hash )
+ end
+
+
+ def process_test_config_change
+ # has project configuration changed since last test build
+ @test_config_changed = @cacheinator.diff_cached_test_config?( @config_hash )
+ end
+
+ def process_test_defines_change(files)
+ # has definitions changed since last test build
+ @test_defines_changed = @cacheinator.diff_cached_test_defines?( files )
+ if @test_defines_changed
+ # update timestamp for rake task prerequisites
+ @file_wrapper.touch( @configurator.project_test_force_rebuild_filepath )
+ end
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/project_file_loader.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/project_file_loader.rb
new file mode 100755
index 00000000..bf5dcd41
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/project_file_loader.rb
@@ -0,0 +1,99 @@
+require 'ceedling/constants'
+
+
+class ProjectFileLoader
+
+ attr_reader :main_file, :user_file
+
+ constructor :yaml_wrapper, :stream_wrapper, :system_wrapper, :file_wrapper
+
+ def setup
+ @main_file = nil
+ @mixin_files = []
+ @user_file = nil
+
+ @main_project_filepath = ''
+ @mixin_project_filepaths = []
+ @user_project_filepath = ''
+ end
+
+
+ def find_project_files
+ # first go hunting for optional user project file by looking for environment variable and then default location on disk
+ user_filepath = @system_wrapper.env_get('CEEDLING_USER_PROJECT_FILE')
+
+ if ( not user_filepath.nil? and @file_wrapper.exist?(user_filepath) )
+ @user_project_filepath = user_filepath
+ elsif (@file_wrapper.exist?(DEFAULT_CEEDLING_USER_PROJECT_FILE))
+ @user_project_filepath = DEFAULT_CEEDLING_USER_PROJECT_FILE
+ end
+
+ # next check for mixin project files by looking for environment variable
+ mixin_filepaths = @system_wrapper.env_get('CEEDLING_MIXIN_PROJECT_FILES')
+ if ( not mixin_filepaths.nil? )
+ mixin_filepaths.split(File::PATH_SEPARATOR).each do |filepath|
+ if ( @file_wrapper.exist?(filepath) )
+ @mixin_project_filepaths.push(filepath)
+ end
+ end
+ end
+
+ # next check for main project file by looking for environment variable and then default location on disk;
+ # blow up if we don't find this guy -- like, he's so totally important
+ main_filepath = @system_wrapper.env_get('CEEDLING_MAIN_PROJECT_FILE')
+
+ if ( not main_filepath.nil? and @file_wrapper.exist?(main_filepath) )
+ @main_project_filepath = main_filepath
+ elsif (@file_wrapper.exist?(DEFAULT_CEEDLING_MAIN_PROJECT_FILE))
+ @main_project_filepath = DEFAULT_CEEDLING_MAIN_PROJECT_FILE
+ else
+ # no verbosity checking since this is lowest level reporting anyhow &
+ # verbosity checking depends on configurator which in turns needs this class (circular dependency)
+ @stream_wrapper.stderr_puts('Found no Ceedling project file (*.yml)')
+ raise
+ end
+
+ @main_file = File.basename( @main_project_filepath )
+ @mixin_project_filepaths.each do |filepath|
+ @mixin_files.push(File.basename( filepath ))
+ end
+ @user_file = File.basename( @user_project_filepath ) if ( not @user_project_filepath.empty? )
+ end
+
+ def yaml_merger(y1, y2)
+ o1 = y1
+ y2.each_pair do |k,v|
+ if o1[k].nil?
+ o1[k] = v
+ else
+ if (o1[k].instance_of? Hash)
+ o1[k] = yaml_merger(o1[k], v)
+ elsif (o1[k].instance_of? Array)
+ o1[k] += v
+ else
+ o1[k] = v
+ end
+ end
+ end
+ return o1
+ end
+
+ def load_project_config
+ config_hash = @yaml_wrapper.load(@main_project_filepath)
+
+ # if there are mixin project files, then use them
+ @mixin_project_filepaths.each do |filepath|
+ mixin = @yaml_wrapper.load(filepath)
+ config_hash = yaml_merger( config_hash, mixin )
+ end
+
+ # if there's a user project file, then use it
+ if ( not @user_project_filepath.empty? )
+ user_hash = @yaml_wrapper.load(@user_project_filepath)
+ config_hash = yaml_merger( config_hash, user_hash )
+ end
+
+ return config_hash
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rake_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_utils.rb
new file mode 100755
index 00000000..3f667c85
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_utils.rb
@@ -0,0 +1,17 @@
+
+class RakeUtils
+
+ constructor :rake_wrapper
+
+ def task_invoked?(task_regex)
+ task_invoked = false
+ @rake_wrapper.task_list.each do |task|
+ if ((task.already_invoked) and (task.to_s =~ task_regex))
+ task_invoked = true
+ break
+ end
+ end
+ return task_invoked
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rake_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_wrapper.rb
new file mode 100755
index 00000000..15e47961
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rake_wrapper.rb
@@ -0,0 +1,33 @@
+require 'rubygems'
+require 'rake'
+require 'ceedling/makefile' # our replacement for rake's make-style dependency loader
+
+include Rake::DSL if defined?(Rake::DSL)
+
+class Rake::Task
+ attr_reader :already_invoked
+end
+
+class RakeWrapper
+
+ def initialize
+ @makefile_loader = Rake::MakefileLoader.new # use our custom replacement noted above
+ end
+
+ def [](task)
+ return Rake::Task[task]
+ end
+
+ def task_list
+ return Rake::Task.tasks
+ end
+
+ def create_file_task(file_task, dependencies)
+ file(file_task => dependencies)
+ end
+
+ def load_dependencies(dependencies_path)
+ @makefile_loader.load(dependencies_path)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rakefile.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/rakefile.rb
new file mode 100755
index 00000000..37001bac
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rakefile.rb
@@ -0,0 +1,86 @@
+require 'fileutils'
+
+# get directory containing this here file, back up one directory, and expand to full path
+CEEDLING_ROOT = File.expand_path(File.dirname(__FILE__) + '/../..')
+CEEDLING_LIB = File.join(CEEDLING_ROOT, 'lib')
+CEEDLING_VENDOR = File.join(CEEDLING_ROOT, 'vendor')
+CEEDLING_RELEASE = File.join(CEEDLING_ROOT, 'release')
+
+$LOAD_PATH.unshift( CEEDLING_LIB )
+$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'unity/auto') )
+$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'diy/lib') )
+$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'cmock/lib') )
+$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'deep_merge/lib') )
+
+require 'rake'
+
+#Let's make sure we remember the task descriptions in case we need them
+Rake::TaskManager.record_task_metadata = true
+
+require 'diy'
+require 'constructor'
+
+require 'ceedling/constants'
+require 'ceedling/target_loader'
+
+
+# construct all our objects
+# ensure load path contains all libraries needed first
+lib_ceedling_load_path_temp = File.join(CEEDLING_LIB, 'ceedling')
+$LOAD_PATH.unshift( lib_ceedling_load_path_temp )
+@ceedling = DIY::Context.from_yaml( File.read( File.join(lib_ceedling_load_path_temp, 'objects.yml') ) )
+@ceedling.build_everything
+# now that all objects are built, delete 'lib/ceedling' from load path
+$LOAD_PATH.delete(lib_ceedling_load_path_temp)
+# one-stop shopping for all our setup and such after construction
+@ceedling[:setupinator].ceedling = @ceedling
+
+project_config =
+ begin
+ cfg = @ceedling[:setupinator].load_project_files
+ TargetLoader.inspect(cfg, ENV['TARGET'])
+ rescue TargetLoader::NoTargets
+ cfg
+ rescue TargetLoader::RequestReload
+ @ceedling[:setupinator].load_project_files
+ end
+
+@ceedling[:setupinator].do_setup( project_config )
+
+
+# tell all our plugins we're about to do something
+@ceedling[:plugin_manager].pre_build
+
+# load rakefile component files (*.rake)
+PROJECT_RAKEFILE_COMPONENT_FILES.each { |component| load(component) }
+
+# tell rake to shut up by default (overridden in verbosity / debug tasks as appropriate)
+verbose(false)
+
+
+# end block always executed following rake run
+END {
+ $stdout.flush unless $stdout.nil?
+ $stderr.flush unless $stderr.nil?
+
+ # cache our input configurations to use in comparison upon next execution
+ @ceedling[:cacheinator].cache_test_config( @ceedling[:setupinator].config_hash ) if (@ceedling[:task_invoker].test_invoked?)
+ @ceedling[:cacheinator].cache_release_config( @ceedling[:setupinator].config_hash ) if (@ceedling[:task_invoker].release_invoked?)
+
+ # delete all temp files unless we're in debug mode
+ if (not @ceedling[:configurator].project_debug)
+ @ceedling[:file_wrapper].rm_f( @ceedling[:file_wrapper].directory_listing( File.join(@ceedling[:configurator].project_temp_path, '*') ))
+ end
+
+ # only perform these final steps if we got here without runtime exceptions or errors
+ if (@ceedling[:system_wrapper].ruby_success)
+
+ # tell all our plugins the build is done and process results
+ @ceedling[:plugin_manager].post_build
+ @ceedling[:plugin_manager].print_plugin_failures
+ exit(1) if (@ceedling[:plugin_manager].plugins_failed? && !@ceedling[:setupinator].config_hash[:graceful_fail])
+ else
+ puts "ERROR: Ceedling Failed"
+ @ceedling[:plugin_manager].post_error
+ end
+}
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker.rb
new file mode 100755
index 00000000..5bfb6cd7
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker.rb
@@ -0,0 +1,73 @@
+require 'ceedling/constants'
+
+
+class ReleaseInvoker
+
+ constructor :configurator, :release_invoker_helper, :build_invoker_utils, :dependinator, :task_invoker, :file_path_utils, :file_wrapper
+
+
+ def setup_and_invoke_c_objects( c_files )
+ objects = @file_path_utils.form_release_build_c_objects_filelist( c_files )
+
+ begin
+ @release_invoker_helper.process_deep_dependencies( @file_path_utils.form_release_dependencies_filelist( c_files ) )
+
+ @dependinator.enhance_release_file_dependencies( objects )
+ @task_invoker.invoke_release_objects( objects )
+ rescue => e
+ @build_invoker_utils.process_exception( e, RELEASE_SYM, false )
+ end
+
+ return objects
+ end
+
+
+ def setup_and_invoke_asm_objects( asm_files )
+ objects = @file_path_utils.form_release_build_asm_objects_filelist( asm_files )
+
+ begin
+ @dependinator.enhance_release_file_dependencies( objects )
+ @task_invoker.invoke_release_objects( objects )
+ rescue => e
+ @build_invoker_utils.process_exception( e, RELEASE_SYM, false )
+ end
+
+ return objects
+ end
+
+
+ def refresh_c_deep_dependencies
+ return if (not @configurator.project_use_deep_dependencies)
+
+ @file_wrapper.rm_f(
+ @file_wrapper.directory_listing(
+ File.join( @configurator.project_release_dependencies_path, '*' + @configurator.extension_dependencies ) ) )
+
+ @release_invoker_helper.process_deep_dependencies(
+ @file_path_utils.form_release_dependencies_filelist(
+ @configurator.collection_all_source ) )
+ end
+
+
+ def artifactinate( *files )
+ files.flatten.each do |file|
+ @file_wrapper.cp( file, @configurator.project_release_artifacts_path ) if @file_wrapper.exist?( file )
+ end
+ end
+
+ def convert_libraries_to_arguments(libraries)
+ args = (libraries || []) + ((defined? LIBRARIES_SYSTEM) ? LIBRARIES_SYSTEM : [])
+ if (defined? LIBRARIES_FLAG)
+ args.map! {|v| LIBRARIES_FLAG.gsub(/\$\{1\}/, v) }
+ end
+ return args
+ end
+
+ def sort_objects_and_libraries(both)
+ extension = "\\" + ((defined? EXTENSION_SUBPROJECTS) ? EXTENSION_SUBPROJECTS : ".LIBRARY")
+ sorted_objects = both.group_by {|v| v.match(/.+#{extension}$/) ? :libraries : :objects }
+ libraries = sorted_objects[:libraries] || []
+ objects = sorted_objects[:objects] || []
+ return objects, libraries
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker_helper.rb
new file mode 100755
index 00000000..f83a2a53
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/release_invoker_helper.rb
@@ -0,0 +1,19 @@
+
+
+class ReleaseInvokerHelper
+
+ constructor :configurator, :dependinator, :task_invoker
+
+
+ def process_deep_dependencies(dependencies_list)
+ return if (not @configurator.project_use_deep_dependencies)
+
+ if @configurator.project_generate_deep_dependencies
+ @dependinator.enhance_release_file_dependencies( dependencies_list )
+ @task_invoker.invoke_release_dependencies_files( dependencies_list )
+ end
+
+ @dependinator.load_release_object_deep_dependencies( dependencies_list )
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/reportinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/reportinator.rb
new file mode 100755
index 00000000..0f583d06
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/reportinator.rb
@@ -0,0 +1,26 @@
+##
+# Pretifies reports
+class Reportinator
+
+ ##
+ # Generates a banner for a message based on the length of the message or a
+ # given width.
+ # ==== Attributes
+ #
+ # * _message_: The message to put.
+ # * _width_: The width of the message. If nil the size of the banner is
+ # determined by the length of the message.
+ #
+ # ==== Examples
+ #
+ # rp = Reportinator.new
+ # rp.generate_banner("Hello world!") => "------------\nHello world!\n------------\n"
+ # rp.generate_banner("Hello world!", 3) => "---\nHello world!\n---\n"
+ #
+ #
+ def generate_banner(message, width=nil)
+ dash_count = ((width.nil?) ? message.strip.length : width)
+ return "#{'-' * dash_count}\n#{message}\n#{'-' * dash_count}\n"
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_cmock.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_cmock.rake
new file mode 100755
index 00000000..70ddcbc2
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_cmock.rake
@@ -0,0 +1,9 @@
+
+
+rule(/#{CMOCK_MOCK_PREFIX}[^\/\\]+#{'\\'+EXTENSION_SOURCE}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_header_input_for_mock_file(task_name)
+ end
+ ]) do |mock|
+ @ceedling[:generator].generate_mock(TEST_SYM, mock.source)
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_preprocess.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_preprocess.rake
new file mode 100755
index 00000000..c2911127
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_preprocess.rake
@@ -0,0 +1,26 @@
+
+
+# invocations against this rule should only happen when enhanced dependencies are enabled;
+# otherwise, dependency tracking will be too shallow and preprocessed files could intermittently
+# fail to be updated when they actually need to be.
+rule(/#{PROJECT_TEST_PREPROCESS_FILES_PATH}\/.+/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_test_or_source_or_header_file(task_name)
+ end
+ ]) do |file|
+ if (not @ceedling[:configurator].project_use_deep_dependencies)
+ raise 'ERROR: Ceedling preprocessing rule invoked though neccessary auxiliary dependency support not enabled.'
+ end
+ @ceedling[:generator].generate_preprocessed_file(TEST_SYM, file.source)
+end
+
+
+# invocations against this rule can always happen as there are no deeper dependencies to consider
+rule(/#{PROJECT_TEST_PREPROCESS_INCLUDES_PATH}\/.+/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_test_or_source_or_header_file(task_name)
+ end
+ ]) do |file|
+ @ceedling[:generator].generate_shallow_includes_list(TEST_SYM, file.source)
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release.rake
new file mode 100755
index 00000000..ae39a76e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release.rake
@@ -0,0 +1,86 @@
+
+RELEASE_COMPILE_TASK_ROOT = RELEASE_TASK_ROOT + 'compile:' unless defined?(RELEASE_COMPILE_TASK_ROOT)
+RELEASE_ASSEMBLE_TASK_ROOT = RELEASE_TASK_ROOT + 'assemble:' unless defined?(RELEASE_ASSEMBLE_TASK_ROOT)
+
+
+if (RELEASE_BUILD_USE_ASSEMBLY)
+rule(/#{PROJECT_RELEASE_BUILD_OUTPUT_ASM_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_assembly_file(task_name)
+ end
+ ]) do |object|
+ @ceedling[:generator].generate_object_file(
+ TOOLS_RELEASE_ASSEMBLER,
+ OPERATION_ASSEMBLE_SYM,
+ RELEASE_SYM,
+ object.source,
+ object.name )
+end
+end
+
+
+rule(/#{PROJECT_RELEASE_BUILD_OUTPUT_C_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name, :error, true)
+ end
+ ]) do |object|
+ @ceedling[:generator].generate_object_file(
+ TOOLS_RELEASE_COMPILER,
+ OPERATION_COMPILE_SYM,
+ RELEASE_SYM,
+ object.source,
+ object.name,
+ @ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ),
+ @ceedling[:file_path_utils].form_release_dependencies_filepath( object.name ) )
+end
+
+
+rule(/#{PROJECT_RELEASE_BUILD_TARGET}/) do |bin_file|
+ objects, libraries = @ceedling[:release_invoker].sort_objects_and_libraries(bin_file.prerequisites)
+ tool = TOOLS_RELEASE_LINKER.clone
+ lib_args = @ceedling[:release_invoker].convert_libraries_to_arguments(libraries)
+ map_file = @ceedling[:configurator].project_release_build_map
+ @ceedling[:generator].generate_executable_file(
+ tool,
+ RELEASE_SYM,
+ objects,
+ bin_file.name,
+ map_file,
+ lib_args )
+ @ceedling[:release_invoker].artifactinate( bin_file.name, map_file, @ceedling[:configurator].release_build_artifacts )
+end
+
+
+namespace RELEASE_SYM do
+ # use rules to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks)
+
+ namespace :compile do
+ rule(/^#{RELEASE_COMPILE_TASK_ROOT}\S+#{'\\'+EXTENSION_SOURCE}$/ => [ # compile task names by regex
+ proc do |task_name|
+ source = task_name.sub(/#{RELEASE_COMPILE_TASK_ROOT}/, '')
+ @ceedling[:file_finder].find_source_file(source, :error)
+ end
+ ]) do |compile|
+ @ceedling[:rake_wrapper][:directories].invoke
+ @ceedling[:project_config_manager].process_release_config_change
+ @ceedling[:release_invoker].setup_and_invoke_c_objects( [compile.source] )
+ end
+ end
+
+ if (RELEASE_BUILD_USE_ASSEMBLY)
+ namespace :assemble do
+ rule(/^#{RELEASE_ASSEMBLE_TASK_ROOT}\S+#{'\\'+EXTENSION_ASSEMBLY}$/ => [ # assemble task names by regex
+ proc do |task_name|
+ source = task_name.sub(/#{RELEASE_ASSEMBLE_TASK_ROOT}/, '')
+ @ceedling[:file_finder].find_assembly_file(source)
+ end
+ ]) do |assemble|
+ @ceedling[:rake_wrapper][:directories].invoke
+ @ceedling[:project_config_manager].process_release_config_change
+ @ceedling[:release_invoker].setup_and_invoke_asm_objects( [assemble.source] )
+ end
+ end
+ end
+
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake
new file mode 100755
index 00000000..9550783c
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_release_deep_dependencies.rake
@@ -0,0 +1,15 @@
+
+
+rule(/#{PROJECT_RELEASE_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name, :error, true)
+ end
+ ]) do |dep|
+ @ceedling[:generator].generate_dependencies_file(
+ TOOLS_RELEASE_DEPENDENCIES_GENERATOR,
+ RELEASE_SYM,
+ dep.source,
+ @ceedling[:file_path_utils].form_release_build_c_object_filepath(dep.source),
+ dep.name)
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests.rake
new file mode 100755
index 00000000..2b8f7af5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests.rake
@@ -0,0 +1,74 @@
+
+
+rule(/#{PROJECT_TEST_FILE_PREFIX}#{'.+'+TEST_RUNNER_FILE_SUFFIX}#{'\\'+EXTENSION_SOURCE}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_test_input_for_runner_file(task_name)
+ end
+ ]) do |runner|
+ @ceedling[:generator].generate_test_runner(TEST_SYM, runner.source, runner.name)
+end
+
+rule(/#{PROJECT_TEST_BUILD_OUTPUT_C_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name)
+ end
+ ]) do |object|
+ if (File.basename(object.source) =~ /#{EXTENSION_SOURCE}$/)
+ @ceedling[:generator].generate_object_file(
+ TOOLS_TEST_COMPILER,
+ OPERATION_COMPILE_SYM,
+ TEST_SYM,
+ object.source,
+ object.name,
+ @ceedling[:file_path_utils].form_test_build_list_filepath( object.name ),
+ @ceedling[:file_path_utils].form_test_dependencies_filepath( object.name ))
+ elsif (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY)
+ @ceedling[:generator].generate_object_file(
+ TOOLS_TEST_ASSEMBLER,
+ OPERATION_ASSEMBLE_SYM,
+ TEST_SYM,
+ object.source,
+ object.name )
+ end
+end
+
+
+rule(/#{PROJECT_TEST_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_EXECUTABLE}$/) do |bin_file|
+
+ lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments()
+
+ @ceedling[:generator].generate_executable_file(
+ TOOLS_TEST_LINKER,
+ TEST_SYM,
+ bin_file.prerequisites,
+ bin_file.name,
+ @ceedling[:file_path_utils].form_test_build_map_filepath( bin_file.name ),
+ lib_args )
+end
+
+
+rule(/#{PROJECT_TEST_RESULTS_PATH}\/#{'.+\\'+EXTENSION_TESTPASS}$/ => [
+ proc do |task_name|
+ @ceedling[:file_path_utils].form_test_executable_filepath(task_name)
+ end
+ ]) do |test_result|
+ @ceedling[:generator].generate_test_results(TOOLS_TEST_FIXTURE, TEST_SYM, test_result.source, test_result.name)
+end
+
+
+namespace TEST_SYM do
+ # use rules to increase efficiency for large projects (instead of iterating through all sources and creating defined tasks)
+
+ rule(/^#{TEST_TASK_ROOT}\S+$/ => [ # test task names by regex
+ proc do |task_name|
+ test = task_name.sub(/#{TEST_TASK_ROOT}/, '')
+ test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" if not (test.start_with?(PROJECT_TEST_FILE_PREFIX))
+ @ceedling[:file_finder].find_test_from_file_path(test)
+ end
+ ]) do |test|
+ @ceedling[:rake_wrapper][:directories].reenable if @ceedling[:task_invoker].first_run == false && @ceedling[:project_config_manager].test_defines_changed
+ @ceedling[:rake_wrapper][:directories].invoke
+ @ceedling[:test_invoker].setup_and_invoke([test.source])
+ end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake
new file mode 100755
index 00000000..7175ee3f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/rules_tests_deep_dependencies.rake
@@ -0,0 +1,15 @@
+
+
+rule(/#{PROJECT_TEST_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name)
+ end
+ ]) do |dep|
+ @ceedling[:generator].generate_dependencies_file(
+ TOOLS_TEST_DEPENDENCIES_GENERATOR,
+ TEST_SYM,
+ dep.source,
+ @ceedling[:file_path_utils].form_test_build_c_object_filepath(dep.source),
+ dep.name)
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/setupinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/setupinator.rb
new file mode 100755
index 00000000..8347b42a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/setupinator.rb
@@ -0,0 +1,53 @@
+
+class Setupinator
+
+ attr_reader :config_hash
+ attr_writer :ceedling
+
+ def setup
+ @ceedling = {}
+ @config_hash = {}
+ end
+
+ def load_project_files
+ @ceedling[:project_file_loader].find_project_files
+ return @ceedling[:project_file_loader].load_project_config
+ end
+
+ def do_setup(config_hash)
+ @config_hash = config_hash
+
+ # load up all the constants and accessors our rake files, objects, & external scripts will need;
+ # note: configurator modifies the cmock section of the hash with a couple defaults to tie
+ # project together - the modified hash is used to build cmock object
+ @ceedling[:configurator].populate_defaults( config_hash )
+ @ceedling[:configurator].populate_unity_defaults( config_hash )
+ @ceedling[:configurator].populate_cmock_defaults( config_hash )
+ @ceedling[:configurator].find_and_merge_plugins( config_hash )
+ @ceedling[:configurator].merge_imports( config_hash )
+ @ceedling[:configurator].tools_setup( config_hash )
+ @ceedling[:configurator].eval_environment_variables( config_hash )
+ @ceedling[:configurator].eval_paths( config_hash )
+ @ceedling[:configurator].standardize_paths( config_hash )
+ @ceedling[:configurator].validate( config_hash )
+ @ceedling[:configurator].build( config_hash, :environment )
+
+ @ceedling[:configurator].insert_rake_plugins( @ceedling[:configurator].rake_plugins )
+ @ceedling[:configurator].tools_supplement_arguments( config_hash )
+
+ # merge in any environment variables plugins specify, after the main build
+ @ceedling[:plugin_manager].load_plugin_scripts( @ceedling[:configurator].script_plugins, @ceedling ) do |env|
+ @ceedling[:configurator].eval_environment_variables( env )
+ @ceedling[:configurator].build_supplement( config_hash, env )
+ end
+
+ @ceedling[:plugin_reportinator].set_system_objects( @ceedling )
+ @ceedling[:file_finder].prepare_search_sources
+ @ceedling[:loginator].setup_log_filepath
+ @ceedling[:project_config_manager].config_hash = config_hash
+ end
+
+ def reset_defaults(config_hash)
+ @ceedling[:configurator].reset_defaults( config_hash )
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/stream_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/stream_wrapper.rb
new file mode 100755
index 00000000..7e160527
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/stream_wrapper.rb
@@ -0,0 +1,28 @@
+
+class StreamWrapper
+
+ def stdout_override(&fnc)
+ @stdout_overide_fnc = fnc
+ end
+
+ def stdout_puts(string)
+ if @stdout_overide_fnc
+ @stdout_overide_fnc.call(string)
+ else
+ $stdout.puts(string)
+ end
+ end
+
+ def stdout_flush
+ $stdout.flush
+ end
+
+ def stderr_puts(string)
+ $stderr.puts(string)
+ end
+
+ def stderr_flush
+ $stderr.flush
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator.rb
new file mode 100755
index 00000000..b8dcd070
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator.rb
@@ -0,0 +1,40 @@
+require 'ceedling/constants'
+
+class Streaminator
+
+ constructor :streaminator_helper, :verbosinator, :loginator, :stream_wrapper
+
+ # for those objects for whom the configurator has already been instantiated,
+ # Streaminator is a convenience object for handling verbosity and writing to the std streams
+
+ def stdout_puts(string, verbosity=Verbosity::NORMAL)
+ if (@verbosinator.should_output?(verbosity))
+ @stream_wrapper.stdout_puts(string)
+ @stream_wrapper.stdout_flush
+ end
+
+ # write to log as though Verbosity::OBNOXIOUS
+ @loginator.log( string, @streaminator_helper.extract_name($stdout) )
+ end
+
+ def stderr_puts(string, verbosity=Verbosity::NORMAL)
+ if (@verbosinator.should_output?(verbosity))
+ @stream_wrapper.stderr_puts(string)
+ @stream_wrapper.stderr_flush
+ end
+
+ # write to log as though Verbosity::OBNOXIOUS
+ @loginator.log( string, @streaminator_helper.extract_name($stderr) )
+ end
+
+ def stream_puts(stream, string, verbosity=Verbosity::NORMAL)
+ if (@verbosinator.should_output?(verbosity))
+ stream.puts(string)
+ stream.flush
+ end
+
+ # write to log as though Verbosity::OBNOXIOUS
+ @loginator.log( string, @streaminator_helper.extract_name(stream) )
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator_helper.rb
new file mode 100755
index 00000000..9fb5cc0b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/streaminator_helper.rb
@@ -0,0 +1,15 @@
+
+class StreaminatorHelper
+
+ def extract_name(stream)
+ name = case (stream.fileno)
+ when 0 then '#<IO:$stdin>'
+ when 1 then '#<IO:$stdout>'
+ when 2 then '#<IO:$stderr>'
+ else stream.inspect
+ end
+
+ return name
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/system_utils.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/system_utils.rb
new file mode 100755
index 00000000..477aba4f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/system_utils.rb
@@ -0,0 +1,37 @@
+
+class Object
+ def deep_clone
+ Marshal::load(Marshal.dump(self))
+ end
+end
+
+
+##
+# Class containing system utility funcions.
+class SystemUtils
+
+ constructor :system_wrapper
+
+ ##
+ # Sets up the class.
+ def setup
+ @tcsh_shell = nil
+ end
+
+ ##
+ # Checks the system shell to see if it a tcsh shell.
+ def tcsh_shell?
+ # once run a single time, return state determined at that execution
+ return @tcsh_shell if not @tcsh_shell.nil?
+
+ result = @system_wrapper.shell_backticks('echo $version')
+
+ if ((result[:exit_code] == 0) and (result[:output].strip =~ /^tcsh/))
+ @tcsh_shell = true
+ else
+ @tcsh_shell = false
+ end
+
+ return @tcsh_shell
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/system_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/system_wrapper.rb
new file mode 100755
index 00000000..2b0f1edd
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/system_wrapper.rb
@@ -0,0 +1,80 @@
+require 'rbconfig'
+
+class SystemWrapper
+
+ # static method for use in defaults
+ def self.windows?
+ return ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) if defined?(RbConfig)
+ return ((Config::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false)
+ end
+
+ # class method so as to be mockable for tests
+ def windows?
+ return SystemWrapper.windows?
+ end
+
+ def module_eval(string)
+ return Object.module_eval("\"" + string + "\"")
+ end
+
+ def eval(string)
+ return eval(string)
+ end
+
+ def search_paths
+ return ENV['PATH'].split(File::PATH_SEPARATOR)
+ end
+
+ def cmdline_args
+ return ARGV
+ end
+
+ def env_set(name, value)
+ ENV[name] = value
+ end
+
+ def env_get(name)
+ return ENV[name]
+ end
+
+ def time_now
+ return Time.now.asctime
+ end
+
+ def shell_backticks(command, boom = true)
+ retval = `#{command}`.freeze
+ $exit_code = ($?.exitstatus).freeze if boom
+ return {
+ :output => retval.freeze,
+ :exit_code => ($?.exitstatus).freeze
+ }
+ end
+
+ def shell_system(command, boom = true)
+ system( command )
+ $exit_code = ($?.exitstatus).freeze if boom
+ return {
+ :output => "".freeze,
+ :exit_code => ($?.exitstatus).freeze
+ }
+ end
+
+ def add_load_path(path)
+ $LOAD_PATH.unshift(path)
+ end
+
+ def require_file(path)
+ require(path)
+ end
+
+ def ruby_success
+ # We are successful if we've never had an exit code that went boom (either because it's empty or it was 0)
+ return ($exit_code.nil? || ($exit_code == 0)) && ($!.nil? || $!.is_a?(SystemExit) && $!.success?)
+ end
+
+ def constants_include?(item)
+ # forcing to strings provides consistency across Ruby versions
+ return Object.constants.map{|constant| constant.to_s}.include?(item.to_s)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/target_loader.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/target_loader.rb
new file mode 100755
index 00000000..7fbc0959
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/target_loader.rb
@@ -0,0 +1,38 @@
+module TargetLoader
+ class NoTargets < Exception; end
+ class NoDirectory < Exception; end
+ class NoDefault < Exception; end
+ class NoSuchTarget < Exception; end
+
+ class RequestReload < Exception; end
+
+ def self.inspect(config, target_name=nil)
+ unless config[:targets]
+ raise NoTargets
+ end
+
+ targets = config[:targets]
+ unless targets[:targets_directory]
+ raise NoDirectory.new("No targets directory specified.")
+ end
+ unless targets[:default_target]
+ raise NoDefault.new("No default target specified.")
+ end
+
+ target_path = lambda {|name| File.join(targets[:targets_directory], name + ".yml")}
+
+ target = if target_name
+ target_path.call(target_name)
+ else
+ target_path.call(targets[:default_target])
+ end
+
+ unless File.exists? target
+ raise NoSuchTarget.new("No such target: #{target}")
+ end
+
+ ENV['CEEDLING_MAIN_PROJECT_FILE'] = target
+
+ raise RequestReload
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/task_invoker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/task_invoker.rb
new file mode 100755
index 00000000..642695c4
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/task_invoker.rb
@@ -0,0 +1,117 @@
+require 'ceedling/par_map'
+
+class TaskInvoker
+
+ attr_accessor :first_run
+
+ constructor :dependinator, :rake_utils, :rake_wrapper, :project_config_manager
+
+ def setup
+ @test_regexs = [/^#{TEST_ROOT_NAME}:/]
+ @release_regexs = [/^#{RELEASE_ROOT_NAME}(:|$)/]
+ @first_run = true
+ end
+
+ def add_test_task_regex(regex)
+ @test_regexs << regex
+ end
+
+ def add_release_task_regex(regex)
+ @release_regexs << regex
+ end
+
+ def test_invoked?
+ invoked = false
+
+ @test_regexs.each do |regex|
+ invoked = true if (@rake_utils.task_invoked?(regex))
+ break if invoked
+ end
+
+ return invoked
+ end
+
+ def release_invoked?
+ invoked = false
+
+ @release_regexs.each do |regex|
+ invoked = true if (@rake_utils.task_invoked?(regex))
+ break if invoked
+ end
+
+ return invoked
+ end
+
+ def invoked?(regex)
+ return @rake_utils.task_invoked?(regex)
+ end
+
+
+ def invoke_test_mocks(mocks)
+ @dependinator.enhance_mock_dependencies( mocks )
+ mocks.each { |mock|
+ @rake_wrapper[mock].reenable if @first_run == false && @project_config_manager.test_defines_changed
+ @rake_wrapper[mock].invoke
+ }
+ end
+
+ def invoke_test_runner(runner)
+ @dependinator.enhance_runner_dependencies( runner )
+ @rake_wrapper[runner].reenable if @first_run == false && @project_config_manager.test_defines_changed
+ @rake_wrapper[runner].invoke
+ end
+
+ def invoke_test_shallow_include_lists(files)
+ @dependinator.enhance_shallow_include_lists_dependencies( files )
+ par_map(PROJECT_COMPILE_THREADS, files) do |file|
+ @rake_wrapper[file].reenable if @first_run == false && @project_config_manager.test_defines_changed
+ @rake_wrapper[file].invoke
+ end
+ end
+
+ def invoke_test_preprocessed_files(files)
+ @dependinator.enhance_preprocesed_file_dependencies( files )
+ par_map(PROJECT_COMPILE_THREADS, files) do |file|
+ @rake_wrapper[file].reenable if @first_run == false && @project_config_manager.test_defines_changed
+ @rake_wrapper[file].invoke
+ end
+ end
+
+ def invoke_test_dependencies_files(files)
+ @dependinator.enhance_dependencies_dependencies( files )
+ par_map(PROJECT_COMPILE_THREADS, files) do |file|
+ @rake_wrapper[file].reenable if @first_run == false && @project_config_manager.test_defines_changed
+ @rake_wrapper[file].invoke
+ end
+ end
+
+ def invoke_test_objects(objects)
+ par_map(PROJECT_COMPILE_THREADS, objects) do |object|
+ @rake_wrapper[object].reenable if @first_run == false && @project_config_manager.test_defines_changed
+ @rake_wrapper[object].invoke
+ end
+ end
+
+ def invoke_test_executable(file)
+ @rake_wrapper[file].invoke
+ end
+
+ def invoke_test_results(result)
+ @dependinator.enhance_results_dependencies( result )
+ @rake_wrapper[result].reenable if @first_run == false && @project_config_manager.test_defines_changed
+ @rake_wrapper[result].invoke
+ end
+
+ def invoke_release_dependencies_files(files)
+ par_map(PROJECT_COMPILE_THREADS, files) do |file|
+ @rake_wrapper[file].invoke
+ end
+ end
+
+ def invoke_release_objects(objects)
+ par_map(PROJECT_COMPILE_THREADS, objects) do |object|
+ @rake_wrapper[object].invoke
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_base.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_base.rake
new file mode 100755
index 00000000..8c825309
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_base.rake
@@ -0,0 +1,111 @@
+require 'ceedling/constants'
+require 'ceedling/file_path_utils'
+require 'ceedling/version'
+
+desc "Display build environment version info."
+task :version do
+ puts " Ceedling:: #{Ceedling::Version::CEEDLING}"
+
+ [
+ ['CException', File.join( CEEDLING_VENDOR, CEXCEPTION_ROOT_PATH)],
+ [' CMock', File.join( CEEDLING_VENDOR, CMOCK_ROOT_PATH)],
+ [' Unity', File.join( CEEDLING_VENDOR, UNITY_ROOT_PATH)],
+ ].each do |tool|
+ name = tool[0]
+ base_path = tool[1]
+
+ version_string = begin
+ @ceedling[:file_wrapper].read( File.join(base_path, 'release', 'version.info') ).strip
+ rescue
+ "UNKNOWN"
+ end
+ build_string = begin
+ @ceedling[:file_wrapper].read( File.join(base_path, 'release', 'build.info') ).strip
+ rescue
+ "UNKNOWN"
+ end
+ puts "#{name}:: #{version_string.empty? ? '#.#.' : (version_string + '.')}#{build_string.empty? ? '?' : build_string}"
+ end
+end
+
+desc "Set verbose output (silent:[#{Verbosity::SILENT}] - obnoxious:[#{Verbosity::OBNOXIOUS}])."
+task :verbosity, :level do |t, args|
+ verbosity_level = args.level.to_i
+
+ if (PROJECT_USE_MOCKS)
+ # don't store verbosity level in setupinator's config hash, use a copy;
+ # otherwise, the input configuration will change and trigger entire project rebuilds
+ hash = @ceedling[:setupinator].config_hash[:cmock].clone
+ hash[:verbosity] = verbosity_level
+
+ @ceedling[:cmock_builder].manufacture( hash )
+ end
+
+ @ceedling[:configurator].project_verbosity = verbosity_level
+
+ # control rake's verbosity with new setting
+ verbose( ((verbosity_level >= Verbosity::OBNOXIOUS) ? true : false) )
+end
+
+desc "Enable logging"
+task :logging do
+ @ceedling[:configurator].project_logging = true
+end
+
+# non advertised debug task
+task :debug do
+ Rake::Task[:verbosity].invoke(Verbosity::DEBUG)
+ Rake.application.options.trace = true
+ @ceedling[:configurator].project_debug = true
+end
+
+# non advertised sanity checking task
+task :sanity_checks, :level do |t, args|
+ check_level = args.level.to_i
+ @ceedling[:configurator].sanity_checks = check_level
+end
+
+# list expanded environment variables
+if (not ENVIRONMENT.empty?)
+desc "List all configured environment variables."
+task :environment do
+ env_list = []
+ ENVIRONMENT.each do |env|
+ env.each_key do |key|
+ name = key.to_s.upcase
+ env_list.push(" - #{name}: \"#{env[key]}\"")
+ end
+ end
+ env_list.sort.each do |env_line|
+ puts env_line
+ end
+end
+end
+
+namespace :options do
+
+ COLLECTION_PROJECT_OPTIONS.each do |option_path|
+ option = File.basename(option_path, '.yml')
+
+ desc "Merge #{option} project options."
+ task option.downcase.to_sym do
+ hash = @ceedling[:project_config_manager].merge_options( @ceedling[:setupinator].config_hash, option_path )
+ @ceedling[:setupinator].do_setup( hash )
+ if @ceedling[:configurator].project_release_build
+ load(File.join(CEEDLING_LIB, 'ceedling', 'rules_release.rake'))
+ end
+ end
+ end
+
+end
+
+
+# do not present task if there's no plugins
+if (not PLUGINS_ENABLED.empty?)
+desc "Execute plugin result summaries (no build triggering)."
+task :summary do
+ @ceedling[:plugin_manager].summary
+ puts "\nNOTE: Summaries may be out of date with project sources.\n\n"
+end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_filesystem.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_filesystem.rake
new file mode 100755
index 00000000..58fa6511
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_filesystem.rake
@@ -0,0 +1,103 @@
+
+# rather than require 'rake/clean' & try to override, we replicate for finer control
+CLEAN = Rake::FileList["**/*~", "**/*.bak"]
+CLOBBER = Rake::FileList.new
+
+CLEAN.clear_exclude.exclude { |fn| fn.pathmap("%f") == 'core' && File.directory?(fn) }
+
+CLEAN.include(File.join(PROJECT_TEST_BUILD_OUTPUT_PATH, '*'))
+CLEAN.include(File.join(PROJECT_TEST_RESULTS_PATH, '*'))
+CLEAN.include(File.join(PROJECT_TEST_DEPENDENCIES_PATH, '*'))
+CLEAN.include(File.join(PROJECT_BUILD_RELEASE_ROOT, '*.*'))
+CLEAN.include(File.join(PROJECT_RELEASE_BUILD_OUTPUT_PATH, '*'))
+CLEAN.include(File.join(PROJECT_RELEASE_DEPENDENCIES_PATH, '*'))
+
+CLOBBER.include(File.join(PROJECT_BUILD_ARTIFACTS_ROOT, '**/*'))
+CLOBBER.include(File.join(PROJECT_BUILD_TESTS_ROOT, '**/*'))
+CLOBBER.include(File.join(PROJECT_BUILD_RELEASE_ROOT, '**/*'))
+CLOBBER.include(File.join(PROJECT_LOG_PATH, '**/*'))
+CLOBBER.include(File.join(PROJECT_TEMP_PATH, '**/*'))
+
+# just in case they're using git, let's make sure we allow them to preserved the build directory if desired.
+CLOBBER.exclude(File.join(TESTS_BASE_PATH), '**/.gitkeep')
+
+# because of cmock config, mock path can optionally exist apart from standard test build paths
+CLOBBER.include(File.join(CMOCK_MOCK_PATH, '*'))
+
+REMOVE_FILE_PROC = Proc.new { |fn| rm_r fn rescue nil }
+
+# redefine clean so we can override how it advertises itself
+desc "Delete all build artifacts and temporary products."
+task(:clean) do
+ # because :clean is a prerequisite for :clobber, intelligently display the progress message
+ if (not @ceedling[:task_invoker].invoked?(/^clobber$/))
+ @ceedling[:streaminator].stdout_puts("\nCleaning build artifacts...\n(For large projects, this task may take a long time to complete)\n\n")
+ end
+ begin
+ CLEAN.each { |fn| REMOVE_FILE_PROC.call(fn) }
+ rescue
+ end
+end
+
+# redefine clobber so we can override how it advertises itself
+desc "Delete all generated files (and build artifacts)."
+task(:clobber => [:clean]) do
+ @ceedling[:streaminator].stdout_puts("\nClobbering all generated files...\n(For large projects, this task may take a long time to complete)\n\n")
+ begin
+ CLOBBER.each { |fn| REMOVE_FILE_PROC.call(fn) }
+ rescue
+ end
+end
+
+
+PROJECT_BUILD_PATHS.each { |path| directory(path) }
+
+# create directories that hold build output and generated files & touching rebuild dependency sources
+task(:directories => PROJECT_BUILD_PATHS) { @ceedling[:dependinator].touch_force_rebuild_files }
+
+
+# list paths discovered at load time
+namespace :paths do
+
+ paths = @ceedling[:setupinator].config_hash[:paths]
+ paths.each_key do |section|
+ name = section.to_s.downcase
+ path_list = Object.const_get("COLLECTION_PATHS_#{name.upcase}")
+
+ if (path_list.size != 0)
+ desc "List all collected #{name} paths."
+ task(name.to_sym) { puts "#{name} paths:"; path_list.sort.each {|path| puts " - #{path}" } }
+ end
+ end
+
+end
+
+
+# list files & file counts discovered at load time
+namespace :files do
+
+ categories = [
+ ['test', COLLECTION_ALL_TESTS],
+ ['source', COLLECTION_ALL_SOURCE],
+ ['header', COLLECTION_ALL_HEADERS]
+ ]
+
+ using_assembly = (defined?(TEST_BUILD_USE_ASSEMBLY) && TEST_BUILD_USE_ASSEMBLY) ||
+ (defined?(RELEASE_BUILD_USE_ASSEMBLY) && RELEASE_BUILD_USE_ASSEMBLY)
+ categories << ['assembly', COLLECTION_ALL_ASSEMBLY] if using_assembly
+
+ categories.each do |category|
+ name = category[0]
+ collection = category[1]
+
+ desc "List all collected #{name} files."
+ task(name.to_sym) do
+ puts "#{name} files:"
+ collection.sort.each { |filepath| puts " - #{filepath}" }
+ puts "file count: #{collection.size}"
+ end
+ end
+
+end
+
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release.rake
new file mode 100755
index 00000000..b313b2f5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release.rake
@@ -0,0 +1,30 @@
+require 'ceedling/constants'
+require 'ceedling/file_path_utils'
+
+
+desc "Build release target."
+task RELEASE_SYM => [:directories] do
+ header = "Release build '#{File.basename(PROJECT_RELEASE_BUILD_TARGET)}'"
+ @ceedling[:streaminator].stdout_puts("\n\n#{header}\n#{'-' * header.length}")
+
+ begin
+ @ceedling[:plugin_manager].pre_release
+
+ core_objects = []
+ extra_objects = @ceedling[:file_path_utils].form_release_build_c_objects_filelist( COLLECTION_RELEASE_ARTIFACT_EXTRA_LINK_OBJECTS )
+
+ @ceedling[:project_config_manager].process_release_config_change
+ core_objects.concat( @ceedling[:release_invoker].setup_and_invoke_c_objects( COLLECTION_ALL_SOURCE ) )
+
+ # if assembler use isn't enabled, COLLECTION_ALL_ASSEMBLY is empty array & nothing happens
+ core_objects.concat( @ceedling[:release_invoker].setup_and_invoke_asm_objects( COLLECTION_ALL_ASSEMBLY ) )
+
+ # if we're using libraries, we need to add those to our collection as well
+ library_objects = (defined? LIBRARIES_RELEASE && !LIBRARIES_RELEASE.empty?) ? LIBRARIES_RELEASE.flatten.compact : []
+ file( PROJECT_RELEASE_BUILD_TARGET => (core_objects + extra_objects + library_objects) )
+ Rake::Task[PROJECT_RELEASE_BUILD_TARGET].invoke
+ ensure
+ @ceedling[:plugin_manager].post_release
+ end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake
new file mode 100755
index 00000000..db2be5f3
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_release_deep_dependencies.rake
@@ -0,0 +1,9 @@
+require 'ceedling/constants'
+
+namespace REFRESH_SYM do
+
+ task RELEASE_SYM do
+ @ceedling[:release_invoker].refresh_c_deep_dependencies
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests.rake
new file mode 100755
index 00000000..5d09c1af
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests.rake
@@ -0,0 +1,60 @@
+require 'ceedling/constants'
+
+task :test => [:directories] do
+ Rake.application['test:all'].invoke
+end
+
+namespace TEST_SYM do
+
+ desc "Run all unit tests (also just 'test' works)."
+ task :all => [:directories] do
+ @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS)
+ end
+
+ desc "Run single test ([*] real test or source file name, no path)."
+ task :* do
+ message = "\nOops! '#{TEST_ROOT_NAME}:*' isn't a real task. " +
+ "Use a real test or source file name (no path) in place of the wildcard.\n" +
+ "Example: rake #{TEST_ROOT_NAME}:foo.c\n\n"
+
+ @ceedling[:streaminator].stdout_puts( message )
+ end
+
+ desc "Run tests for changed files."
+ task :delta => [:directories] do
+ @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TEST_SYM, {:force_run => false})
+ end
+
+ desc "Just build tests without running."
+ task :build_only => [:directories] do
+ @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, TEST_SYM, {:build_only => true})
+ end
+
+ desc "Run tests by matching regular expression pattern."
+ task :pattern, [:regex] => [:directories] do |t, args|
+ matches = []
+
+ COLLECTION_ALL_TESTS.each { |test| matches << test if (test =~ /#{args.regex}/) }
+
+ if (matches.size > 0)
+ @ceedling[:test_invoker].setup_and_invoke(matches, TEST_SYM, {:force_run => false})
+ else
+ @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.")
+ end
+ end
+
+ desc "Run tests whose test path contains [dir] or [dir] substring."
+ task :path, [:dir] => [:directories] do |t, args|
+ matches = []
+
+ COLLECTION_ALL_TESTS.each { |test| matches << test if File.dirname(test).include?(args.dir.gsub(/\\/, '/')) }
+
+ if (matches.size > 0)
+ @ceedling[:test_invoker].setup_and_invoke(matches, TEST_SYM, {:force_run => false})
+ else
+ @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.")
+ end
+ end
+
+end
+
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake
new file mode 100755
index 00000000..f8994071
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_tests_deep_dependencies.rake
@@ -0,0 +1,9 @@
+require 'ceedling/constants'
+
+namespace REFRESH_SYM do
+
+ task TEST_SYM do
+ @ceedling[:test_invoker].refresh_deep_dependencies
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_vendor.rake b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_vendor.rake
new file mode 100755
index 00000000..63c2ca55
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tasks_vendor.rake
@@ -0,0 +1,35 @@
+require 'ceedling/constants'
+require 'ceedling/file_path_utils'
+
+# create file dependencies to ensure C-based components of vendor tools are recompiled when they are updated with new versions
+# forming these explicitly rather than depend on auxiliary dependencies so all scenarios are explicitly covered
+
+file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( UNITY_C_FILE ) => [
+ File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_C_FILE ),
+ File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_H_FILE ),
+ File.join( UNITY_VENDOR_PATH, UNITY_LIB_PATH, UNITY_INTERNALS_H_FILE ) ]
+ )
+
+
+if (PROJECT_USE_MOCKS)
+file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( CMOCK_C_FILE ) => [
+ File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, CMOCK_C_FILE ),
+ File.join( CMOCK_VENDOR_PATH, CMOCK_LIB_PATH, CMOCK_H_FILE ) ]
+ )
+end
+
+
+if (PROJECT_USE_EXCEPTIONS)
+file( @ceedling[:file_path_utils].form_test_build_c_object_filepath( CEXCEPTION_C_FILE ) => [
+ File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_C_FILE ),
+ File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_H_FILE ) ]
+ )
+end
+
+
+if (PROJECT_USE_EXCEPTIONS and PROJECT_RELEASE_BUILD)
+file( @ceedling[:file_path_utils].form_release_build_c_object_filepath( CEXCEPTION_C_FILE ) => [
+ File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_C_FILE ),
+ File.join( CEXCEPTION_VENDOR_PATH, CEXCEPTION_LIB_PATH, CEXCEPTION_H_FILE ) ]
+ )
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/test_includes_extractor.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/test_includes_extractor.rb
new file mode 100755
index 00000000..50cc7c04
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/test_includes_extractor.rb
@@ -0,0 +1,85 @@
+
+class TestIncludesExtractor
+
+ constructor :configurator, :yaml_wrapper, :file_wrapper
+
+ def setup
+ @includes = {}
+ @mocks = {}
+ end
+
+
+ # for includes_list file, slurp up array from yaml file and sort & store includes
+ def parse_includes_list(includes_list)
+ gather_and_store_includes( includes_list, @yaml_wrapper.load(includes_list) )
+ end
+
+ # open, scan for, and sort & store includes of test file
+ def parse_test_file(test)
+ gather_and_store_includes( test, extract_from_file(test) )
+ end
+
+ # mocks with no file extension
+ def lookup_raw_mock_list(test)
+ file_key = form_file_key(test)
+ return [] if @mocks[file_key].nil?
+ return @mocks[file_key]
+ end
+
+ # includes with file extension
+ def lookup_includes_list(file)
+ file_key = form_file_key(file)
+ return [] if (@includes[file_key]).nil?
+ return @includes[file_key]
+ end
+
+ private #################################
+
+ def form_file_key(filepath)
+ return File.basename(filepath).to_sym
+ end
+
+ def extract_from_file(file)
+ includes = []
+ header_extension = @configurator.extension_header
+
+ contents = @file_wrapper.read(file)
+
+ # remove line comments
+ contents = contents.gsub(/\/\/.*$/, '')
+ # remove block comments
+ contents = contents.gsub(/\/\*.*?\*\//m, '')
+
+ contents.split("\n").each do |line|
+ # look for include statement
+ scan_results = line.scan(/#include\s+\"\s*(.+#{'\\'+header_extension})\s*\"/)
+
+ includes << scan_results[0][0] if (scan_results.size > 0)
+
+ # look for TEST_FILE statement
+ scan_results = line.scan(/TEST_FILE\(\s*\"\s*(.+\.\w+)\s*\"\s*\)/)
+
+ includes << scan_results[0][0] if (scan_results.size > 0)
+ end
+
+ return includes.uniq
+ end
+
+ def gather_and_store_includes(file, includes)
+ mock_prefix = @configurator.cmock_mock_prefix
+ header_extension = @configurator.extension_header
+ file_key = form_file_key(file)
+ @mocks[file_key] = []
+
+ # add includes to lookup hash
+ @includes[file_key] = includes
+
+ includes.each do |include_file|
+ # check if include is a mock
+ scan_results = include_file.scan(/(#{mock_prefix}.+)#{'\\'+header_extension}/)
+ # add mock to lookup hash
+ @mocks[file_key] << scan_results[0][0] if (scan_results.size > 0)
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker.rb
new file mode 100755
index 00000000..652cb318
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker.rb
@@ -0,0 +1,188 @@
+require 'ceedling/constants'
+
+
+class TestInvoker
+
+ attr_reader :sources, :tests, :mocks
+
+ constructor :configurator,
+ :test_invoker_helper,
+ :plugin_manager,
+ :streaminator,
+ :preprocessinator,
+ :task_invoker,
+ :dependinator,
+ :project_config_manager,
+ :build_invoker_utils,
+ :file_path_utils,
+ :file_wrapper
+
+ def setup
+ @sources = []
+ @tests = []
+ @mocks = []
+ end
+
+ def get_test_definition_str(test)
+ return "-D" + File.basename(test, File.extname(test)).upcase.sub(/@.*$/, "")
+ end
+
+ def get_tools_compilers
+ tools_compilers = Hash.new
+ tools_compilers["for unit test"] = TOOLS_TEST_COMPILER if defined? TOOLS_TEST_COMPILER
+ tools_compilers["for gcov"] = TOOLS_GCOV_COMPILER if defined? TOOLS_GCOV_COMPILER
+ return tools_compilers
+ end
+
+ def add_test_definition(test)
+ test_definition_str = get_test_definition_str(test)
+ get_tools_compilers.each do |tools_compiler_key, tools_compiler_value|
+ tools_compiler_value[:arguments].push("-D#{File.basename(test, ".*").strip.upcase.sub(/@.*$/, "")}")
+ @streaminator.stdout_puts("Add the definition value in the build option #{tools_compiler_value[:arguments][-1]} #{tools_compiler_key}", Verbosity::OBNOXIOUS)
+ end
+ end
+
+ def delete_test_definition(test)
+ test_definition_str = get_test_definition_str(test)
+ get_tools_compilers.each do |tools_compiler_key, tools_compiler_value|
+ num_options = tools_compiler_value[:arguments].size
+ @streaminator.stdout_puts("Delete the definition value in the build option #{tools_compiler_value[:arguments][-1]} #{tools_compiler_key}", Verbosity::OBNOXIOUS)
+ tools_compiler_value[:arguments].delete_if{|i| i == test_definition_str}
+ if num_options > tools_compiler_value[:arguments].size + 1
+ @streaminator.stderr_puts("WARNING: duplicated test definition.")
+ end
+ end
+ end
+
+ # Convert libraries configuration form YAML configuration
+ # into a string that can be given to the compiler.
+ def convert_libraries_to_arguments()
+ if @configurator.project_config_hash.has_key?(:libraries_test)
+ lib_args = @configurator.project_config_hash[:libraries_test]
+ lib_args.flatten!
+ lib_flag = @configurator.project_config_hash[:libraries_flag]
+ lib_args.map! {|v| lib_flag.gsub(/\$\{1\}/, v) } if (defined? lib_flag)
+ return lib_args
+ end
+ end
+
+
+ def setup_and_invoke(tests, context=TEST_SYM, options={:force_run => true, :build_only => false})
+
+ @tests = tests
+
+ @project_config_manager.process_test_config_change
+
+ @tests.each do |test|
+ # announce beginning of test run
+ header = "Test '#{File.basename(test)}'"
+ @streaminator.stdout_puts("\n\n#{header}\n#{'-' * header.length}")
+
+ begin
+ @plugin_manager.pre_test( test )
+ test_name ="#{File.basename(test)}".chomp('.c')
+ def_test_key="defines_#{test_name.downcase}"
+
+ # Re-define the project out path and pre-processor defines.
+ if @configurator.project_config_hash.has_key?(def_test_key.to_sym)
+ @project_config_manager.test_config_changed
+ defs_bkp = Array.new(COLLECTION_DEFINES_TEST_AND_VENDOR)
+ printf " ************** Specific test definitions for #{test_name} !!! \n"
+ tst_defs_cfg = @configurator.project_config_hash[def_test_key.to_sym]
+
+ orig_path = @configurator.project_test_build_output_path
+ @configurator.project_config_hash[:project_test_build_output_path] = File.join(@configurator.project_test_build_output_path, test_name)
+ @file_wrapper.mkdir(@configurator.project_test_build_output_path)
+ COLLECTION_DEFINES_TEST_AND_VENDOR.replace(tst_defs_cfg)
+ # printf " * new defines = #{COLLECTION_DEFINES_TEST_AND_VENDOR}\n"
+ end
+
+ # collect up test fixture pieces & parts
+ runner = @file_path_utils.form_runner_filepath_from_test( test )
+ mock_list = @preprocessinator.preprocess_test_and_invoke_test_mocks( test )
+ sources = @test_invoker_helper.extract_sources( test )
+ extras = @configurator.collection_test_fixture_extra_link_objects
+ core = [test] + mock_list + sources
+ objects = @file_path_utils.form_test_build_objects_filelist( [runner] + core + extras )
+ results_pass = @file_path_utils.form_pass_results_filepath( test )
+ results_fail = @file_path_utils.form_fail_results_filepath( test )
+
+ @project_config_manager.process_test_defines_change(sources)
+
+ # add the definition value in the build option for the unit test
+ if @configurator.defines_use_test_definition
+ add_test_definition(test)
+ end
+
+ # clean results files so we have a missing file with which to kick off rake's dependency rules
+ @test_invoker_helper.clean_results( {:pass => results_pass, :fail => results_fail}, options )
+
+ # load up auxiliary dependencies so deep changes cause rebuilding appropriately
+ @test_invoker_helper.process_deep_dependencies( core ) do |dependencies_list|
+ @dependinator.load_test_object_deep_dependencies( dependencies_list )
+ end
+
+ # tell rake to create test runner if needed
+ @task_invoker.invoke_test_runner( runner )
+
+ # enhance object file dependencies to capture externalities influencing regeneration
+ @dependinator.enhance_test_build_object_dependencies( objects )
+
+ # associate object files with executable
+ @dependinator.setup_test_executable_dependencies( test, objects )
+
+ # build test objects
+ @task_invoker.invoke_test_objects( objects )
+
+ # if the option build_only has been specified, build only the executable
+ # but don't run the test
+ if (options[:build_only])
+ executable = @file_path_utils.form_test_executable_filepath( test )
+ @task_invoker.invoke_test_executable( executable )
+ else
+ # 3, 2, 1... launch
+ @task_invoker.invoke_test_results( results_pass )
+ end
+ rescue => e
+ @build_invoker_utils.process_exception( e, context )
+ ensure
+ # delete the definition value in the build option for the unit test
+ if @configurator.defines_use_test_definition
+ delete_test_definition(test)
+ end
+ @plugin_manager.post_test( test )
+ # restore the project test defines
+ if @configurator.project_config_hash.has_key?(def_test_key.to_sym)
+ # @configurator.project_config_hash[:defines_test] =
+ COLLECTION_DEFINES_TEST_AND_VENDOR.replace(defs_bkp)
+ # printf " ---- Restored defines at #{defs_bkp}"
+ @configurator.project_config_hash[:project_test_build_output_path] = orig_path
+ printf " ************** Restored defines and build path\n"
+ end
+ end
+
+ # store away what's been processed
+ @mocks.concat( mock_list )
+ @sources.concat( sources )
+
+ @task_invoker.first_run = false
+ end
+
+ # post-process collected mock list
+ @mocks.uniq!
+
+ # post-process collected sources list
+ @sources.uniq!
+ end
+
+
+ def refresh_deep_dependencies
+ @file_wrapper.rm_f(
+ @file_wrapper.directory_listing(
+ File.join( @configurator.project_test_dependencies_path, '*' + @configurator.extension_dependencies ) ) )
+
+ @test_invoker_helper.process_deep_dependencies(
+ @configurator.collection_all_tests + @configurator.collection_all_source )
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker_helper.rb
new file mode 100755
index 00000000..b0a223f5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/test_invoker_helper.rb
@@ -0,0 +1,32 @@
+
+class TestInvokerHelper
+
+ constructor :configurator, :task_invoker, :test_includes_extractor, :file_finder, :file_path_utils, :file_wrapper
+
+ def clean_results(results, options)
+ @file_wrapper.rm_f( results[:fail] )
+ @file_wrapper.rm_f( results[:pass] ) if (options[:force_run])
+ end
+
+ def process_deep_dependencies(files)
+ return if (not @configurator.project_use_deep_dependencies)
+
+ dependencies_list = @file_path_utils.form_test_dependencies_filelist( files )
+
+ if @configurator.project_generate_deep_dependencies
+ @task_invoker.invoke_test_dependencies_files( dependencies_list )
+ end
+
+ yield( dependencies_list ) if block_given?
+ end
+
+ def extract_sources(test)
+ sources = []
+ includes = @test_includes_extractor.lookup_includes_list(test)
+
+ includes.each { |include| sources << @file_finder.find_compilation_input_file(include, :ignore) }
+
+ return sources.compact
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor.rb
new file mode 100755
index 00000000..0ab5ddca
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor.rb
@@ -0,0 +1,229 @@
+require 'ceedling/constants'
+require 'benchmark'
+
+class ShellExecutionException < RuntimeError
+ attr_reader :shell_result
+ def initialize(shell_result)
+ @shell_result = shell_result
+ end
+end
+
+class ToolExecutor
+
+ constructor :configurator, :tool_executor_helper, :streaminator, :system_wrapper
+
+ def setup
+ @tool_name = ''
+ @executable = ''
+ end
+
+ # build up a command line from yaml provided config
+
+ # @param extra_params is an array of parameters to append to executable
+ def build_command_line(tool_config, extra_params, *args)
+ @tool_name = tool_config[:name]
+ @executable = tool_config[:executable]
+
+ command = {}
+
+ # basic premise is to iterate top to bottom through arguments using '$' as
+ # a string replacement indicator to expand globals or inline yaml arrays
+ # into command line arguments via substitution strings
+ # executable must be quoted if it includes spaces (common on windows)
+ executable = @tool_executor_helper.osify_path_separators( expandify_element(@executable, *args) )
+ executable = "\"#{executable}\"" if executable.include?(' ')
+ command[:line] = [
+ executable,
+ extra_params.join(' ').strip,
+ build_arguments(tool_config[:arguments], *args),
+ ].reject{|s| s.nil? || s.empty?}.join(' ').strip
+
+ command[:options] = {
+ :stderr_redirect => @tool_executor_helper.stderr_redirection(tool_config, @configurator.project_logging),
+ :background_exec => tool_config[:background_exec]
+ }
+
+ return command
+ end
+
+
+ # shell out, execute command, and return response
+ def exec(command, options={}, args=[])
+ options[:boom] = true if (options[:boom].nil?)
+ options[:stderr_redirect] = StdErrRedirect::NONE if (options[:stderr_redirect].nil?)
+ options[:background_exec] = BackgroundExec::NONE if (options[:background_exec].nil?)
+ # build command line
+ command_line = [
+ @tool_executor_helper.background_exec_cmdline_prepend( options ),
+ command.strip,
+ args,
+ @tool_executor_helper.stderr_redirect_cmdline_append( options ),
+ @tool_executor_helper.background_exec_cmdline_append( options ),
+ ].flatten.compact.join(' ')
+
+ @streaminator.stderr_puts("Verbose: #{__method__.to_s}(): #{command_line}", Verbosity::DEBUG)
+
+ shell_result = {}
+
+ # depending on background exec option, we shell out differently
+ time = Benchmark.realtime do
+ if (options[:background_exec] != BackgroundExec::NONE)
+ shell_result = @system_wrapper.shell_system( command_line, options[:boom] )
+ else
+ shell_result = @system_wrapper.shell_backticks( command_line, options[:boom] )
+ end
+ end
+ shell_result[:time] = time
+
+ #scrub the string for illegal output
+ unless shell_result[:output].nil?
+ shell_result[:output] = shell_result[:output].scrub if "".respond_to?(:scrub)
+ shell_result[:output].gsub!(/\033\[\d\dm/,'')
+ end
+
+ @tool_executor_helper.print_happy_results( command_line, shell_result, options[:boom] )
+ @tool_executor_helper.print_error_results( command_line, shell_result, options[:boom] )
+
+ # go boom if exit code isn't 0 (but in some cases we don't want a non-0 exit code to raise)
+ raise ShellExecutionException.new(shell_result) if ((shell_result[:exit_code] != 0) and options[:boom])
+
+ return shell_result
+ end
+
+
+ private #############################
+
+
+ def build_arguments(config, *args)
+ build_string = ''
+
+ return nil if (config.nil?)
+
+ # iterate through each argument
+
+ # the yaml blob array needs to be flattened so that yaml substitution
+ # is handled correctly, since it creates a nested array when an anchor is
+ # dereferenced
+ config.flatten.each do |element|
+ argument = ''
+
+ case(element)
+ # if we find a simple string then look for string replacement operators
+ # and expand with the parameters in this method's argument list
+ when String then argument = expandify_element(element, *args)
+ # if we find a hash, then we grab the key as a substitution string and expand the
+ # hash's value(s) within that substitution string
+ when Hash then argument = dehashify_argument_elements(element)
+ end
+
+ build_string.concat("#{argument} ") if (argument.length > 0)
+ end
+
+ build_string.strip!
+ return build_string if (build_string.length > 0)
+ return nil
+ end
+
+
+ # handle simple text string argument & argument array string replacement operators
+ def expandify_element(element, *args)
+ match = //
+ to_process = nil
+ args_index = 0
+
+ # handle ${#} input replacement
+ if (element =~ TOOL_EXECUTOR_ARGUMENT_REPLACEMENT_PATTERN)
+ args_index = ($2.to_i - 1)
+
+ if (args.nil? or args[args_index].nil?)
+ @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' expected valid argument data to accompany replacement operator #{$1}.", Verbosity::ERRORS)
+ raise
+ end
+
+ match = /#{Regexp.escape($1)}/
+ to_process = args[args_index]
+ end
+
+ # simple string argument: replace escaped '\$' and strip
+ element.sub!(/\\\$/, '$')
+ element.strip!
+
+ # handle inline ruby execution
+ if (element =~ RUBY_EVAL_REPLACEMENT_PATTERN)
+ element.replace(eval($1))
+ end
+
+ build_string = ''
+
+ # handle array or anything else passed into method to be expanded in place of replacement operators
+ case (to_process)
+ when Array then to_process.each {|value| build_string.concat( "#{element.sub(match, value.to_s)} " ) } if (to_process.size > 0)
+ else build_string.concat( element.sub(match, to_process.to_s) )
+ end
+
+ # handle inline ruby string substitution
+ if (build_string =~ RUBY_STRING_REPLACEMENT_PATTERN)
+ build_string.replace(@system_wrapper.module_eval(build_string))
+ end
+
+ return build_string.strip
+ end
+
+
+ # handle argument hash: keys are substitution strings, values are data to be expanded within substitution strings
+ def dehashify_argument_elements(hash)
+ build_string = ''
+ elements = []
+
+ # grab the substitution string (hash key)
+ substitution = hash.keys[0].to_s
+ # grab the string(s) to squirt into the substitution string (hash value)
+ expand = hash[hash.keys[0]]
+
+ if (expand.nil?)
+ @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' could not expand nil elements for substitution string '#{substitution}'.", Verbosity::ERRORS)
+ raise
+ end
+
+ # array-ify expansion input if only a single string
+ expansion = ((expand.class == String) ? [expand] : expand)
+
+ expansion.each do |item|
+ # code eval substitution
+ if (item =~ RUBY_EVAL_REPLACEMENT_PATTERN)
+ elements << eval($1)
+ # string eval substitution
+ elsif (item =~ RUBY_STRING_REPLACEMENT_PATTERN)
+ elements << @system_wrapper.module_eval(item)
+ # global constants
+ elsif (@system_wrapper.constants_include?(item))
+ const = Object.const_get(item)
+ if (const.nil?)
+ @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' found constant '#{item}' to be nil.", Verbosity::ERRORS)
+ raise
+ else
+ elements << const
+ end
+ elsif (item.class == Array)
+ elements << item
+ elsif (item.class == String)
+ @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' cannot expand nonexistent value '#{item}' for substitution string '#{substitution}'.", Verbosity::ERRORS)
+ raise
+ else
+ @streaminator.stderr_puts("ERROR: Tool '#{@tool_name}' cannot expand value having type '#{item.class}' for substitution string '#{substitution}'.", Verbosity::ERRORS)
+ raise
+ end
+ end
+
+ # expand elements (whether string or array) into substitution string & replace escaped '\$'
+ elements.flatten!
+ elements.each do |element|
+ build_string.concat( substitution.sub(/([^\\]*)\$/, "\\1#{element}") ) # don't replace escaped '\$' but allow us to replace just a lonesome '$'
+ build_string.gsub!(/\\\$/, '$')
+ build_string.concat(' ')
+ end
+
+ return build_string.strip
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor_helper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor_helper.rb
new file mode 100755
index 00000000..de4cafe4
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/tool_executor_helper.rb
@@ -0,0 +1,164 @@
+require 'ceedling/constants' # for Verbosity enumeration & $stderr redirect enumeration
+
+##
+# Helper functions for the tool executor
+class ToolExecutorHelper
+
+ constructor :streaminator, :system_utils, :system_wrapper
+
+ ##
+ # Returns the stderr redirection based on the config and logging.
+ # ==== Attributes
+ #
+ # * _tool_config_: A hash containing config information.
+ # * _logging_: A boolean representing if logging is enabled or not.
+ #
+ def stderr_redirection(tool_config, logging)
+ # if there's no logging enabled, return :stderr_redirect unmodified
+ return tool_config[:stderr_redirect] if (not logging)
+
+ # if there is logging enabled but the redirect is a custom value (not enum), return the custom string
+ return tool_config[:stderr_redirect] if (tool_config[:stderr_redirect].class == String)
+
+ # if logging is enabled but there's no custom string, return the AUTO enumeration so $stderr goes into the log
+ return StdErrRedirect::AUTO
+ end
+
+
+ ##
+ # Returns the background execution prepend based on the config.
+ # ==== Attributes
+ #
+ # * _tool_config_: A hash containing config information.
+ #
+ def background_exec_cmdline_prepend(tool_config)
+ return nil if (tool_config.nil? || tool_config[:background_exec].nil?)
+
+ config_exec = tool_config[:background_exec]
+
+ if ((config_exec == BackgroundExec::AUTO) and (@system_wrapper.windows?))
+ return 'start'
+ end
+
+ if (config_exec == BackgroundExec::WIN)
+ return 'start'
+ end
+
+ return nil
+ end
+
+
+ ##
+ # Modifies an executables path based on platform.
+ # ==== Attributes
+ #
+ # * _executable_: The executable's path.
+ #
+ def osify_path_separators(executable)
+ return executable.gsub(/\//, '\\') if (@system_wrapper.windows?)
+ return executable
+ end
+
+ ##
+ # Returns the stderr redirect append based on the config.
+ # ==== Attributes
+ #
+ # * _tool_config_: A hash containing config information.
+ #
+ def stderr_redirect_cmdline_append(tool_config)
+ return nil if (tool_config.nil? || tool_config[:stderr_redirect].nil?)
+
+ config_redirect = tool_config[:stderr_redirect]
+ redirect = StdErrRedirect::NONE
+
+ if (config_redirect == StdErrRedirect::AUTO)
+ if (@system_wrapper.windows?)
+ redirect = StdErrRedirect::WIN
+ elsif (@system_utils.tcsh_shell?)
+ redirect = StdErrRedirect::TCSH
+ else
+ redirect = StdErrRedirect::UNIX
+ end
+ end
+
+ case redirect
+ # we may need more complicated processing after some learning with various environments
+ when StdErrRedirect::NONE then nil
+ when StdErrRedirect::WIN then '2>&1'
+ when StdErrRedirect::UNIX then '2>&1'
+ when StdErrRedirect::TCSH then '|&'
+ else redirect.to_s
+ end
+ end
+
+ ##
+ # Returns the background execution append based on the config.
+ # ==== Attributes
+ #
+ # * _tool_config_: A hash containing config information.
+ #
+ def background_exec_cmdline_append(tool_config)
+ return nil if (tool_config.nil? || tool_config[:background_exec].nil?)
+
+ config_exec = tool_config[:background_exec]
+
+ # if :auto & windows, then we already prepended 'start' and should append nothing
+ return nil if ((config_exec == BackgroundExec::AUTO) and (@system_wrapper.windows?))
+
+ # if :auto & not windows, then we append standard '&'
+ return '&' if ((config_exec == BackgroundExec::AUTO) and (not @system_wrapper.windows?))
+
+ # if explicitly Unix, then append '&'
+ return '&' if (config_exec == BackgroundExec::UNIX)
+
+ # * _command_str_: A hash containing config information.
+ # all other cases, including :none, :win, & anything unrecognized, append nothing
+ return nil
+ end
+
+ ##
+ # Outputs success results if command succeeded and we have verbosity cranked up.
+ # ==== Attributes
+ #
+ # * _command_str_: The command ran.
+ # * _shell_results_: The outputs of the command including exit code and
+ # output.
+ # * _boom_: A boolean representing if a non zero result is erroneous.
+ #
+ def print_happy_results(command_str, shell_result, boom=true)
+ if ((shell_result[:exit_code] == 0) or ((shell_result[:exit_code] != 0) and not boom))
+ output = "> Shell executed command:\n"
+ output += "'#{command_str}'\n"
+ output += "> Produced output:\n" if (not shell_result[:output].empty?)
+ output += "#{shell_result[:output].strip}\n" if (not shell_result[:output].empty?)
+ output += "> And exited with status: [#{shell_result[:exit_code]}].\n" if (shell_result[:exit_code] != 0)
+ output += "\n"
+
+ @streaminator.stdout_puts(output, Verbosity::OBNOXIOUS)
+ end
+ end
+
+ ##
+ # Outputs failures results if command failed and we have verbosity set to minimum error level.
+ # ==== Attributes
+ #
+ # * _command_str_: The command ran.
+ # * _shell_results_: The outputs of the command including exit code and
+ # output.
+ # * _boom_: A boolean representing if a non zero result is erroneous.
+ #
+ def print_error_results(command_str, shell_result, boom=true)
+ if ((shell_result[:exit_code] != 0) and boom)
+ output = "ERROR: Shell command failed.\n"
+ output += "> Shell executed command:\n"
+ output += "'#{command_str}'\n"
+ output += "> Produced output:\n" if (not shell_result[:output].empty?)
+ output += "#{shell_result[:output].strip}\n" if (not shell_result[:output].empty?)
+ output += "> And exited with status: [#{shell_result[:exit_code]}].\n" if (shell_result[:exit_code] != nil)
+ output += "> And then likely crashed.\n" if (shell_result[:exit_code] == nil)
+ output += "\n"
+
+ @streaminator.stderr_puts(output, Verbosity::ERRORS)
+ end
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/verbosinator.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/verbosinator.rb
new file mode 100755
index 00000000..e8ed38d7
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/verbosinator.rb
@@ -0,0 +1,10 @@
+
+class Verbosinator
+
+ constructor :configurator
+
+ def should_output?(level)
+ return (level <= @configurator.project_verbosity)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb
new file mode 100755
index 00000000..ba917df5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb
@@ -0,0 +1,36 @@
+
+# @private
+module Ceedling
+ module Version
+ # Check for local or global version of vendor directory in order to look up versions
+ {
+ "CEXCEPTION" => File.join("vendor","c_exception","lib","CException.h"),
+ "CMOCK" => File.join("vendor","cmock","src","cmock.h"),
+ "UNITY" => File.join("vendor","unity","src","unity.h"),
+ }.each_pair do |name, path|
+ filename = if (File.exist?(File.join("..","..",path)))
+ File.join("..","..",path)
+ elsif (File.exist?(File.join(File.dirname(__FILE__),"..","..",path)))
+ File.join(File.dirname(__FILE__),"..","..",path)
+ else
+ eval "#{name} = 'unknown'"
+ continue
+ end
+
+ # Actually look up the versions
+ a = [0,0,0]
+ File.readlines(filename) do |line|
+ ["VERSION_MAJOR", "VERSION_MINOR", "VERSION_BUILD"].each_with_index do |field, i|
+ m = line.match(/#{name}_#{field}\s+(\d+)/)
+ a[i] = m[1] unless (m.nil?)
+ end
+ end
+
+ # Make a constant from each, so that we can use it elsewhere
+ eval "#{name} = '#{a.join(".")}'"
+ end
+
+ GEM = "0.29.0"
+ CEEDLING = GEM
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb.erb b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb.erb
new file mode 100755
index 00000000..a31e3abb
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/version.rb.erb
@@ -0,0 +1,15 @@
+# @private
+module Ceedling
+ module Version
+ # @private
+ GEM = "0.27.0"
+ # @private
+ CEEDLING = "<%= versions["CEEDLING"] %>"
+ # @private
+ CEXCEPTION = "<%= versions["CEXCEPTION"] %>"
+ # @private
+ CMOCK = "<%= versions["CMOCK"] %>"
+ # @private
+ UNITY = "<%= versions["UNITY"] %>"
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/lib/ceedling/yaml_wrapper.rb b/tinyusb/test/vendor/ceedling/lib/ceedling/yaml_wrapper.rb
new file mode 100755
index 00000000..00ece514
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/lib/ceedling/yaml_wrapper.rb
@@ -0,0 +1,17 @@
+require 'yaml'
+require 'erb'
+
+
+class YamlWrapper
+
+ def load(filepath)
+ return YAML.load(ERB.new(File.read(filepath)).result)
+ end
+
+ def dump(filepath, structure)
+ File.open(filepath, 'w') do |output|
+ YAML.dump(structure, output)
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/beep/README.md b/tinyusb/test/vendor/ceedling/plugins/beep/README.md
new file mode 100755
index 00000000..e59d881b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/beep/README.md
@@ -0,0 +1,22 @@
+ceedling-beep
+=============
+
+This is a simple plugin that just beeps at the end of a build and/or test sequence. Are you getting too distracted surfing
+the internet, chatting with coworkers, or swordfighting while it's building or testing? The friendly beep will let you know
+it's time to pay attention again.
+
+This plugin has very few configuration options. At this time it can beep on completion of a task and/or on an error condition.
+For each of these, you can configure the method that it should beep.
+
+```
+:tools:
+ :beep_on_done: :bell
+ :beep_on_error: :bell
+```
+
+Each of these have the following options:
+
+ - :bell - this option uses the ASCII bell character out stdout
+ - :speaker_test - this uses the linux speaker-test command if installed
+
+Very likely, we'll be adding to this list if people find this to be useful.
diff --git a/tinyusb/test/vendor/ceedling/plugins/beep/lib/beep.rb b/tinyusb/test/vendor/ceedling/plugins/beep/lib/beep.rb
new file mode 100755
index 00000000..6a6d01ab
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/beep/lib/beep.rb
@@ -0,0 +1,40 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+
+class Beep < Plugin
+
+ attr_reader :config
+
+ def setup
+ @config = {
+ :on_done => ((defined? TOOLS_BEEP_ON_DONE) ? TOOLS_BEEP_ON_DONE : :bell ),
+ :on_error => ((defined? TOOLS_BEEP_ON_ERROR) ? TOOLS_BEEP_ON_ERROR : :bell ),
+ }
+ end
+
+ def post_build
+ beep @config[:on_done]
+ end
+
+ def post_error
+ beep @config[:on_error]
+ end
+
+ private
+
+ def beep(method = :none)
+ case method
+ when :bell
+ if (SystemWrapper.windows?)
+ puts "echo '\007'"
+ else
+ puts "echo -ne '\007'"
+ end
+ when :speaker_test
+ `speaker-test -t sine -f 1000 -l 1`
+ else
+ #do nothing with illegal or :none
+ end
+ end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/bullseye/assets/template.erb
new file mode 100755
index 00000000..504f8558
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/assets/template.erb
@@ -0,0 +1,15 @@
+% function_string = hash[:coverage][:functions].to_s
+% branch_string = hash[:coverage][:branches].to_s
+% format_string = "%#{[function_string.length, branch_string.length].max}i"
+<%=@ceedling[:plugin_reportinator].generate_banner("#{hash[:header]}: CODE COVERAGE SUMMARY")%>
+% if (!hash[:coverage][:functions].nil?)
+FUNCTIONS: <%=sprintf(format_string, hash[:coverage][:functions])%>%
+% else
+FUNCTIONS: none
+% end
+% if (!hash[:coverage][:branches].nil?)
+BRANCHES: <%=sprintf(format_string, hash[:coverage][:branches])%>%
+% else
+BRANCHES: none
+% end
+
diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/bullseye.rake b/tinyusb/test/vendor/ceedling/plugins/bullseye/bullseye.rake
new file mode 100755
index 00000000..a7bbebe3
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/bullseye.rake
@@ -0,0 +1,169 @@
+directory(BULLSEYE_BUILD_OUTPUT_PATH)
+directory(BULLSEYE_RESULTS_PATH)
+directory(BULLSEYE_ARTIFACTS_PATH)
+directory(BULLSEYE_DEPENDENCIES_PATH)
+
+CLEAN.include(File.join(BULLSEYE_BUILD_OUTPUT_PATH, '*'))
+CLEAN.include(File.join(BULLSEYE_RESULTS_PATH, '*'))
+CLEAN.include(File.join(BULLSEYE_DEPENDENCIES_PATH, '*'))
+
+CLOBBER.include(File.join(BULLSEYE_BUILD_PATH, '**/*'))
+PLUGINS_BULLSEYE_LIB_PATH = 'C:\\tools\\BullseyeCoverage\\lib' if not defined?(PLUGINS_BULLSEYE_LIB_PATH)
+
+rule(/#{BULLSEYE_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_OBJECT}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name)
+ end
+ ]) do |object|
+
+ if File.basename(object.source) =~ /^(#{PROJECT_TEST_FILE_PREFIX}|#{CMOCK_MOCK_PREFIX}|#{BULLSEYE_IGNORE_SOURCES.join('|')})/i
+ @ceedling[:generator].generate_object_file(
+ TOOLS_BULLSEYE_COMPILER,
+ OPERATION_COMPILE_SYM,
+ BULLSEYE_SYM,
+ object.source,
+ object.name,
+ @ceedling[:file_path_utils].form_test_build_list_filepath(object.name)
+ )
+ else
+ @ceedling[BULLSEYE_SYM].generate_coverage_object_file(object.source, object.name)
+ end
+
+end
+
+rule(/#{BULLSEYE_BUILD_OUTPUT_PATH}\/#{'.+\\'+EXTENSION_EXECUTABLE}$/) do |bin_file|
+ @ceedling[:generator].generate_executable_file(
+ TOOLS_BULLSEYE_LINKER,
+ BULLSEYE_SYM,
+ bin_file.prerequisites,
+ bin_file.name,
+ @ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name)
+ )
+end
+
+rule(/#{BULLSEYE_RESULTS_PATH}\/#{'.+\\'+EXTENSION_TESTPASS}$/ => [
+ proc do |task_name|
+ @ceedling[:file_path_utils].form_test_executable_filepath(task_name)
+ end
+ ]) do |test_result|
+ @ceedling[:generator].generate_test_results(TOOLS_BULLSEYE_FIXTURE, BULLSEYE_SYM, test_result.source, test_result.name)
+end
+
+rule(/#{BULLSEYE_DEPENDENCIES_PATH}\/#{'.+\\'+EXTENSION_DEPENDENCIES}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name)
+ end
+ ]) do |dep|
+ @ceedling[:generator].generate_dependencies_file(
+ TOOLS_TEST_DEPENDENCIES_GENERATOR,
+ BULLSEYE_SYM,
+ dep.source,
+ File.join(BULLSEYE_BUILD_OUTPUT_PATH, File.basename(dep.source).ext(EXTENSION_OBJECT) ),
+ dep.name
+ )
+end
+
+task :directories => [BULLSEYE_BUILD_OUTPUT_PATH, BULLSEYE_RESULTS_PATH, BULLSEYE_DEPENDENCIES_PATH, BULLSEYE_ARTIFACTS_PATH]
+
+namespace BULLSEYE_SYM do
+ task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{BULLSEYE_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}")
+
+ desc 'Run code coverage for all tests'
+ task all: [:directories] do
+ @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
+ @ceedling[BULLSEYE_SYM].enableBullseye(true)
+ @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM)
+ @ceedling[:configurator].restore_config
+ end
+
+ desc "Run single test w/ coverage ([*] real test or source file name, no path)."
+ task :* do
+ message = "\nOops! '#{BULLSEYE_ROOT_NAME}:*' isn't a real task. " +
+ "Use a real test or source file name (no path) in place of the wildcard.\n" +
+ "Example: rake #{BULLSEYE_ROOT_NAME}:foo.c\n\n"
+
+ @ceedling[:streaminator].stdout_puts( message )
+ end
+
+ desc 'Run tests by matching regular expression pattern.'
+ task :pattern, [:regex] => [:directories] do |_t, args|
+ matches = []
+
+ COLLECTION_ALL_TESTS.each do |test|
+ matches << test if test =~ /#{args.regex}/
+ end
+
+ if !matches.empty?
+ @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
+ @ceedling[BULLSEYE_SYM].enableBullseye(true)
+ @ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false)
+ @ceedling[:configurator].restore_config
+ else
+ @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.")
+ end
+ end
+
+ desc 'Run tests whose test path contains [dir] or [dir] substring.'
+ task :path, [:dir] => [:directories] do |_t, args|
+ matches = []
+
+ COLLECTION_ALL_TESTS.each do |test|
+ matches << test if File.dirname(test).include?(args.dir.tr('\\', '/'))
+ end
+
+ if !matches.empty?
+ @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
+ @ceedling[BULLSEYE_SYM].enableBullseye(true)
+ @ceedling[:test_invoker].setup_and_invoke(matches, BULLSEYE_SYM, force_run: false)
+ @ceedling[:configurator].restore_config
+ else
+ @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.")
+ end
+ end
+
+ desc 'Run code coverage for changed files'
+ task delta: [:directories] do
+ @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
+ @ceedling[BULLSEYE_SYM].enableBullseye(true)
+ @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, BULLSEYE_SYM, {:force_run => false})
+ @ceedling[:configurator].restore_config
+ end
+
+ # use a rule to increase efficiency for large projects
+ # bullseye test tasks by regex
+ rule(/^#{BULLSEYE_TASK_ROOT}\S+$/ => [
+ proc do |task_name|
+ test = task_name.sub(/#{BULLSEYE_TASK_ROOT}/, '')
+ test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" unless test.start_with?(PROJECT_TEST_FILE_PREFIX)
+ @ceedling[:file_finder].find_test_from_file_path(test)
+ end
+ ]) do |test|
+ @ceedling[:rake_wrapper][:directories].invoke
+ @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
+ @ceedling[BULLSEYE_SYM].enableBullseye(true)
+ @ceedling[:test_invoker].setup_and_invoke([test.source], BULLSEYE_SYM)
+ @ceedling[:configurator].restore_config
+ end
+
+end
+
+if PROJECT_USE_DEEP_DEPENDENCIES
+namespace REFRESH_SYM do
+ task BULLSEYE_SYM do
+ @ceedling[:configurator].replace_flattened_config(@ceedling[BULLSEYE_SYM].config)
+ @ceedling[BULLSEYE_SYM].enableBullseye(true)
+ @ceedling[:test_invoker].refresh_deep_dependencies
+ @ceedling[:configurator].restore_config
+ end
+end
+end
+
+namespace UTILS_SYM do
+
+ desc "Open Bullseye code coverage browser"
+ task BULLSEYE_SYM do
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_BROWSER, [])
+ @ceedling[:tool_executor].exec(command[:line], command[:options])
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/config/defaults.yml b/tinyusb/test/vendor/ceedling/plugins/bullseye/config/defaults.yml
new file mode 100755
index 00000000..ed261d8e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/config/defaults.yml
@@ -0,0 +1,57 @@
+---
+
+:bullseye:
+ :auto_license: TRUE
+:plugins:
+ :bullseye_lib_path: []
+:paths:
+ :bullseye_toolchain_include: []
+
+:tools:
+ :bullseye_instrumentation:
+ :executable: covc
+ :arguments:
+ - '--file $': ENVIRONMENT_COVFILE
+ - -q
+ - ${1}
+ :bullseye_compiler:
+ :executable: gcc
+ :arguments:
+ - -g
+ - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR
+ - -I"$": COLLECTION_PATHS_BULLSEYE_TOOLCHAIN_INCLUDE
+ - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR
+ - -DBULLSEYE_COMPILER
+ - -c "${1}"
+ - -o "${2}"
+ :bullseye_linker:
+ :executable: gcc
+ :arguments:
+ - ${1}
+ - -o ${2}
+ - -L$: PLUGINS_BULLSEYE_LIB_PATH
+ - -lcov
+ :bullseye_fixture:
+ :executable: ${1}
+ :bullseye_report_covsrc:
+ :executable: covsrc
+ :arguments:
+ - '--file $': ENVIRONMENT_COVFILE
+ - -q
+ - -w140
+ :bullseye_report_covfn:
+ :executable: covfn
+ :stderr_redirect: :auto
+ :arguments:
+ - '--file $': ENVIRONMENT_COVFILE
+ - --width 120
+ - --no-source
+ - '"${1}"'
+ :bullseye_browser:
+ :executable: CoverageBrowser
+ :background_exec: :auto
+ :optional: TRUE
+ :arguments:
+ - '"$"': ENVIRONMENT_COVFILE
+
+...
diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb b/tinyusb/test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb
new file mode 100755
index 00000000..ffa444ac
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/lib/bullseye.rb
@@ -0,0 +1,194 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+
+BULLSEYE_ROOT_NAME = 'bullseye'
+BULLSEYE_TASK_ROOT = BULLSEYE_ROOT_NAME + ':'
+BULLSEYE_SYM = BULLSEYE_ROOT_NAME.to_sym
+
+BULLSEYE_BUILD_PATH = "#{PROJECT_BUILD_ROOT}/#{BULLSEYE_ROOT_NAME}"
+BULLSEYE_BUILD_OUTPUT_PATH = "#{BULLSEYE_BUILD_PATH}/out"
+BULLSEYE_RESULTS_PATH = "#{BULLSEYE_BUILD_PATH}/results"
+BULLSEYE_DEPENDENCIES_PATH = "#{BULLSEYE_BUILD_PATH}/dependencies"
+BULLSEYE_ARTIFACTS_PATH = "#{PROJECT_BUILD_ARTIFACTS_ROOT}/#{BULLSEYE_ROOT_NAME}"
+
+BULLSEYE_IGNORE_SOURCES = ['unity', 'cmock', 'cexception']
+
+
+class Bullseye < Plugin
+
+ def setup
+ @result_list = []
+ @environment = [ {:covfile => File.join( BULLSEYE_ARTIFACTS_PATH, 'test.cov' )} ]
+ @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ @coverage_template_all = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
+ end
+
+ def config
+ {
+ :project_test_build_output_path => BULLSEYE_BUILD_OUTPUT_PATH,
+ :project_test_results_path => BULLSEYE_RESULTS_PATH,
+ :project_test_dependencies_path => BULLSEYE_DEPENDENCIES_PATH,
+ :defines_test => DEFINES_TEST + ['CODE_COVERAGE'],
+ :collection_defines_test_and_vendor => COLLECTION_DEFINES_TEST_AND_VENDOR + ['CODE_COVERAGE']
+ }
+ end
+
+ def generate_coverage_object_file(source, object)
+ arg_hash = {:tool => TOOLS_BULLSEYE_INSTRUMENTATION, :context => BULLSEYE_SYM, :source => source, :object => object}
+ @ceedling[:plugin_manager].pre_compile_execute(arg_hash)
+
+ @ceedling[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...")
+ compile_command =
+ @ceedling[:tool_executor].build_command_line(
+ TOOLS_BULLSEYE_COMPILER,
+ @ceedling[:flaginator].flag_down( OPERATION_COMPILE_SYM, BULLSEYE_SYM, source ),
+ source,
+ object,
+ @ceedling[:file_path_utils].form_test_build_list_filepath( object ) )
+ coverage_command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_INSTRUMENTATION, [], compile_command[:line] )
+
+ shell_result = @ceedling[:tool_executor].exec( coverage_command[:line], coverage_command[:options] )
+
+ arg_hash[:shell_result] = shell_result
+ @ceedling[:plugin_manager].post_compile_execute(arg_hash)
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ result_file = arg_hash[:result_file]
+
+ if ((result_file =~ /#{BULLSEYE_RESULTS_PATH}/) and (not @result_list.include?(result_file)))
+ @result_list << arg_hash[:result_file]
+ end
+ end
+
+ def post_build
+ return if (not @ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}/))
+
+ # test results
+ results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
+ hash = {
+ :header => BULLSEYE_ROOT_NAME.upcase,
+ :results => results
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash) do
+ message = ''
+ message = 'Unit test failures.' if (results[:counts][:failed] > 0)
+ message
+ end
+
+ # coverage results
+ return if (verify_coverage_file() == false)
+ if (@ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}(all|delta)/))
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVSRC, [])
+ shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options])
+ report_coverage_results_all(shell_result[:output])
+ else
+ report_per_function_coverage_results(@ceedling[:test_invoker].sources)
+ end
+ end
+
+ def summary
+ return if (verify_coverage_file() == false)
+ result_list = @ceedling[:file_path_utils].form_pass_results_filelist( BULLSEYE_RESULTS_PATH, COLLECTION_ALL_TESTS )
+
+ # test results
+ # get test results for only those tests in our configuration and of those only tests with results on disk
+ hash = {
+ :header => BULLSEYE_ROOT_NAME.upcase,
+ :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash)
+
+ # coverage results
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVSRC)
+ shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options])
+ report_coverage_results_all(shell_result[:output])
+ end
+
+ def enableBullseye(enable)
+ if BULLSEYE_AUTO_LICENSE
+ if (enable)
+ args = ['push', 'on']
+ @ceedling[:streaminator].stdout_puts("Enabling Bullseye")
+ else
+ args = ['pop']
+ @ceedling[:streaminator].stdout_puts("Reverting Bullseye to previous state")
+ end
+
+ args.each do |arg|
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_BUILD_ENABLE_DISABLE, [], arg)
+ shell_result = @ceedling[:tool_executor].exec(command[:line], command[:options])
+ end
+
+ end
+ end
+
+ private ###################################
+
+ def report_coverage_results_all(coverage)
+ results = {
+ :header => BULLSEYE_ROOT_NAME.upcase,
+ :coverage => {
+ :functions => nil,
+ :branches => nil
+ }
+ }
+
+ if (coverage =~ /^Total.*?=\s+([0-9]+)\%/)
+ results[:coverage][:functions] = $1.to_i
+ end
+
+ if (coverage =~ /^Total.*=\s+([0-9]+)\%\s*$/)
+ results[:coverage][:branches] = $1.to_i
+ end
+
+ @ceedling[:plugin_reportinator].run_report($stdout, @coverage_template_all, results)
+ end
+
+ def report_per_function_coverage_results(sources)
+ banner = @ceedling[:plugin_reportinator].generate_banner( "#{BULLSEYE_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" )
+ @ceedling[:streaminator].stdout_puts "\n" + banner
+
+ coverage_sources = sources.clone
+ coverage_sources.delete_if {|item| item =~ /#{CMOCK_MOCK_PREFIX}.+#{EXTENSION_SOURCE}$/}
+ coverage_sources.delete_if {|item| item =~ /#{BULLSEYE_IGNORE_SOURCES.join('|')}#{EXTENSION_SOURCE}$/}
+
+ coverage_sources.each do |source|
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVFN, [], source)
+ shell_results = @ceedling[:tool_executor].exec(command[:line], command[:options])
+ coverage_results = shell_results[:output].deep_clone
+ coverage_results.sub!(/.*\n.*\n/,'') # Remove the Bullseye tool banner
+ if (coverage_results =~ /warning cov814: report is empty/)
+ coverage_results = "WARNING: #{source} contains no coverage data!\n\n"
+ @ceedling[:streaminator].stdout_puts(coverage_results, Verbosity::COMPLAIN)
+ else
+ coverage_results += "\n"
+ @ceedling[:streaminator].stdout_puts(coverage_results)
+ end
+ end
+ end
+
+ def verify_coverage_file
+ exist = @ceedling[:file_wrapper].exist?( ENVIRONMENT_COVFILE )
+
+ if (!exist)
+ banner = @ceedling[:plugin_reportinator].generate_banner( "#{BULLSEYE_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY" )
+ @ceedling[:streaminator].stdout_puts "\n" + banner + "\nNo coverage file.\n\n"
+ end
+
+ return exist
+ end
+
+end
+
+
+# end blocks always executed following rake run
+END {
+ # cache our input configurations to use in comparison upon next execution
+ if (@ceedling[:task_invoker].invoked?(/^#{BULLSEYE_TASK_ROOT}/))
+ @ceedling[:cacheinator].cache_test_config( @ceedling[:setupinator].config_hash )
+ @ceedling[BULLSEYE_SYM].enableBullseye(false)
+ end
+}
diff --git a/tinyusb/test/vendor/ceedling/plugins/bullseye/readme.txt b/tinyusb/test/vendor/ceedling/plugins/bullseye/readme.txt
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/bullseye/readme.txt
diff --git a/tinyusb/test/vendor/ceedling/plugins/colour_report/lib/colour_report.rb b/tinyusb/test/vendor/ceedling/plugins/colour_report/lib/colour_report.rb
new file mode 100755
index 00000000..1211eab4
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/colour_report/lib/colour_report.rb
@@ -0,0 +1,16 @@
+require 'ceedling/plugin'
+require 'ceedling/streaminator'
+require 'ceedling/constants'
+
+class ColourReport < Plugin
+
+ def setup
+ @ceedling[:stream_wrapper].stdout_override(&ColourReport.method(:colour_stdout))
+ end
+
+ def self.colour_stdout(string)
+ require 'colour_reporter.rb'
+ report string
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/command_hooks/README.md b/tinyusb/test/vendor/ceedling/plugins/command_hooks/README.md
new file mode 100755
index 00000000..8ac64afc
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/command_hooks/README.md
@@ -0,0 +1,53 @@
+ceedling-command-hooks
+======================
+
+Plugin for easily calling command line tools at various points in the build process
+
+Define any of these sections in :tools: to provide additional hooks to be called on demand:
+
+```
+ :pre_mock_generate
+ :post_mock_generate
+ :pre_runner_generate
+ :post_runner_generate
+ :pre_compile_execute
+ :post_compile_execute
+ :pre_link_execute
+ :post_link_execute
+ :pre_test_fixture_execute
+ :pre_test
+ :post_test
+ :pre_release
+ :post_release
+ :pre_build
+ :post_build
+```
+
+Each of these tools can support an :executable string and an :arguments list, like so:
+
+```
+:tools:
+ :post_link_execute:
+ :executable: objcopy.exe
+ :arguments:
+ - ${1} #This is replaced with the executable name
+ - output.srec
+ - --strip-all
+```
+
+You may also specify an array of executables to be called in a particular place, like so:
+
+```
+:tools:
+ :post_test:
+ - :executable: echo
+ :arguments: "${1} was glorious!"
+ - :executable: echo
+ :arguments:
+ - it kinda made me cry a little.
+ - you?
+```
+
+Please note that it varies which arguments are being parsed down to the
+hooks. For now see `command_hooks.rb` to figure out which suits you best.
+Happy Tweaking!
diff --git a/tinyusb/test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb b/tinyusb/test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb
new file mode 100755
index 00000000..4bf8b531
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/command_hooks/lib/command_hooks.rb
@@ -0,0 +1,92 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+class CommandHooks < Plugin
+
+ attr_reader :config
+
+ def setup
+ @config = {
+ :pre_mock_generate => ((defined? TOOLS_PRE_MOCK_GENERATE) ? TOOLS_PRE_MOCK_GENERATE : nil ),
+ :post_mock_generate => ((defined? TOOLS_POST_MOCK_GENERATE) ? TOOLS_POST_MOCK_GENERATE : nil ),
+ :pre_runner_generate => ((defined? TOOLS_PRE_RUNNER_GENERATE) ? TOOLS_PRE_RUNNER_GENERATE : nil ),
+ :post_runner_generate => ((defined? TOOLS_POST_RUNNER_GENERATE) ? TOOLS_POST_RUNNER_GENERATE : nil ),
+ :pre_compile_execute => ((defined? TOOLS_PRE_COMPILE_EXECUTE) ? TOOLS_PRE_COMPILE_EXECUTE : nil ),
+ :post_compile_execute => ((defined? TOOLS_POST_COMPILE_EXECUTE) ? TOOLS_POST_COMPILE_EXECUTE : nil ),
+ :pre_link_execute => ((defined? TOOLS_PRE_LINK_EXECUTE) ? TOOLS_PRE_LINK_EXECUTE : nil ),
+ :post_link_execute => ((defined? TOOLS_POST_LINK_EXECUTE) ? TOOLS_POST_LINK_EXECUTE : nil ),
+ :pre_test_fixture_execute => ((defined? TOOLS_PRE_TEST_FIXTURE_EXECUTE) ? TOOLS_PRE_TEST_FIXTURE_EXECUTE : nil ),
+ :post_test_fixture_execute => ((defined? TOOLS_POST_TEST_FIXTURE_EXECUTE) ? TOOLS_POST_TEST_FIXTURE_EXECUTE : nil ),
+ :pre_test => ((defined? TOOLS_PRE_TEST) ? TOOLS_PRE_TEST : nil ),
+ :post_test => ((defined? TOOLS_POST_TEST) ? TOOLS_POST_TEST : nil ),
+ :pre_release => ((defined? TOOLS_PRE_RELEASE) ? TOOLS_PRE_RELEASE : nil ),
+ :post_release => ((defined? TOOLS_POST_RELEASE) ? TOOLS_POST_RELEASE : nil ),
+ :pre_build => ((defined? TOOLS_PRE_BUILD) ? TOOLS_PRE_BUILD : nil ),
+ :post_build => ((defined? TOOLS_POST_BUILD) ? TOOLS_POST_BUILD : nil ),
+ :post_error => ((defined? TOOLS_POST_ERROR) ? TOOLS_POST_ERROR : nil ),
+ }
+ @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ end
+
+ def pre_mock_generate(arg_hash); run_hook(:pre_mock_generate, arg_hash[:header_file] ); end
+ def post_mock_generate(arg_hash); run_hook(:post_mock_generate, arg_hash[:header_file] ); end
+ def pre_runner_generate(arg_hash); run_hook(:pre_runner_generate, arg_hash[:source ] ); end
+ def post_runner_generate(arg_hash); run_hook(:post_runner_generate, arg_hash[:runner_file] ); end
+ def pre_compile_execute(arg_hash); run_hook(:pre_compile_execute, arg_hash[:source_file] ); end
+ def post_compile_execute(arg_hash); run_hook(:post_compile_execute, arg_hash[:object_file] ); end
+ def pre_link_execute(arg_hash); run_hook(:pre_link_execute, arg_hash[:executable] ); end
+ def post_link_execute(arg_hash); run_hook(:post_link_execute, arg_hash[:executable] ); end
+ def pre_test_fixture_execute(arg_hash); run_hook(:pre_test_fixture_execute, arg_hash[:executable] ); end
+ def post_test_fixture_execute(arg_hash); run_hook(:post_test_fixture_execute, arg_hash[:executable] ); end
+ def pre_test(test); run_hook(:pre_test, test ); end
+ def post_test(test); run_hook(:post_test, test ); end
+ def pre_release; run_hook(:pre_release ); end
+ def post_release; run_hook(:post_release ); end
+ def pre_build; run_hook(:pre_build ); end
+ def post_build; run_hook(:post_build ); end
+ def post_error; run_hook(:post_error ); end
+
+ private
+
+ ##
+ # Run a hook if its available.
+ #
+ # :args:
+ # - hook: Name of the hook to run
+ # - name: Name of file (default: "")
+ #
+ # :return:
+ # shell_result.
+ #
+ def run_hook_step(hook, name="")
+ if (hook[:executable])
+ # Handle argument replacemant ({$1}), and get commandline
+ cmd = @ceedling[:tool_executor].build_command_line( hook, [], name )
+ shell_result = @ceedling[:tool_executor].exec(cmd[:line], cmd[:options])
+ end
+ end
+
+ ##
+ # Run a hook if its available.
+ #
+ # If __which_hook__ is an array, run each of them sequentially.
+ #
+ # :args:
+ # - which_hook: Name of the hook to run
+ # - name: Name of file
+ #
+ def run_hook(which_hook, name="")
+ if (@config[which_hook])
+ @ceedling[:streaminator].stdout_puts("Running Hook #{which_hook}...", Verbosity::NORMAL)
+ if (@config[which_hook].is_a? Array)
+ @config[which_hook].each do |hook|
+ run_hook_step(hook, name)
+ end
+ elsif (@config[which_hook].is_a? Hash)
+ run_hook_step( @config[which_hook], name )
+ else
+ @ceedling[:streaminator].stdout_puts("Hook #{which_hook} was poorly formed", Verbosity::COMPLAINT)
+ end
+ end
+ end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md
new file mode 100755
index 00000000..8042775e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md
@@ -0,0 +1,250 @@
+# A Fake Function Framework Plug-in for Ceedling
+
+This is a plug-in for [Ceedling](https://github.com/ThrowTheSwitch/Ceedling) to use the [Fake Function Framework](https://github.com/meekrosoft/fff) for mocking instead of CMock.
+
+Using fff provides less strict mocking than CMock, and allows for more loosely-coupled tests.
+And, when tests fail -- since you get the actual line number of the failure -- it's a lot easier to figure out what went wrong.
+
+## Installing the plug-in
+
+To use the plugin you need to 1) get the contents of this repo and 2) configure your project to use it.
+
+### Get the source
+
+The easiest way to get the source is to just clone this repo into the Ceedling plugin folder for your existing Ceedling project.
+(Don't have a Ceedling project already? [Here are instructions to create one.](http://www.electronvector.com/blog/try-embedded-test-driven-development-right-now-with-ceedling))
+From within `<your-project>/vendor/ceedling/plugins`, run:
+
+`git clone https://github.com/ElectronVector/fake_function_framework.git`
+
+This will create a new folder named `fake_function_framework` in the plugins folder.
+
+### Enable the plug-in.
+
+The plug-in is enabled from within your project.yml file.
+
+In the `:plugins` configuration, add `fake_function_framework` to the list of enabled plugins:
+
+```yaml
+:plugins:
+ :load_paths:
+ - vendor/ceedling/plugins
+ :enabled:
+ - stdout_pretty_tests_report
+ - module_generator
+ - fake_function_framework
+```
+*Note that you could put the plugin source in some other loaction.
+In that case you'd need to add a new path the `:load_paths`.*
+
+## How to use it
+
+You use fff with Ceedling the same way you used to use CMock.
+Modules can still be generated with the default module generator: `rake module:create[my_module]`.
+If you want to "mock" `some_module.h` in your tests, just `#include "mock_some_module.h"`.
+This creates a fake function for each of the functions defined in `some_module.h`.
+
+The name of each fake is the original function name with an appended `_fake`.
+For example, if we're generating fakes for a stack module with `push` and `pop` functions, we would have the fakes `push_fake` and `pop_fake`.
+These fakes are linked into our test executable so that any time our unit under test calls `push` or `pop` our fakes are called instead.
+
+Each of these fakes is actually a structure containing information about how the function was called, and what it might return.
+We can use Unity to inspect these fakes in our tests, and verify the interactions of our units.
+There is also a global structure named `fff` which we can use to check the sequence of calls.
+
+The fakes can also be configured to return particular values, so you can exercise the unit under test however you want.
+
+The examples below explain how to use fff to test a variety of module interactions.
+Each example uses fakes for a "display" module, created from a display.h file with `#include "mock_display.h"`. The `display.h` file must exist and must contain the prototypes for the functions to be faked.
+
+### Test that a function was called once
+
+```c
+void
+test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()
+{
+ // When
+ event_deviceReset();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);
+}
+```
+
+### Test that a function was NOT called
+
+```c
+void
+test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void)
+{
+ // When
+ event_powerReadingUpdate(4);
+
+ // Then
+ TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count);
+}
+```
+
+## Test that a single function was called with the correct argument
+
+```c
+void
+test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void)
+{
+ // When
+ event_volumeKnobMaxed();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count);
+ TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val);
+}
+```
+
+## Test that calls are made in a particular sequence
+
+```c
+void
+test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void)
+{
+ // When
+ event_modeSelectButtonPressed();
+ event_modeSelectButtonPressed();
+ event_modeSelectButtonPressed();
+
+ // Then
+ TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMinimum, fff.call_history[0]);
+ TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMaximum, fff.call_history[1]);
+ TEST_ASSERT_EQUAL_PTR((void*)display_setModeToAverage, fff.call_history[2]);
+}
+```
+
+## Fake a return value from a function
+
+```c
+void
+test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void)
+{
+ // Given
+ display_isError_fake.return_val = true;
+
+ // When
+ event_devicePoweredOn();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
+}
+```
+
+## Fake a function with a value returned by reference
+
+```c
+void
+test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void)
+{
+ // Given
+ char mockedEntry[] = "sleep";
+ void return_mock_value(char * entry, int length)
+ {
+ if (length > strlen(mockedEntry))
+ {
+ strncpy(entry, mockedEntry, length);
+ }
+ }
+ display_getKeyboardEntry_fake.custom_fake = return_mock_value;
+
+ // When
+ event_keyboardCheckTimerExpired();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
+}
+```
+
+## Fake a function with a function pointer parameter
+
+```
+void
+test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void)
+{
+ // A mock function for capturing the callback handler function pointer.
+ void(*registeredCallback)(void) = 0;
+ void mock_display_updateData(int data, void(*callback)(void))
+ {
+ //Save the callback function.
+ registeredCallback = callback;
+ }
+ display_updateData_fake.custom_fake = mock_display_updateData;
+
+ // Given
+ event_newDataAvailable(10);
+
+ // When
+ if (registeredCallback != 0)
+ {
+ registeredCallback();
+ }
+
+ // Then
+ TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete());
+}
+```
+
+## Helper macros
+
+For convenience, there are also some helper macros that create new Unity-style asserts:
+
+- `TEST_ASSERT_CALLED(function)`: Asserts that a function was called once.
+- `TEST_ASSERT_NOT_CALLED(function)`: Asserts that a function was never called.
+- `TEST_ASSERT_CALLED_TIMES(times, function)`: Asserts that a function was called a particular number of times.
+- `TEST_ASSERT_CALLED_IN_ORDER(order, function)`: Asserts that a function was called in a particular order.
+
+Here's how you might use one of these instead of simply checking the call_count value:
+
+```c
+void
+test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()
+{
+ // When
+ event_deviceReset();
+
+ // Then
+ // This how to directly use fff...
+ TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);
+ // ...and this is how to use the helper macro.
+ TEST_ASSERT_CALLED(display_turnOffStatusLed);
+}
+```
+
+## Test setup
+
+All of the fake functions, and any fff global state are all reset automatically between each test.
+
+## CMock configuration
+
+Use still use some of the CMock configuration options for setting things like the mock prefix, and for including additional header files in the mock files.
+
+```yaml
+:cmock:
+ :mock_prefix: mock_
+ :includes:
+ -
+ :includes_h_pre_orig_header:
+ -
+ :includes_h_post_orig_header:
+ -
+ :includes_c_pre_header:
+ -
+ :includes_c_post_header:
+```
+
+## Running the tests
+
+There are unit and integration tests for the plug-in itself.
+These are run with the default `rake` task.
+The integration test runs the tests for the example project in examples/fff_example.
+For the integration tests to succeed, this repository must be placed in a Ceedling tree in the plugins folder.
+
+## More examples
+
+There is an example project in examples/fff_example.
+It shows how to use the plug-in with some full-size examples.
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile
new file mode 100755
index 00000000..bc559411
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile
@@ -0,0 +1,19 @@
+require 'rake'
+require 'rspec/core/rake_task'
+
+desc "Run all rspecs"
+RSpec::Core::RakeTask.new(:spec) do |t|
+ t.pattern = Dir.glob('spec/**/*_spec.rb')
+ t.rspec_opts = '--format documentation'
+ # t.rspec_opts << ' more options'
+end
+
+desc "Run integration test on example"
+task :integration_test do
+ chdir("./examples/fff_example") do
+ sh "rake clobber"
+ sh "rake test:all"
+ end
+end
+
+task :default => [:spec, :integration_test] \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml
new file mode 100755
index 00000000..6bda2229
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml
@@ -0,0 +1,71 @@
+---
+
+# Notes:
+# Sample project C code is not presently written to produce a release artifact.
+# As such, release build options are disabled.
+# This sample, therefore, only demonstrates running a collection of unit tests.
+
+:project:
+ :use_exceptions: FALSE
+ :use_test_preprocessor: TRUE
+ :use_auxiliary_dependencies: TRUE
+ :build_root: build
+# :release_build: TRUE
+ :test_file_prefix: test_
+
+#:release_build:
+# :output: MyApp.out
+# :use_assembly: FALSE
+
+:environment:
+
+:extension:
+ :executable: .out
+
+:paths:
+ :test:
+ - +:test/**
+ :source:
+ - src/**
+ :support:
+
+:defines:
+ # in order to add common defines:
+ # 1) remove the trailing [] from the :common: section
+ # 2) add entries to the :common: section (e.g. :test: has TEST defined)
+ :commmon: &common_defines []
+ :test:
+ - *common_defines
+ - TEST
+ :test_preprocess:
+ - *common_defines
+ - TEST
+
+:cmock:
+ :mock_prefix: mock_
+ :when_no_prototypes: :warn
+ :enforce_strict_ordering: TRUE
+ :plugins:
+ - :ignore
+ - :callback
+ :treat_as:
+ uint8: HEX8
+ uint16: HEX16
+ uint32: UINT32
+ int8: INT8
+ bool: UINT8
+
+#:tools:
+# Ceedling defaults to using gcc for compiling, linking, etc.
+# As [:tools] is blank, gcc will be used (so long as it's in your system path)
+# See documentation to configure a given toolchain for use
+
+:plugins:
+ :load_paths:
+ # This change from the default is for running Ceedling out of another folder.
+ - ../../../../plugins
+ :enabled:
+ - stdout_pretty_tests_report
+ - module_generator
+ - fake_function_framework
+...
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb
new file mode 100755
index 00000000..e484d5fb
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb
@@ -0,0 +1,7 @@
+# This change from the default is for running Ceedling out of another folder.
+PROJECT_CEEDLING_ROOT = "../../../.."
+load "#{PROJECT_CEEDLING_ROOT}/lib/ceedling.rb"
+
+Ceedling.load_project
+
+task :default => %w[ test:all release ]
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c
new file mode 100755
index 00000000..6a403234
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c
@@ -0,0 +1 @@
+#include "bar.h"
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h
new file mode 100755
index 00000000..febc5865
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h
@@ -0,0 +1,14 @@
+#ifndef bar_H
+#define bar_H
+
+#include "custom_types.h"
+
+void bar_turn_on(void);
+void bar_print_message(const char * message);
+void bar_print_message_formatted(const char * format, ...);
+void bar_numbers(int one, int two, char three);
+void bar_const_test(const char * a, char * const b, const int c);
+custom_t bar_needs_custom_type(void);
+const char * bar_return_const_ptr(int one);
+
+#endif // bar_H
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h
new file mode 100755
index 00000000..b426b32c
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h
@@ -0,0 +1,6 @@
+#ifndef custom_types_H
+#define custom_types_H
+
+typedef int custom_t;
+
+#endif
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c
new file mode 100755
index 00000000..2f03449b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "display.h"
+
+void display_turnOffStatusLed(void)
+{
+ printf("Display: Status LED off");
+} \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h
new file mode 100755
index 00000000..def29960
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h
@@ -0,0 +1,16 @@
+#include <stdbool.h>
+
+void display_turnOffStatusLed(void);
+void display_turnOnStatusLed(void);
+void display_setVolume(int level);
+void display_setModeToMinimum(void);
+void display_setModeToMaximum(void);
+void display_setModeToAverage(void);
+bool display_isError(void);
+void display_powerDown(void);
+void display_updateData(int data, void(*updateCompleteCallback)(void));
+
+/*
+ The entry is returned (up to `length` bytes) in the provided `entry` buffer.
+*/
+void display_getKeyboardEntry(char * entry, int length);
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c
new file mode 100755
index 00000000..916a9236
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c
@@ -0,0 +1,93 @@
+/*
+ This module implements some business logic to test.
+
+ Signal events by calling the functions on the module.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "event_processor.h"
+#include "display.h"
+
+void event_deviceReset(void)
+{
+ //printf ("Device reset\n");
+ display_turnOffStatusLed();
+}
+
+void event_volumeKnobMaxed(void)
+{
+ display_setVolume(11);
+}
+
+void event_powerReadingUpdate(int powerReading)
+{
+ if (powerReading >= 5)
+ {
+ display_turnOnStatusLed();
+ }
+}
+
+void event_modeSelectButtonPressed(void)
+{
+ static int mode = 0;
+
+ if (mode == 0)
+ {
+ display_setModeToMinimum();
+ mode++;
+ }
+ else if (mode == 1)
+ {
+ display_setModeToMaximum();
+ mode++;
+ }
+ else if (mode == 2)
+ {
+ display_setModeToAverage();
+ mode++;
+ }
+ else
+ {
+ mode = 0;
+ }
+}
+
+void event_devicePoweredOn(void)
+{
+ if (display_isError())
+ {
+ display_powerDown();
+ }
+}
+
+void event_keyboardCheckTimerExpired(void)
+{
+ char userEntry[100];
+
+ display_getKeyboardEntry(userEntry, 100);
+
+ if (strcmp(userEntry, "sleep") == 0)
+ {
+ display_powerDown();
+ }
+}
+
+static bool event_lastComplete = false;
+
+/* Function called when the display update is complete. */
+static void displayUpdateComplete(void)
+{
+ event_lastComplete = true;
+}
+
+void event_newDataAvailable(int data)
+{
+ event_lastComplete = false;
+ display_updateData(data, displayUpdateComplete);
+}
+
+bool eventProcessor_isLastEventComplete(void)
+{
+ return event_lastComplete;
+}
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h
new file mode 100755
index 00000000..a79e68c5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h
@@ -0,0 +1,11 @@
+#include <stdbool.h>
+
+void event_deviceReset(void);
+void event_volumeKnobMaxed(void);
+void event_powerReadingUpdate(int powerReading);
+void event_modeSelectButtonPressed(void);
+void event_devicePoweredOn(void);
+void event_keyboardCheckTimerExpired(void);
+void event_newDataAvailable(int data);
+
+bool eventProcessor_isLastEventComplete(void);
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c
new file mode 100755
index 00000000..c05b1154
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c
@@ -0,0 +1,16 @@
+#include "foo.h"
+#include "bar.h"
+#include "subfolder/zzz.h"
+
+void foo_turn_on(void) {
+ bar_turn_on();
+ zzz_sleep(1, "sleepy");
+}
+
+void foo_print_message(const char * message) {
+ bar_print_message(message);
+}
+
+void foo_print_special_message(void) {
+ bar_print_message_formatted("The numbers are %d, %d and %d", 1, 2, 3);
+}
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h
new file mode 100755
index 00000000..3fea6994
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h
@@ -0,0 +1,8 @@
+#ifndef foo_H
+#define foo_H
+
+void foo_turn_on(void);
+void foo_print_message(const char * message);
+void foo_print_special_message(void);
+
+#endif // foo_H
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c
new file mode 100755
index 00000000..85f370e1
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c
@@ -0,0 +1 @@
+#include "zzz.h"
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h
new file mode 100755
index 00000000..32c52940
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h
@@ -0,0 +1,6 @@
+#ifndef zzz_H
+#define zzz_H
+
+int zzz_sleep(int time, char * name);
+
+#endif // zzz_H
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c
new file mode 100755
index 00000000..9f999443
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c
@@ -0,0 +1,155 @@
+#include "unity.h"
+#include "event_processor.h"
+#include "mock_display.h"
+#include <string.h>
+
+void setUp (void)
+{
+}
+
+void tearDown (void)
+{
+}
+/*
+ Test that a single function was called.
+*/
+void
+test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()
+{
+ // When
+ event_deviceReset();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);
+ // or use the helper macro...
+ TEST_ASSERT_CALLED(display_turnOffStatusLed);
+}
+
+/*
+ Test that a single function is NOT called.
+*/
+void
+test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void)
+{
+ // When
+ event_powerReadingUpdate(4);
+
+ // Then
+ TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count);
+ // or use the helper macro...
+ TEST_ASSERT_NOT_CALLED(display_turnOffStatusLed);
+}
+
+/*
+ Test that a single function was called with the correct arugment.
+*/
+void
+test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void)
+{
+ // When
+ event_volumeKnobMaxed();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count);
+ // or use the helper macro...
+ TEST_ASSERT_CALLED(display_setVolume);
+ TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val);
+}
+
+/*
+ Test a sequence of calls.
+*/
+
+void
+test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void)
+{
+ // When
+ event_modeSelectButtonPressed();
+ event_modeSelectButtonPressed();
+ event_modeSelectButtonPressed();
+
+ // Then
+ TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMinimum, fff.call_history[0]);
+ TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMaximum, fff.call_history[1]);
+ TEST_ASSERT_EQUAL_PTR((void *)display_setModeToAverage, fff.call_history[2]);
+ // or use the helper macros...
+ TEST_ASSERT_CALLED_IN_ORDER(0, display_setModeToMinimum);
+ TEST_ASSERT_CALLED_IN_ORDER(1, display_setModeToMaximum);
+ TEST_ASSERT_CALLED_IN_ORDER(2, display_setModeToAverage);
+}
+
+/*
+ Mock a return value from a function.
+*/
+void
+test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void)
+{
+ // Given
+ display_isError_fake.return_val = true;
+
+ // When
+ event_devicePoweredOn();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
+ // or use the helper macro...
+ TEST_ASSERT_CALLED(display_powerDown);
+}
+
+/*
+ Mock a sequence of calls with return values.
+*/
+
+/*
+ Mocking a function with a value returned by reference.
+*/
+void
+test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void)
+{
+ // Given
+ char mockedEntry[] = "sleep";
+ void return_mock_value(char * entry, int length)
+ {
+ if (length > strlen(mockedEntry))
+ {
+ strncpy(entry, mockedEntry, length);
+ }
+ }
+ display_getKeyboardEntry_fake.custom_fake = return_mock_value;
+
+ // When
+ event_keyboardCheckTimerExpired();
+
+ // Then
+ TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);
+ // or use the helper macro...
+ TEST_ASSERT_CALLED(display_powerDown);
+}
+
+/*
+ Mock a function with a function pointer parameter.
+*/
+void
+test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void)
+{
+ // A mock function for capturing the callback handler function pointer.
+ void(*registeredCallback)(void) = 0;
+ void mock_display_updateData(int data, void(*callback)(void))
+ {
+ //Save the callback function.
+ registeredCallback = callback;
+ }
+ display_updateData_fake.custom_fake = mock_display_updateData;
+
+ // Given
+ event_newDataAvailable(10);
+
+ // When
+ if (registeredCallback != 0)
+ {
+ registeredCallback();
+ }
+
+ // Then
+ TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete());
+}
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c
new file mode 100755
index 00000000..12dd61a1
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c
@@ -0,0 +1,47 @@
+#include "unity.h"
+#include "foo.h"
+#include "mock_bar.h"
+#include "mock_zzz.h"
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_foo(void)
+{
+ //When
+ foo_turn_on();
+
+ //Then
+ TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count);
+ TEST_ASSERT_EQUAL(1, zzz_sleep_fake.call_count);
+ TEST_ASSERT_EQUAL_STRING("sleepy", zzz_sleep_fake.arg1_val);
+}
+
+void test_foo_again(void)
+{
+ //When
+ foo_turn_on();
+
+ //Then
+ TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count);
+}
+
+void test_foo_mock_with_const(void)
+{
+ foo_print_message("123");
+
+ TEST_ASSERT_EQUAL(1, bar_print_message_fake.call_count);
+ TEST_ASSERT_EQUAL_STRING("123", bar_print_message_fake.arg0_val);
+}
+
+void test_foo_mock_with_variable_args(void)
+{
+ foo_print_special_message();
+ TEST_ASSERT_EQUAL(1, bar_print_message_formatted_fake.call_count);
+ TEST_ASSERT_EQUAL_STRING("The numbers are %d, %d and %d", bar_print_message_formatted_fake.arg0_val);
+}
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb
new file mode 100755
index 00000000..51a90b3a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb
@@ -0,0 +1,87 @@
+require 'ceedling/plugin'
+require 'fff_mock_generator'
+
+class FakeFunctionFramework < Plugin
+
+ # Set up Ceedling to use this plugin.
+ def setup
+ # Get the location of this plugin.
+ @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ puts "Using fake function framework (fff)..."
+
+ # Switch out the cmock_builder with our own.
+ @ceedling[:cmock_builder].cmock = FffMockGeneratorForCMock.new(@ceedling[:setupinator].config_hash[:cmock])
+
+ # Add the path to fff.h to the include paths.
+ COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/vendor/fff"
+ COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/src"
+ end
+
+ def post_runner_generate(arg_hash)
+ # After the test runner file has been created, append the FFF globals
+ # definition to the end of the test runner. These globals will be shared by
+ # all mocks linked into the test.
+ File.open(arg_hash[:runner_file], 'a') do |f|
+ f.puts
+ f.puts "//=======Defintions of FFF variables====="
+ f.puts %{#include "fff.h"}
+ f.puts "DEFINE_FFF_GLOBALS;"
+ end
+ end
+
+end # class FakeFunctionFramework
+
+class FffMockGeneratorForCMock
+
+ def initialize(options=nil)
+ @cm_config = CMockConfig.new(options)
+ @cm_parser = CMockHeaderParser.new(@cm_config)
+ @silent = (@cm_config.verbosity < 2)
+
+ # These are the additional files to include in the mock files.
+ @includes_h_pre_orig_header = (@cm_config.includes || @cm_config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+ @includes_h_post_orig_header = (@cm_config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+ @includes_c_pre_header = (@cm_config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+ @includes_c_post_header = (@cm_config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+ end
+
+ def setup_mocks(files)
+ [files].flatten.each do |src|
+ generate_mock (src)
+ end
+ end
+
+ def generate_mock (header_file_to_mock)
+ module_name = File.basename(header_file_to_mock, '.h')
+ puts "Creating mock for #{module_name}..." unless @silent
+ mock_name = @cm_config.mock_prefix + module_name + @cm_config.mock_suffix
+ mock_path = @cm_config.mock_path
+ if @cm_config.subdir
+ # If a subdirectory has been configured, append it to the mock path.
+ mock_path = "#{mock_path}/#{@cm_config.subdir}"
+ end
+ full_path_for_mock = "#{mock_path}/#{mock_name}"
+
+ # Parse the header file so we know what to mock.
+ parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock))
+
+ # Create the directory if it doesn't exist.
+ mkdir_p full_path_for_mock.pathmap("%d")
+
+ # Generate the mock header file.
+ puts "Creating mock: #{full_path_for_mock}.h"
+
+ # Create the mock header.
+ File.open("#{full_path_for_mock}.h", 'w') do |f|
+ f.write(FffMockGenerator.create_mock_header(module_name, mock_name, parsed_header,
+ @includes_h_pre_orig_header, @includes_h_post_orig_header))
+ end
+
+ # Create the mock source file.
+ File.open("#{full_path_for_mock}.c", 'w') do |f|
+ f.write(FffMockGenerator.create_mock_source(mock_name, parsed_header,
+ @includes_c_pre_orig_header, @includes_c_post_orig_header))
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb
new file mode 100755
index 00000000..9dc03a65
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb
@@ -0,0 +1,163 @@
+# Creates mock files from parsed header files that can be linked into applications.
+# The mocks created are compatible with CMock for use with Ceedling.
+
+class FffMockGenerator
+
+ def self.create_mock_header(module_name, mock_name, parsed_header, pre_includes=nil,
+ post_includes=nil)
+ output = StringIO.new
+ write_opening_include_guard(mock_name, output)
+ output.puts
+ write_extra_includes(pre_includes, output)
+ write_header_includes(module_name, output)
+ write_extra_includes(post_includes, output)
+ output.puts
+ write_typedefs(parsed_header, output)
+ output.puts
+ write_function_declarations(parsed_header, output)
+ output.puts
+ write_control_function_prototypes(mock_name, output)
+ output.puts
+ write_closing_include_guard(mock_name, output)
+ output.string
+ end
+
+ def self.create_mock_source (mock_name, parsed_header, pre_includes=nil,
+ post_includes=nil)
+ output = StringIO.new
+ write_extra_includes(pre_includes, output)
+ write_source_includes(mock_name, output)
+ write_extra_includes(post_includes, output)
+ output.puts
+ write_function_definitions(parsed_header, output)
+ output.puts
+ write_control_function_definitions(mock_name, parsed_header, output)
+ output.string
+ end
+
+ private
+
+# Header file generation functions.
+
+ def self.write_opening_include_guard(mock_name, output)
+ output.puts "#ifndef #{mock_name}_H"
+ output.puts "#define #{mock_name}_H"
+ end
+
+ def self.write_header_includes(module_name, output)
+ output.puts %{#include "fff.h"}
+ output.puts %{#include "fff_unity_helper.h"}
+ output.puts %{#include "#{module_name}.h"}
+ end
+
+ def self.write_typedefs(parsed_header, output)
+ return unless parsed_header.key?(:typedefs)
+ parsed_header[:typedefs].each do |typedef|
+ output.puts typedef
+ end
+ end
+
+ def self.write_function_declarations(parsed_header, output)
+ write_function_macros("DECLARE", parsed_header, output)
+ end
+
+
+ def self.write_control_function_prototypes(mock_name, output)
+ output.puts "void #{mock_name}_Init(void);"
+ output.puts "void #{mock_name}_Verify(void);"
+ output.puts "void #{mock_name}_Destroy(void);"
+ end
+
+ def self.write_closing_include_guard(mock_name, output)
+ output.puts "#endif // #{mock_name}_H"
+ end
+
+# Source file generation functions.
+
+ def self.write_source_includes (mock_name, output)
+ output.puts "#include <string.h>"
+ output.puts %{#include "fff.h"}
+ output.puts %{#include "#{mock_name}.h"}
+ end
+
+ def self.write_function_definitions(parsed_header, output)
+ write_function_macros("DEFINE", parsed_header, output)
+ end
+
+ def self.write_control_function_definitions(mock_name, parsed_header, output)
+ output.puts "void #{mock_name}_Init(void)"
+ output.puts "{"
+ # In the init function, reset the FFF globals. These are used for things
+ # like the call history.
+ output.puts " FFF_RESET_HISTORY();"
+
+ # Also, reset all of the fakes.
+ if parsed_header[:functions]
+ parsed_header[:functions].each do |function|
+ output.puts " RESET_FAKE(#{function[:name]})"
+ end
+ end
+ output.puts "}"
+ output.puts "void #{mock_name}_Verify(void)"
+ output.puts "{"
+ output.puts "}"
+ output.puts "void #{mock_name}_Destroy(void)"
+ output.puts "{"
+ output.puts "}"
+ end
+
+# Shared functions.
+
+ def self.write_extra_includes(includes, output)
+ if includes
+ includes.each {|inc| output.puts "#include #{inc}\n"}
+ end
+ end
+
+ def self.write_function_macros(macro_type, parsed_header, output)
+ return unless parsed_header.key?(:functions)
+ parsed_header[:functions].each do |function|
+ name = function[:name]
+ return_type = function[:return][:type]
+ if function.has_key? :modifier
+ # Prepend any modifier. If there isn't one, trim any leading whitespace.
+ return_type = "#{function[:modifier]} #{return_type}".lstrip
+ end
+ arg_count = function[:args].size
+
+ # Check for variable arguments.
+ var_arg_suffix = ""
+ if function[:var_arg]
+ # If there are are variable arguments, then we need to add this argument
+ # to the count, update the suffix that will get added to the macro.
+ arg_count += 1
+ var_arg_suffix = "_VARARG"
+ end
+
+ # Generate the correct macro.
+ if return_type == 'void'
+ output.print "#{macro_type}_FAKE_VOID_FUNC#{arg_count}#{var_arg_suffix}(#{name}"
+ else
+ output.print "#{macro_type}_FAKE_VALUE_FUNC#{arg_count}#{var_arg_suffix}(#{return_type}, #{name}"
+ end
+
+ # Append each argument type.
+ function[:args].each do |arg|
+ output.print ", "
+ if arg[:const?]
+ output.print "const "
+ end
+ output.print "#{arg[:type]}"
+ end
+
+ # If this argument list ends with a variable argument, add it here at the end.
+ if function[:var_arg]
+ output.print ", ..."
+ end
+
+ # Close the declaration.
+ output.puts ");"
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb
new file mode 100755
index 00000000..e6ac11dd
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb
@@ -0,0 +1,304 @@
+require 'stringio'
+require 'fff_mock_generator.rb'
+require 'header_generator.rb'
+
+# Test the contents of the .h file created for the mock.
+describe "FffMockGenerator.create_mock_header" do
+
+ context "when there is nothing to mock," do
+ let(:mock_header) {
+ parsed_header = {}
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated header file starts with an opening include guard" do
+ expect(mock_header).to start_with(
+ "#ifndef mock_display_H\n" +
+ "#define mock_display_H")
+ end
+ it "then the generated file ends with a closing include guard" do
+ expect(mock_header).to end_with(
+ "#endif // mock_display_H\n")
+ end
+ it "then the generated file includes the fff header" do
+ expect(mock_header).to include(
+ %{#include "fff.h"\n})
+ end
+ it "then the generated file has a prototype for the init function" do
+ expect(mock_header).to include(
+ "void mock_display_Init(void);")
+ end
+ it "then the generated file has a prototype for the verify function" do
+ expect(mock_header).to include(
+ "void mock_display_Verify(void);")
+ end
+ it "then the generated file has a prototype for the destroy function" do
+ expect(mock_header).to include(
+ "void mock_display_Destroy(void);")
+ end
+ end
+
+ context "when there is a function with no args and a void return," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ [{:name => 'display_turnOffStatusLed', :return_type => 'void'}])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated header file starts with an opening include guard" do
+ expect(mock_header).to start_with(
+ "#ifndef mock_display_H\n" +
+ "#define mock_display_H")
+ end
+ it "then the generated header file contains a fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VOID_FUNC0(display_turnOffStatusLed);"
+ )
+ end
+ it "then the generated file ends with a closing include guard" do
+ expect(mock_header).to end_with(
+ "#endif // mock_display_H\n")
+ end
+ end
+
+ context "when there is a function with no args and a bool return," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ [{:name => 'display_isError', :return_type => 'bool'}])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VALUE_FUNC0(bool, display_isError);"
+ )
+ end
+ end
+
+ context "when there is a function with no args and an int return," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ [{:name => 'display_isError', :return_type => 'int'}])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VALUE_FUNC0(int, display_isError);"
+ )
+ end
+ end
+
+ context "when there is a function with args and a void return," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ [{:name => 'display_setVolume', :return_type => 'void', :args => ['int']}])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VOID_FUNC1(display_setVolume, int);"
+ )
+ end
+ end
+
+ context "when there is a function with args and a value return," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ [{:name => 'a_function', :return_type => 'int', :args => ['char *']}])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the fake function declaration" do
+ expect(mock_header).to include(
+ "FAKE_VALUE_FUNC1(int, a_function, char *);"
+ )
+ end
+ end
+
+ context "when there is a function with many args and a void return," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ [{:name => 'a_function', :return_type => 'void',
+ :args => ['int', 'char *', 'int', 'int', 'bool', 'applesauce']}])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VOID_FUNC6(a_function, int, char *, int, int, bool, applesauce);"
+ )
+ end
+ end
+
+ context "when there are multiple functions," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ [ {:name => 'a_function', :return_type => 'int', :args => ['char *']},
+ {:name => 'another_function', :return_type => 'void'},
+ {:name => 'three', :return_type => 'bool', :args => ['float', 'int']}
+ ])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the first fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VALUE_FUNC1(int, a_function, char *);"
+ )
+ end
+ it "then the generated file contains the second fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VOID_FUNC0(another_function);"
+ )
+ end
+ it "then the generated file contains the third fake function declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VALUE_FUNC2(bool, three, float, int);"
+ )
+ end
+ end
+
+ context "when there is a typedef," do
+ let(:mock_header) {
+ parsed_header = create_cmock_style_parsed_header(
+ nil, ["typedef void (*displayCompleteCallback) (void);"])
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the typedef" do
+ expect(mock_header).to include(
+ "typedef void (*displayCompleteCallback) (void);"
+ )
+ end
+ end
+
+ context "when there is a void function with variable arguments" do
+ let(:mock_header){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "function_with_var_args",
+ :return => {:type => "void"},
+ :var_arg => "...",
+ :args => [{:type => 'char *'}]
+ }]
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the vararg declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VOID_FUNC2_VARARG(function_with_var_args, char *, ...)"
+ )
+ end
+ end
+
+ context "when there is a function with a return value and variable arguments" do
+ let(:mock_header){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "function_with_var_args",
+ :return => {:type => "int"},
+ :var_arg => "...",
+ :args => [{:type => 'char *'}]
+ }]
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the vararg declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VALUE_FUNC2_VARARG(int, function_with_var_args, char *, ...)"
+ )
+ end
+ end
+
+ context "when there is a void function with variable arguments and " +
+ "additional arguments" do
+ let(:mock_header){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "function_with_var_args",
+ :return => {:type => "void"},
+ :var_arg => "...",
+ :args => [{:type => 'char *'}, {:type => 'int'}]
+ }]
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the vararg declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)"
+ )
+ end
+ end
+
+ context "when there is a function with a pointer to a const value" do
+ let(:mock_header){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "const_test_function",
+ :return => {:type => "void"},
+ :args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true},
+ {:type => "char *", :name => "b", :ptr? => false, :const? => false}]
+ }]
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the correct const argument in the declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)"
+ )
+ end
+ end
+
+ context "when there is a function that returns a const pointer" do
+ let(:mock_header){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "return_const_pointer_test_function",
+ :modifier => "const",
+ :return => {:type => "char *" },
+ :args => [{:type => "int", :name => "a"}]
+ }]
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the correct const return value in the declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VALUE_FUNC1(const char *, return_const_pointer_test_function, int)"
+ )
+ end
+ end
+
+ context "when there is a function that returns a const int" do
+ let(:mock_header){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "return_const_int_test_function",
+ :modifier => "const",
+ :return => {:type => "int" },
+ :args => []
+ }]
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header)
+ }
+ it "then the generated file contains the correct const return value in the declaration" do
+ expect(mock_header).to include(
+ "DECLARE_FAKE_VALUE_FUNC0(const int, return_const_int_test_function)"
+ )
+ end
+ end
+
+ context "when there are pre-includes" do
+ let(:mock_header) {
+ parsed_header = {}
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header,
+ [%{"another_header.h"}])
+ }
+ it "then they are included before the other files" do
+ expect(mock_header).to include(
+ %{#include "another_header.h"\n} +
+ %{#include "fff.h"}
+ )
+ end
+ end
+
+ context "when there are post-includes" do
+ let(:mock_header) {
+ parsed_header = {}
+ FffMockGenerator.create_mock_header("display", "mock_display", parsed_header,
+ nil, [%{"another_header.h"}])
+ }
+ it "then they are included after the other files" do
+ expect(mock_header).to include(
+ %{#include "display.h"\n} +
+ %{#include "another_header.h"\n}
+ )
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb
new file mode 100755
index 00000000..364f8521
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb
@@ -0,0 +1,149 @@
+require 'stringio'
+require 'fff_mock_generator.rb'
+
+# Test the contents of the .c file created for the mock.
+describe "FffMockGenerator.create_mock_source" do
+
+ context "when there is nothing to mock," do
+ let(:mock_source) {
+ parsed_header = {}
+ FffMockGenerator.create_mock_source("mock_my_module", parsed_header)
+ }
+ it "then the generated file includes the fff header" do
+ expect(mock_source).to include(
+ # fff.h also requires including string.h
+ %{#include <string.h>\n} +
+ %{#include "fff.h"}
+ )
+ end
+ it "then the generated file includes the mock header" do
+ expect(mock_source).to include(
+ %{#include "mock_my_module.h"\n}
+ )
+ end
+ it "then the generated file defines the init function" do
+ expect(mock_source).to include(
+ "void mock_my_module_Init(void)\n" +
+ "{\n" +
+ " FFF_RESET_HISTORY();\n" +
+ "}"
+ )
+ end
+ it "then the generated file defines the verify function" do
+ expect(mock_source).to include(
+ "void mock_my_module_Verify(void)\n" +
+ "{\n" +
+ "}"
+ )
+ end
+ it "then the generated file defines the destroy function" do
+ expect(mock_source).to include(
+ "void mock_my_module_Destroy(void)\n" +
+ "{\n" +
+ "}"
+ )
+ end
+ end
+
+ context "when there are multiple functions," do
+ let(:mock_source) {
+ parsed_header = create_cmock_style_parsed_header(
+ [ {:name => 'a_function', :return_type => 'int', :args => ['char *']},
+ {:name => 'another_function', :return_type => 'void'},
+ {:name => 'three', :return_type => 'bool', :args => ['float', 'int']}
+ ])
+ FffMockGenerator.create_mock_source("mock_display", parsed_header)
+ }
+ it "then the generated file contains the first fake function definition" do
+ expect(mock_source).to include(
+ "DEFINE_FAKE_VALUE_FUNC1(int, a_function, char *);"
+ )
+ end
+ it "then the generated file contains the second fake function definition" do
+ expect(mock_source).to include(
+ "DEFINE_FAKE_VOID_FUNC0(another_function);"
+ )
+ end
+ it "then the generated file contains the third fake function definition" do
+ expect(mock_source).to include(
+ "DEFINE_FAKE_VALUE_FUNC2(bool, three, float, int);"
+ )
+ end
+ it "then the init function resets all of the fakes" do
+ expect(mock_source).to include(
+ "void mock_display_Init(void)\n" +
+ "{\n" +
+ " FFF_RESET_HISTORY();\n" +
+ " RESET_FAKE(a_function)\n" +
+ " RESET_FAKE(another_function)\n" +
+ " RESET_FAKE(three)\n" +
+ "}"
+ )
+ end
+ end
+
+ context "when there is a void function with variable arguments and " +
+ "additional arguments" do
+ let(:mock_source){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "function_with_var_args",
+ :return => {:type => "void"},
+ :var_arg => "...",
+ :args => [{:type => 'char *'}, {:type => 'int'}]
+ }]
+ FffMockGenerator.create_mock_source("mock_display", parsed_header)
+ }
+ it "then the generated file contains the vararg definition" do
+ expect(mock_source).to include(
+ "DEFINE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)"
+ )
+ end
+ end
+
+ context "when there is a function with a pointer to a const value" do
+ let(:mock_source){
+ parsed_header = {}
+ parsed_header[:functions] = [{
+ :name => "const_test_function",
+ :return => {:type => "void"},
+ :args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true},
+ {:type => "char *", :name => "b", :ptr? => false, :const? => false}]
+ }]
+ FffMockGenerator.create_mock_source("mock_display", parsed_header)
+ }
+ it "then the generated file contains the correct const argument in the declaration" do
+ expect(mock_source).to include(
+ "DEFINE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)"
+ )
+ end
+ end
+
+ context "when there are pre-includes" do
+ let(:mock_source) {
+ parsed_source = {}
+ FffMockGenerator.create_mock_source("mock_display", parsed_source,
+ [%{"another_header.h"}])
+ }
+ it "then they are included before the other files" do
+ expect(mock_source).to include(
+ %{#include "another_header.h"\n} +
+ %{#include <string.h>}
+ )
+ end
+ end
+
+ context "when there are post-includes" do
+ let(:mock_source) {
+ parsed_source = {}
+ FffMockGenerator.create_mock_source("mock_display", parsed_source,
+ nil, [%{"another_header.h"}])
+ }
+ it "then they are included before the other files" do
+ expect(mock_source).to include(
+ %{#include "mock_display.h"\n} +
+ %{#include "another_header.h"\n}
+ )
+ end
+ end
+end \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb
new file mode 100755
index 00000000..cda27844
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb
@@ -0,0 +1,51 @@
+# Create a CMock-style parsed header hash. This the type of hash created by
+# CMock when parsing header files for automock generation. It contains all of
+# includes, typedefs and functions (with return types and arguments) parsed from
+# the header file.
+def create_cmock_style_parsed_header(functions, typedefs = nil)
+ parsed_header = {
+ :includes => nil,
+ :functions => [],
+ :typedefs => []
+ }
+
+ # Add the typedefs.
+ if typedefs
+ typedefs.each do |typedef|
+ parsed_header[:typedefs] << typedef
+ end
+ end
+
+ # Add the functions.
+ if functions
+ functions.each do |function|
+ # Build the array of arguments.
+ args = []
+ if function.key?(:args)
+ function[:args].each do |arg|
+ args << {
+ :type => arg
+ }
+ end
+ end
+ parsed_header[:functions] << {
+ :name => function[:name],
+ :modifier => "",
+ :return => {
+ :type => function[:return_type],
+ :name => "cmock_to_return",
+ :ptr? => false,
+ :const? => false,
+ :str => "void cmock_to_return",
+ :void? => true
+ },
+ :var_arg => nil,
+ :args_string => "void",
+ :args => args,
+ :args_call => "",
+ :contains_ptr? => false
+ }
+ end
+ end
+ parsed_header
+end \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb
new file mode 100755
index 00000000..25dc80ac
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb
@@ -0,0 +1,96 @@
+# This file was generated by the `rspec --init` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause
+# this file to always be loaded, without a need to explicitly require it in any
+# files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, consider making
+# a separate helper file that requires the additional dependencies and performs
+# the additional setup, and require it from the spec files that actually need
+# it.
+#
+# The `.rspec` file also contains a few flags that are not defaults but that
+# users commonly want.
+#
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ # rspec-expectations config goes here. You can use an alternate
+ # assertion/expectation library such as wrong or the stdlib/minitest
+ # assertions if you prefer.
+ config.expect_with :rspec do |expectations|
+ # This option will default to `true` in RSpec 4. It makes the `description`
+ # and `failure_message` of custom matchers include text for helper methods
+ # defined using `chain`, e.g.:
+ # be_bigger_than(2).and_smaller_than(4).description
+ # # => "be bigger than 2 and smaller than 4"
+ # ...rather than:
+ # # => "be bigger than 2"
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # rspec-mocks config goes here. You can use an alternate test double
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
+ config.mock_with :rspec do |mocks|
+ # Prevents you from mocking or stubbing a method that does not exist on
+ # a real object. This is generally recommended, and will default to
+ # `true` in RSpec 4.
+ mocks.verify_partial_doubles = true
+ end
+
+# The settings below are suggested to provide a good initial experience
+# with RSpec, but feel free to customize to your heart's content.
+=begin
+ # These two settings work together to allow you to limit a spec run
+ # to individual examples or groups you care about by tagging them with
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+ # get run.
+ config.filter_run :focus
+ config.run_all_when_everything_filtered = true
+
+ # Allows RSpec to persist some state between runs in order to support
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
+ # you configure your source control system to ignore this file.
+ config.example_status_persistence_file_path = "spec/examples.txt"
+
+ # Limits the available syntax to the non-monkey patched syntax that is
+ # recommended. For more details, see:
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
+ config.disable_monkey_patching!
+
+ # This setting enables warnings. It's recommended, but in some cases may
+ # be too noisy due to issues in dependencies.
+ config.warnings = true
+
+ # Many RSpec users commonly either run the entire suite or an individual
+ # file, and it's useful to allow more verbose output when running an
+ # individual spec file.
+ if config.files_to_run.one?
+ # Use the documentation formatter for detailed output,
+ # unless a formatter has already been configured
+ # (e.g. via a command-line flag).
+ config.default_formatter = 'doc'
+ end
+
+ # Print the 10 slowest examples and example groups at the
+ # end of the spec run, to help surface which specs are running
+ # particularly slow.
+ config.profile_examples = 10
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = :random
+
+ # Seed global randomization in this process using the `--seed` CLI option.
+ # Setting this allows you to use `--seed` to deterministically reproduce
+ # test failures related to randomization by passing the same `--seed` value
+ # as the one that triggered the failure.
+ Kernel.srand config.seed
+=end
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h
new file mode 100755
index 00000000..de3db44a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h
@@ -0,0 +1,33 @@
+#ifndef fff_unity_helper_H
+#define fff_unity_helper_H
+
+/*
+ FFF helper macros for Unity.
+*/
+
+/*
+ Fail if the function was not called the expected number of times.
+*/
+#define TEST_ASSERT_CALLED_TIMES(times_, function_) \
+ TEST_ASSERT_EQUAL_MESSAGE(times_, \
+ function_ ## _fake.call_count, \
+ "Function " #function_ " called the incorrect number of times.")
+/*
+ Fail if the function was not called exactly once.
+*/
+#define TEST_ASSERT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(1, function_)
+
+/*
+ Fail if the function was called 1 or more times.
+*/
+#define TEST_ASSERT_NOT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(0, function_)
+
+/*
+ Fail if the function was not called in this particular order.
+*/
+#define TEST_ASSERT_CALLED_IN_ORDER(order_, function_) \
+ TEST_ASSERT_EQUAL_PTR_MESSAGE((void *) function_, \
+ fff.call_history[order_], \
+ "Function " #function_ " not called in order " #order_ )
+
+#endif \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/README.md b/tinyusb/test/vendor/ceedling/plugins/gcov/README.md
new file mode 100755
index 00000000..096ffa10
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/gcov/README.md
@@ -0,0 +1,101 @@
+ceedling-gcov
+=============
+
+# Plugin Overview
+
+Plugin for integrating GNU GCov code coverage tool into Ceedling projects.
+Currently only designed for the gcov command (like LCOV for example). In the
+future we could configure this to work with other code coverage tools.
+
+This plugin currently uses `gcovr` to generate HTML and/or XML reports as a
+utility. The normal gcov plugin _must_ be run first for this report to generate.
+
+## Installation
+
+Gcovr can be installed via pip like so:
+
+```
+pip install gcovr
+```
+
+## Configuration
+
+The gcov plugin supports configuration options via your `project.yml` provided
+by Ceedling.
+
+Generation of HTML reports may be enabled or disabled with the following
+config. Set to `true` to enable or set to `false` to disable.
+
+```
+:gcov:
+ :html_report: true
+```
+
+Generation of XML reports may be enabled or disabled with the following
+config. Set to `true` to enable or set to `false` to disable.
+
+```
+:gcov:
+ :xml_report: true
+```
+
+There are two types of gcovr HTML reports that can be configured in your
+`project.yml`. To create a basic HTML report, with only the overall file
+information, use the following config.
+
+```
+:gcov:
+ :html_report_type: basic
+```
+
+To create a detailed HTML report, with line by line breakdown of the
+coverage, use the following config.
+
+```
+:gcov:
+ :html_report_type: detailed
+```
+
+There are a number of options to control which files are considered part of
+the coverage report. Most often, we only care about coverage on our source code, and not
+on tests or automatically generated mocks, runners, etc. However, there are times
+where this isn't true... or there are times where we've moved ceedling's directory
+structure so that the project file isn't at the root of the project anymore. In these
+cases, you may need to tweak the following:
+
+```
+:gcov:
+ :report_root: "."
+ :report_exclude: "^build|^vendor|^test|^support"
+ :report_include: "^src"
+```
+
+One important note about html_report_root: gcovr will only take a single root folder, unlike
+Ceedling's ability to take as many as you like. So you will need to choose a folder which is
+a superset of ALL the folders you want, and then use the include or exclude options to set up
+patterns of files to pay attention to or ignore. It's not ideal, but it works.
+
+Finally, there are a number of settings which can be specified in order to adjust the
+default behaviors of gcov:
+
+```
+:gcov:
+ :html_medium_threshold: 75
+ :html_high_threshold: 90
+ :fail_under_line: 30
+ :fail_under_branch: 30
+```
+
+These HTML and XML reports will be found in `build/artifacts/gcov`.
+
+## Example Usage
+
+```
+ceedling gcov:all utils:gcov
+```
+
+## To-Do list
+
+- Generate overall report (combined statistics from all files with coverage)
+- Generate coverage output files
+- Easier option override for better customisation
diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/gcov/assets/template.erb
new file mode 100755
index 00000000..5e5a1742
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/gcov/assets/template.erb
@@ -0,0 +1,15 @@
+% function_string = hash[:coverage][:functions].to_s
+% branch_string = hash[:coverage][:branches].to_s
+% format_string = "%#{[function_string.length, branch_string.length].max}i"
+<%=@ceedling[:plugin_reportinator].generate_banner("#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY")%>
+% if (!hash[:coverage][:functions].nil?)
+FUNCTIONS: <%=sprintf(format_string, hash[:coverage][:functions])%>%
+% else
+FUNCTIONS: none
+% end
+% if (!hash[:coverage][:branches].nil?)
+BRANCHES: <%=sprintf(format_string, hash[:coverage][:branches])%>%
+% else
+BRANCHES: none
+% end
+
diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/config/defaults.yml b/tinyusb/test/vendor/ceedling/plugins/gcov/config/defaults.yml
new file mode 100755
index 00000000..13bac556
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/gcov/config/defaults.yml
@@ -0,0 +1,73 @@
+---
+
+:tools:
+ :gcov_compiler:
+ :executable: gcc
+ :arguments:
+ - -g
+ - -fprofile-arcs
+ - -ftest-coverage
+ - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR
+ - -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE
+ - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR
+ - -DGCOV_COMPILER
+ - -DCODE_COVERAGE
+ - -c "${1}"
+ - -o "${2}"
+ :gcov_linker:
+ :executable: gcc
+ :arguments:
+ - -fprofile-arcs
+ - -ftest-coverage
+ - ${1}
+ - -o ${2}
+ - ${3}
+ :gcov_fixture:
+ :executable: ${1}
+ :gcov_report:
+ :executable: gcov
+ :arguments:
+ - -n
+ - -p
+ - -b
+ - -o "$": GCOV_BUILD_OUTPUT_PATH
+ - "\"${1}\""
+ :gcov_post_report:
+ :executable: gcovr
+ :optional: TRUE
+ :arguments:
+ - -p
+ - -b
+ - ${1}
+ - --html
+ - -o GcovCoverageResults.html
+ :gcov_post_report_basic:
+ :executable: gcovr
+ :optional: TRUE
+ :arguments:
+ - -p
+ - -b
+ - ${1}
+ - --html
+ - -o "$": GCOV_ARTIFACTS_FILE
+ :gcov_post_report_advanced:
+ :executable: gcovr
+ :optional: TRUE
+ :arguments:
+ - -p
+ - -b
+ - ${1}
+ - --html
+ - --html-details
+ - -o "$": GCOV_ARTIFACTS_FILE
+ :gcov_post_report_xml:
+ :executable: gcovr
+ :optional: TRUE
+ :arguments:
+ - -p
+ - -b
+ - ${1}
+ - --xml
+ - -o "$": GCOV_ARTIFACTS_FILE_XML
+
+...
diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/gcov.rake b/tinyusb/test/vendor/ceedling/plugins/gcov/gcov.rake
new file mode 100755
index 00000000..3acab856
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/gcov/gcov.rake
@@ -0,0 +1,220 @@
+directory(GCOV_BUILD_OUTPUT_PATH)
+directory(GCOV_RESULTS_PATH)
+directory(GCOV_ARTIFACTS_PATH)
+directory(GCOV_DEPENDENCIES_PATH)
+
+CLEAN.include(File.join(GCOV_BUILD_OUTPUT_PATH, '*'))
+CLEAN.include(File.join(GCOV_RESULTS_PATH, '*'))
+CLEAN.include(File.join(GCOV_ARTIFACTS_PATH, '*'))
+CLEAN.include(File.join(GCOV_DEPENDENCIES_PATH, '*'))
+
+CLOBBER.include(File.join(GCOV_BUILD_PATH, '**/*'))
+
+rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_OBJECT}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name)
+ end
+ ]) do |object|
+
+ if File.basename(object.source) =~ /^(#{PROJECT_TEST_FILE_PREFIX}|#{CMOCK_MOCK_PREFIX}|#{GCOV_IGNORE_SOURCES.join('|')})/i
+ @ceedling[:generator].generate_object_file(
+ TOOLS_GCOV_COMPILER,
+ OPERATION_COMPILE_SYM,
+ GCOV_SYM,
+ object.source,
+ object.name,
+ @ceedling[:file_path_utils].form_test_build_list_filepath(object.name)
+ )
+ else
+ @ceedling[GCOV_SYM].generate_coverage_object_file(object.source, object.name)
+ end
+end
+
+rule(/#{GCOV_BUILD_OUTPUT_PATH}\/#{'.+\\' + EXTENSION_EXECUTABLE}$/) do |bin_file|
+ lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments()
+
+ @ceedling[:generator].generate_executable_file(
+ TOOLS_GCOV_LINKER,
+ GCOV_SYM,
+ bin_file.prerequisites,
+ bin_file.name,
+ lib_args,
+ @ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name)
+ )
+end
+
+rule(/#{GCOV_RESULTS_PATH}\/#{'.+\\' + EXTENSION_TESTPASS}$/ => [
+ proc do |task_name|
+ @ceedling[:file_path_utils].form_test_executable_filepath(task_name)
+ end
+ ]) do |test_result|
+ @ceedling[:generator].generate_test_results(TOOLS_GCOV_FIXTURE, GCOV_SYM, test_result.source, test_result.name)
+end
+
+rule(/#{GCOV_DEPENDENCIES_PATH}\/#{'.+\\' + EXTENSION_DEPENDENCIES}$/ => [
+ proc do |task_name|
+ @ceedling[:file_finder].find_compilation_input_file(task_name)
+ end
+ ]) do |dep|
+ @ceedling[:generator].generate_dependencies_file(
+ TOOLS_TEST_DEPENDENCIES_GENERATOR,
+ GCOV_SYM,
+ dep.source,
+ File.join(GCOV_BUILD_OUTPUT_PATH, File.basename(dep.source).ext(EXTENSION_OBJECT)),
+ dep.name
+ )
+end
+
+task directories: [GCOV_BUILD_OUTPUT_PATH, GCOV_RESULTS_PATH, GCOV_DEPENDENCIES_PATH, GCOV_ARTIFACTS_PATH]
+
+namespace GCOV_SYM do
+ task source_coverage: COLLECTION_ALL_SOURCE.pathmap("#{GCOV_BUILD_OUTPUT_PATH}/%n#{@ceedling[:configurator].extension_object}")
+
+ desc 'Run code coverage for all tests'
+ task all: [:directories] do
+ @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
+ @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM)
+ @ceedling[:configurator].restore_config
+ end
+
+ desc 'Run single test w/ coverage ([*] real test or source file name, no path).'
+ task :* do
+ message = "\nOops! '#{GCOV_ROOT_NAME}:*' isn't a real task. " \
+ "Use a real test or source file name (no path) in place of the wildcard.\n" \
+ "Example: rake #{GCOV_ROOT_NAME}:foo.c\n\n"
+
+ @ceedling[:streaminator].stdout_puts(message)
+ end
+
+ desc 'Run tests by matching regular expression pattern.'
+ task :pattern, [:regex] => [:directories] do |_t, args|
+ matches = []
+
+ COLLECTION_ALL_TESTS.each do |test|
+ matches << test if test =~ /#{args.regex}/
+ end
+
+ if !matches.empty?
+ @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
+ @ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false)
+ @ceedling[:configurator].restore_config
+ else
+ @ceedling[:streaminator].stdout_puts("\nFound no tests matching pattern /#{args.regex}/.")
+ end
+ end
+
+ desc 'Run tests whose test path contains [dir] or [dir] substring.'
+ task :path, [:dir] => [:directories] do |_t, args|
+ matches = []
+
+ COLLECTION_ALL_TESTS.each do |test|
+ matches << test if File.dirname(test).include?(args.dir.tr('\\', '/'))
+ end
+
+ if !matches.empty?
+ @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
+ @ceedling[:test_invoker].setup_and_invoke(matches, GCOV_SYM, force_run: false)
+ @ceedling[:configurator].restore_config
+ else
+ @ceedling[:streaminator].stdout_puts("\nFound no tests including the given path or path component.")
+ end
+ end
+
+ desc 'Run code coverage for changed files'
+ task delta: [:directories] do
+ @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
+ @ceedling[:test_invoker].setup_and_invoke(COLLECTION_ALL_TESTS, GCOV_SYM, force_run: false)
+ @ceedling[:configurator].restore_config
+ end
+
+ # use a rule to increase efficiency for large projects
+ # gcov test tasks by regex
+ rule(/^#{GCOV_TASK_ROOT}\S+$/ => [
+ proc do |task_name|
+ test = task_name.sub(/#{GCOV_TASK_ROOT}/, '')
+ test = "#{PROJECT_TEST_FILE_PREFIX}#{test}" unless test.start_with?(PROJECT_TEST_FILE_PREFIX)
+ @ceedling[:file_finder].find_test_from_file_path(test)
+ end
+ ]) do |test|
+ @ceedling[:rake_wrapper][:directories].invoke
+ @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
+ @ceedling[:test_invoker].setup_and_invoke([test.source], GCOV_SYM)
+ @ceedling[:configurator].restore_config
+ end
+end
+
+if PROJECT_USE_DEEP_DEPENDENCIES
+ namespace REFRESH_SYM do
+ task GCOV_SYM do
+ @ceedling[:configurator].replace_flattened_config(@ceedling[GCOV_SYM].config)
+ @ceedling[:test_invoker].refresh_deep_dependencies
+ @ceedling[:configurator].restore_config
+ end
+ end
+end
+
+namespace UTILS_SYM do
+ def gcov_args_builder(opts)
+ args = ""
+ args += "-r \"#{opts[:gcov_report_root] || '.'}\" "
+ args += "-f \"#{opts[:gcov_report_include]}\" " unless opts[:gcov_report_include].nil?
+ args += "-e \"#{opts[:gcov_report_exclude] || GCOV_FILTER_EXCLUDE}\" "
+ [ :gcov_fail_under_line, :gcov_fail_under_branch, :gcov_html_medium_threshold, :gcov_html_high_threshold].each do |opt|
+ args += "--#{opt.to_s.gsub('_','-').sub(/:?gcov-/,'')} #{opts[opt]} " unless opts[opt].nil?
+ end
+ return args
+ end
+
+ desc 'Create gcov code coverage html report (must run ceedling gcov first)'
+ task GCOV_SYM do
+
+ if !File.directory? GCOV_ARTIFACTS_PATH
+ FileUtils.mkdir_p GCOV_ARTIFACTS_PATH
+ end
+
+ args = gcov_args_builder(@ceedling[:configurator].project_config_hash)
+
+ if @ceedling[:configurator].project_config_hash[:gcov_html_report].nil?
+ puts "In your project.yml, define: \n\n:gcov:\n :html_report:\n\n to true or false to refine this feature."
+ puts "For now, assumimg you want an html report generated."
+ html_enabled = true
+ else
+ html_enabled = @ceedling[:configurator].project_config_hash[:gcov_html_report]
+ end
+
+ if @ceedling[:configurator].project_config_hash[:gcov_xml_report].nil?
+ puts "In your project.yml, define: \n\n:gcov:\n :xml_report:\n\n to true or false to refine this feature."
+ puts "For now, assumimg you do not want an xml report generated."
+ xml_enabled = false
+ else
+ xml_enabled = @ceedling[:configurator].project_config_hash[:gcov_xml_report]
+ end
+
+ if html_enabled
+ if @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'basic'
+ puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], args)
+ @ceedling[:tool_executor].exec(command[:line], command[:options])
+ elsif @ceedling[:configurator].project_config_hash[:gcov_html_report_type] == 'detailed'
+ puts "Creating a detailed html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_ADVANCED, [], args)
+ @ceedling[:tool_executor].exec(command[:line], command[:options])
+
+ else
+ puts "In your project.yml, define: \n\n:gcov:\n :html_report_type:\n\n to basic or detailed to refine this feature."
+ puts "For now, just creating basic."
+ puts "Creating a basic html report of gcov results in #{GCOV_ARTIFACTS_FILE}..."
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_BASIC, [], args)
+ @ceedling[:tool_executor].exec(command[:line], command[:options])
+ end
+ end
+
+ if xml_enabled
+ puts "Creating an xml report of gcov results in #{GCOV_ARTIFACTS_FILE_XML}..."
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_POST_REPORT_XML, [], filter)
+ @ceedling[:tool_executor].exec(command[:line], command[:options])
+ end
+
+ puts "Done."
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov.rb b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov.rb
new file mode 100755
index 00000000..15a1b4cf
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov.rb
@@ -0,0 +1,113 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+require 'gcov_constants'
+
+class Gcov < Plugin
+ attr_reader :config
+
+ def setup
+ @result_list = []
+
+ @config = {
+ project_test_build_output_path: GCOV_BUILD_OUTPUT_PATH,
+ project_test_build_output_c_path: GCOV_BUILD_OUTPUT_PATH,
+ project_test_results_path: GCOV_RESULTS_PATH,
+ project_test_dependencies_path: GCOV_DEPENDENCIES_PATH,
+ defines_test: DEFINES_TEST + ['CODE_COVERAGE'],
+ gcov_html_report_filter: GCOV_FILTER_EXCLUDE
+ }
+
+ @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ @coverage_template_all = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
+ end
+
+ def generate_coverage_object_file(source, object)
+ lib_args = @ceedling[:test_invoker].convert_libraries_to_arguments()
+ compile_command =
+ @ceedling[:tool_executor].build_command_line(
+ TOOLS_GCOV_COMPILER,
+ @ceedling[:flaginator].flag_down(OPERATION_COMPILE_SYM, GCOV_SYM, source),
+ source,
+ object,
+ @ceedling[:file_path_utils].form_test_build_list_filepath(object),
+ lib_args
+ )
+ @ceedling[:streaminator].stdout_puts("Compiling #{File.basename(source)} with coverage...")
+ @ceedling[:tool_executor].exec(compile_command[:line], compile_command[:options])
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ result_file = arg_hash[:result_file]
+
+ if (result_file =~ /#{GCOV_RESULTS_PATH}/) && !@result_list.include?(result_file)
+ @result_list << arg_hash[:result_file]
+ end
+ end
+
+ def post_build
+ return unless @ceedling[:task_invoker].invoked?(/^#{GCOV_TASK_ROOT}/)
+
+ # test results
+ results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
+ hash = {
+ header: GCOV_ROOT_NAME.upcase,
+ results: results
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash) do
+ message = ''
+ message = 'Unit test failures.' if results[:counts][:failed] > 0
+ message
+ end
+
+ report_per_file_coverage_results(@ceedling[:test_invoker].sources)
+ end
+
+ def summary
+ result_list = @ceedling[:file_path_utils].form_pass_results_filelist(GCOV_RESULTS_PATH, COLLECTION_ALL_TESTS)
+
+ # test results
+ # get test results for only those tests in our configuration and of those only tests with results on disk
+ hash = {
+ header: GCOV_ROOT_NAME.upcase,
+ results: @ceedling[:plugin_reportinator].assemble_test_results(result_list, boom: false)
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash)
+ end
+
+ private ###################################
+
+ def report_per_file_coverage_results(sources)
+ banner = @ceedling[:plugin_reportinator].generate_banner "#{GCOV_ROOT_NAME.upcase}: CODE COVERAGE SUMMARY"
+ @ceedling[:streaminator].stdout_puts "\n" + banner
+
+ coverage_sources = sources.clone
+ coverage_sources.delete_if { |item| item =~ /#{CMOCK_MOCK_PREFIX}.+#{EXTENSION_SOURCE}$/ }
+ coverage_sources.delete_if { |item| item =~ /#{GCOV_IGNORE_SOURCES.join('|')}#{EXTENSION_SOURCE}$/ }
+
+ coverage_sources.each do |source|
+ basename = File.basename(source)
+ command = @ceedling[:tool_executor].build_command_line(TOOLS_GCOV_REPORT, [], [basename])
+ shell_results = @ceedling[:tool_executor].exec(command[:line], command[:options])
+ coverage_results = shell_results[:output]
+
+ if coverage_results.strip =~ /(File\s+'#{Regexp.escape(source)}'.+$)/m
+ report = Regexp.last_match(1).lines.to_a[1..-1].map { |line| basename + ' ' + line }.join('')
+ @ceedling[:streaminator].stdout_puts(report + "\n\n")
+ end
+ end
+
+ COLLECTION_ALL_SOURCE.each do |source|
+ unless coverage_sources.include?(source)
+ @ceedling[:streaminator].stdout_puts("Could not find coverage results for " + source + "\n")
+ end
+ end
+ end
+end
+
+# end blocks always executed following rake run
+END {
+ # cache our input configurations to use in comparison upon next execution
+ @ceedling[:cacheinator].cache_test_config(@ceedling[:setupinator].config_hash) if @ceedling[:task_invoker].invoked?(/^#{GCOV_TASK_ROOT}/)
+}
diff --git a/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb
new file mode 100755
index 00000000..539d46f7
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/gcov/lib/gcov_constants.rb
@@ -0,0 +1,19 @@
+
+GCOV_ROOT_NAME = 'gcov'.freeze
+GCOV_TASK_ROOT = GCOV_ROOT_NAME + ':'
+GCOV_SYM = GCOV_ROOT_NAME.to_sym
+
+GCOV_BUILD_PATH = File.join(PROJECT_BUILD_ROOT, GCOV_ROOT_NAME)
+GCOV_BUILD_OUTPUT_PATH = File.join(GCOV_BUILD_PATH, "out")
+GCOV_RESULTS_PATH = File.join(GCOV_BUILD_PATH, "results")
+GCOV_DEPENDENCIES_PATH = File.join(GCOV_BUILD_PATH, "dependencies")
+GCOV_ARTIFACTS_PATH = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, GCOV_ROOT_NAME)
+
+GCOV_ARTIFACTS_FILE = File.join(GCOV_ARTIFACTS_PATH, "GcovCoverageResults.html")
+GCOV_ARTIFACTS_FILE_XML = File.join(GCOV_ARTIFACTS_PATH, "GcovCoverageResults.xml")
+
+GCOV_IGNORE_SOURCES = %w(unity cmock cexception).freeze
+
+GCOV_FILTER_EXCLUDE = '^vendor.*|^build.*|^test.*|^lib.*'
+
+
diff --git a/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/README.md b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/README.md
new file mode 100755
index 00000000..1259fd66
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/README.md
@@ -0,0 +1,36 @@
+junit_tests_report
+====================
+
+## Overview
+
+The junit_tests_report plugin creates an XML file of test results in JUnit
+format, which is handy for Continuous Integration build servers or as input
+into other reporting tools. The XML file is output to the appropriate
+`<build_root>/artifacts/` directory (e.g. `artifacts/test/` for test tasks,
+`artifacts/gcov/` for gcov, or `artifacts/bullseye/` for bullseye runs).
+
+## Setup
+
+Enable the plugin in your project.yml by adding `junit_tests_report`
+to the list of enabled plugins.
+
+``` YAML
+:plugins:
+ :enabled:
+ - junit_tests_report
+```
+
+## Configuration
+
+Optionally configure the output / artifact filename in your project.yml with
+the `artifact_filename` configuration option. The default filename is
+`report.xml`.
+
+You can also configure the path that this artifact is stored. This can be done
+by setting `path`. The default is that it will be placed in a subfolder under
+the `build` directory.
+
+``` YAML
+:junit_tests_report:
+ :artifact_filename: report_junit.xml
+```
diff --git a/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb
new file mode 100755
index 00000000..a777d07d
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb
@@ -0,0 +1,129 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+
+class JunitTestsReport < Plugin
+
+ def setup
+ @results_list = {}
+ @test_counter = 0
+ @time_result = []
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ context = arg_hash[:context]
+
+ @results_list[context] = [] if (@results_list[context].nil?)
+
+ @results_list[context] << arg_hash[:result_file]
+ @time_result << arg_hash[:shell_result][:time]
+
+ end
+
+ def post_build
+ @results_list.each_key do |context|
+ results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context])
+
+ artifact_filename = @ceedling[:configurator].project_config_hash[:junit_tests_report_artifact_filename] || 'report.xml'
+ artifact_fullpath = @ceedling[:configurator].project_config_hash[:junit_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s)
+ file_path = File.join(artifact_fullpath, artifact_filename)
+
+ @ceedling[:file_wrapper].open( file_path, 'w' ) do |f|
+ @testsuite_counter = 0
+ @testcase_counter = 0
+ suites = reorganise_results( results )
+
+ write_header( results, f )
+ suites.each{|suite| write_suite( suite, f ) }
+ write_footer( f )
+ end
+ end
+ end
+
+ private
+
+ def write_header( results, stream )
+ results[:counts][:time] = @time_result.reduce(0, :+)
+ stream.puts '<?xml version="1.0" encoding="utf-8" ?>'
+ stream.puts('<testsuites tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % results[:counts])
+ end
+
+ def write_footer( stream )
+ stream.puts '</testsuites>'
+ end
+
+ def reorganise_results( results )
+ # Reorganise the output by test suite instead of by result
+ suites = Hash.new{ |h,k| h[k] = {collection: [], total: 0, success: 0, failed: 0, ignored: 0, stdout: []} }
+ results[:successes].each do |result|
+ source = result[:source]
+ name = source[:file].sub(/\..{1,4}$/, "")
+ suites[name][:collection] += result[:collection].map{|test| test.merge(result: :success)}
+ suites[name][:total] += result[:collection].length
+ suites[name][:success] += result[:collection].length
+ end
+ results[:failures].each do |result|
+ source = result[:source]
+ name = source[:file].sub(/\..{1,4}$/, "")
+ suites[name][:collection] += result[:collection].map{|test| test.merge(result: :failed)}
+ suites[name][:total] += result[:collection].length
+ suites[name][:failed] += result[:collection].length
+ end
+ results[:ignores].each do |result|
+ source = result[:source]
+ name = source[:file].sub(/\..{1,4}$/, "")
+ suites[name][:collection] += result[:collection].map{|test| test.merge(result: :ignored)}
+ suites[name][:total] += result[:collection].length
+ suites[name][:ignored] += result[:collection].length
+ end
+ results[:stdout].each do |result|
+ source = result[:source]
+ name = source[:file].sub(/\..{1,4}$/, "")
+ suites[name][:stdout] += result[:collection]
+ end
+ suites.map{|name, data| data.merge(name: name) }
+ end
+
+ def write_suite( suite, stream )
+ suite[:time] = @time_result.shift
+ stream.puts(' <testsuite name="%<name>s" tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % suite)
+
+ suite[:collection].each do |test|
+ write_test( test, stream )
+ end
+
+ unless suite[:stdout].empty?
+ stream.puts(' <system-out>')
+ suite[:stdout].each do |line|
+ line.gsub!(/&/, '&amp;')
+ line.gsub!(/</, '&lt;')
+ line.gsub!(/>/, '&gt;')
+ line.gsub!(/"/, '&quot;')
+ line.gsub!(/'/, '&apos;')
+ stream.puts(line)
+ end
+ stream.puts(' </system-out>')
+ end
+
+ stream.puts(' </testsuite>')
+ end
+
+ def write_test( test, stream )
+ test[:test].gsub!('"', '&quot;')
+ case test[:result]
+ when :success
+ stream.puts(' <testcase name="%<test>s" />' % test)
+ when :failed
+ stream.puts(' <testcase name="%<test>s">' % test)
+ if test[:message].empty?
+ stream.puts(' <failure />')
+ else
+ stream.puts(' <failure message="%s" />' % test[:message])
+ end
+ stream.puts(' </testcase>')
+ when :ignored
+ stream.puts(' <testcase name="%<test>s">' % test)
+ stream.puts(' <skipped />')
+ stream.puts(' </testcase>')
+ end
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/module_generator/config/module_generator.yml b/tinyusb/test/vendor/ceedling/plugins/module_generator/config/module_generator.yml
new file mode 100755
index 00000000..cdb2da2e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/module_generator/config/module_generator.yml
@@ -0,0 +1,4 @@
+:module_generator:
+ :project_root: ./
+ :source_root: src/
+ :test_root: test/ \ No newline at end of file
diff --git a/tinyusb/test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb b/tinyusb/test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb
new file mode 100755
index 00000000..b2fac006
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/module_generator/lib/module_generator.rb
@@ -0,0 +1,70 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+require 'erb'
+require 'fileutils'
+
+class ModuleGenerator < Plugin
+
+ attr_reader :config
+
+ def create(module_name, optz={})
+
+ require "generate_module.rb" #From Unity Scripts
+
+ if ((!optz.nil?) && (optz[:destroy]))
+ UnityModuleGenerator.new( divine_options(optz) ).destroy(module_name)
+ else
+ UnityModuleGenerator.new( divine_options(optz) ).generate(module_name)
+ end
+ end
+
+ private
+
+ def divine_options(optz={})
+ unity_generator_options =
+ {
+ :path_src => ((defined? MODULE_GENERATOR_SOURCE_ROOT ) ? MODULE_GENERATOR_SOURCE_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '') : "src" ),
+ :path_inc => ((defined? MODULE_GENERATOR_INC_ROOT ) ?
+ MODULE_GENERATOR_INC_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '')
+ : (defined? MODULE_GENERATOR_SOURCE_ROOT ) ?
+ MODULE_GENERATOR_SOURCE_ROOT.gsub('\\', '/').sub(/^\//, '').sub(/\/$/, '')
+ : "src" ),
+ :path_tst => ((defined? MODULE_GENERATOR_TEST_ROOT ) ? MODULE_GENERATOR_TEST_ROOT.gsub( '\\', '/').sub(/^\//, '').sub(/\/$/, '') : "test" ),
+ :pattern => optz[:pattern],
+ :test_prefix => ((defined? PROJECT_TEST_FILE_PREFIX ) ? PROJECT_TEST_FILE_PREFIX : "Test" ),
+ :mock_prefix => ((defined? CMOCK_MOCK_PREFIX ) ? CMOCK_MOCK_PREFIX : "Mock" ),
+ :includes => ((defined? MODULE_GENERATOR_INCLUDES ) ? MODULE_GENERATOR_INCLUDES : {} ),
+ :boilerplates => ((defined? MODULE_GENERATOR_BOILERPLATES) ? MODULE_GENERATOR_BOILERPLATES : {} ),
+ :naming => ((defined? MODULE_GENERATOR_NAMING ) ? MODULE_GENERATOR_NAMING : nil ),
+ :update_svn => ((defined? MODULE_GENERATOR_UPDATE_SVN ) ? MODULE_GENERATOR_UPDATE_SVN : false ),
+ }
+
+ # Read Boilerplate template file.
+ if (defined? MODULE_GENERATOR_BOILERPLATE_FILES)
+
+ bf = MODULE_GENERATOR_BOILERPLATE_FILES
+
+ if !bf[:src].nil? && File.exists?(bf[:src])
+ unity_generator_options[:boilerplates][:src] = File.read(bf[:src])
+ end
+
+ if !bf[:inc].nil? && File.exists?(bf[:inc])
+ unity_generator_options[:boilerplates][:inc] = File.read(bf[:inc])
+ end
+
+ if !bf[:tst].nil? && File.exists?(bf[:tst])
+ unity_generator_options[:boilerplates][:tst] = File.read(bf[:tst])
+ end
+ end
+
+ # If using "create[<module_root>:<module_name>]" option from command line.
+ unless optz[:module_root_path].to_s.empty?
+ unity_generator_options[:path_src] = File.join(optz[:module_root_path], unity_generator_options[:path_src])
+ unity_generator_options[:path_inc] = File.join(optz[:module_root_path], unity_generator_options[:path_inc])
+ unity_generator_options[:path_tst] = File.join(optz[:module_root_path], unity_generator_options[:path_tst])
+ end
+
+ return unity_generator_options
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/module_generator/module_generator.rake b/tinyusb/test/vendor/ceedling/plugins/module_generator/module_generator.rake
new file mode 100755
index 00000000..e88e346a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/module_generator/module_generator.rake
@@ -0,0 +1,47 @@
+
+namespace :module do
+ module_root_separator = ":"
+
+ desc "Generate module (source, header and test files)"
+ task :create, :module_path do |t, args|
+ files = [args[:module_path]] + (args.extras || [])
+ optz = { :module_root_path => "" }
+ ["dh", "dih", "mch", "mvp", "src", "test"].each do |pat|
+ p = files.delete(pat)
+ optz[:pattern] = p unless p.nil?
+ end
+ files.each do |v|
+ module_root_path, module_name = v.split(module_root_separator, 2)
+ if module_name
+ optz[:module_root_path] = module_root_path
+ v = module_name
+ end
+ if (v =~ /^test_?/i)
+ # If the name of the file starts with test, automatically treat it as one
+ @ceedling[:module_generator].create(v.sub(/^test_?/i,''), optz.merge({:pattern => 'test'}))
+ else
+ # Otherwise, go through the normal procedure
+ @ceedling[:module_generator].create(v, optz)
+ end
+ end
+ end
+
+ desc "Destroy module (source, header and test files)"
+ task :destroy, :module_path do |t, args|
+ files = [args[:module_path]] + (args.extras || [])
+ optz = { :destroy => true, :module_root_path => "" }
+ ["dh", "dih", "mch", "mvp", "src", "test"].each do |pat|
+ p = files.delete(pat)
+ optz[:pattern] = p unless p.nil?
+ end
+ files.each do |v|
+ module_root_path, module_name = v.split(module_root_separator, 2)
+ if module_name
+ optz[:module_root_path] = module_root_path
+ v = module_name
+ end
+ @ceedling[:module_generator].create(v, optz)
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb b/tinyusb/test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb
new file mode 100755
index 00000000..014e6771
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/raw_output_report/lib/raw_output_report.rb
@@ -0,0 +1,41 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+
+class RawOutputReport < Plugin
+ def setup
+ @log_paths = {}
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ output = strip_output(arg_hash[:shell_result][:output])
+ write_raw_output_log(arg_hash, output)
+ end
+
+ private
+
+ def strip_output(raw_output)
+ output = ""
+ raw_output.each_line do |line|
+ next if line =~ /^\n$/
+ next if line =~ /^.*:\d+:.*:(IGNORE|PASS|FAIL)/
+ return output if line =~/^-----------------------\n$/
+ output << line
+ end
+ end
+ def write_raw_output_log(arg_hash, output)
+ logging = generate_log_path(arg_hash)
+ @ceedling[:file_wrapper].write(logging[:path], output , logging[:flags]) unless logging.nil?
+ end
+
+ def generate_log_path(arg_hash)
+ f_name = File.basename(arg_hash[:result_file], '.pass')
+ base_path = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, arg_hash[:context].to_s)
+ file_path = File.join(base_path, f_name + '.log')
+
+ if @ceedling[:file_wrapper].exist?(base_path)
+ return { path: file_path, flags: 'w' }
+ end
+
+ nil
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb
new file mode 100755
index 00000000..fb8e3b13
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb
@@ -0,0 +1,84 @@
+% ignored = hash[:results][:counts][:ignored]
+% failed = hash[:results][:counts][:failed]
+% stdout_count = hash[:results][:counts][:stdout]
+% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '')
+% banner_width = 25 + header_prepend.length # widest message
+% results = {}
+% hash[:results][:successes].each do |testresult|
+% results[ testresult[:source][:file] ] = testresult[:collection]
+% results[ testresult[:source][:file] ].length.times do |i|
+% results[ testresult[:source][:file] ][i][:pass] = true
+% end
+% end
+% hash[:results][:ignores].each do |testresult|
+% if (results[ testresult[:source][:file] ].nil?)
+% results[ testresult[:source][:file] ] = testresult[:collection]
+% else
+% results[ testresult[:source][:file] ] += testresult[:collection]
+% end
+% results[ testresult[:source][:file] ].length.times do |i|
+% results[ testresult[:source][:file] ][i][:pass] = true
+% end
+% end
+% hash[:results][:failures].each do |testresult|
+% if (results[ testresult[:source][:file] ].nil?)
+% results[ testresult[:source][:file] ] = testresult[:collection]
+% else
+% results[ testresult[:source][:file] ] += testresult[:collection]
+% end
+% end
+
+
+[==========] Running <%=hash[:results][:counts][:total].to_s%> tests from <%=results.length.to_s%> test cases.
+[----------] Global test environment set-up.
+% results.each_pair do |modulename, moduledetails|
+[----------] <%=moduledetails.length.to_s%> tests from <%=modulename%>
+% moduledetails.each do |item|
+[ RUN ] <%=modulename%>.<%=item[:test]%>
+% if (not item[:pass])
+% if (not item[:message].empty?)
+<%=modulename%>(<%=item[:line]%>): error: <%=item[:message]%>
+
+% m = item[:message].match(/Expected\s+(.*)\s+Was\s+([^\.]*)\./)
+% if m.nil?
+ Actual: FALSE
+ Expected: TRUE
+% else
+ Actual: <%=m[2]%>
+ Expected: <%=m[1]%>
+% end
+% else
+<%=modulename%>(<%=item[:line]%>): fail: <%=item[:message]%>
+ Actual: FALSE
+ Expected: TRUE
+% end
+[ FAILED ] <%=modulename%>.<%=item[:test]%> (0 ms)
+% else
+[ OK ] <%=modulename%>.<%=item[:test]%> (0 ms)
+% end
+% end
+[----------] <%=moduledetails.length.to_s%> tests from <%=modulename%> (0 ms total)
+% end
+
+% if (hash[:results][:counts][:total] > 0)
+[----------] Global test environment tear-down.
+[==========] <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases ran.
+[ PASSED ] <%=hash[:results][:counts][:passed].to_s%> tests.
+% if (failed == 0)
+[ FAILED ] 0 tests.
+
+ 0 FAILED TESTS
+% else
+[ FAILED ] <%=failed.to_s%> tests, listed below:
+% hash[:results][:failures].each do |failure|
+% failure[:collection].each do |item|
+[ FAILED ] <%=failure[:source][:file]%>.<%=item[:test]%>
+% end
+% end
+% end
+
+ <%=failed.to_s%> FAILED TESTS
+% else
+
+No tests executed.
+% end
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy
new file mode 100755
index 00000000..a90f495e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/assets/template.erb copy
@@ -0,0 +1,59 @@
+% ignored = hash[:results][:counts][:ignored]
+% failed = hash[:results][:counts][:failed]
+% stdout_count = hash[:results][:counts][:stdout]
+% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '')
+% banner_width = 25 + header_prepend.length # widest message
+
+
+% if (stdout_count > 0)
+[==========] Running <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases.
+[----------] Global test environment set-up.
+% end
+% if (failed > 0)
+% hash[:results][:failures].each do |failure|
+[----------] <%=failure[:collection].length.to_s%> tests from <%=failure[:source][:file]%>
+% failure[:collection].each do |item|
+[ RUN ] <%=failure[:source][:file]%>.<%=item[:test]%>
+% if (not item[:message].empty?)
+<%=failure[:source][:file]%>(<%=item[:line]%>): error: <%=item[:message]%>
+
+% m = item[:message].match(/Expected\s+(.*)\s+Was\s+([^\.]*)\./)
+% if m.nil?
+ Actual: FALSE
+ Expected: TRUE
+% else
+ Actual: <%=m[2]%>
+ Expected: <%=m[1]%>
+% end
+% else
+<%=failure[:source][:file]%>(<%=item[:line]%>): fail: <%=item[:message]%>
+ Actual: FALSE
+ Expected: TRUE
+% end
+[ FAILED ] <%=failure[:source][:file]%>.<%=item[:test]%> (0 ms)
+% end
+[----------] <%=failure[:collection].length.to_s%> tests from <%=failure[:source][:file]%> (0 ms total)
+% end
+% end
+% if (hash[:results][:counts][:total] > 0)
+[----------] Global test environment tear-down.
+[==========] <%=hash[:results][:counts][:total].to_s%> tests from <%=hash[:results][:stdout].length.to_s%> test cases ran.
+[ PASSED ] <%=hash[:results][:counts][:passed].to_s%> tests.
+% if (failed == 0)
+[ FAILED ] 0 tests.
+
+ 0 FAILED TESTS
+% else
+[ FAILED ] <%=failed.to_s%> tests, listed below:
+% hash[:results][:failures].each do |failure|
+% failure[:collection].each do |item|
+[ FAILED ] <%=failure[:source][:file]%>.<%=item[:test]%>
+% end
+% end
+
+ <%=failed.to_s%> FAILED TESTS
+% end
+% else
+
+No tests executed.
+% end
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/config/stdout_gtestlike_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/config/stdout_gtestlike_tests_report.yml
new file mode 100755
index 00000000..c25acf51
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/config/stdout_gtestlike_tests_report.yml
@@ -0,0 +1,4 @@
+---
+:plugins:
+ # tell Ceedling we got results display taken care of
+ :display_raw_test_results: FALSE
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb
new file mode 100755
index 00000000..a51438a3
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_gtestlike_tests_report/lib/stdout_gtestlike_tests_report.rb
@@ -0,0 +1,43 @@
+require 'ceedling/plugin'
+require 'ceedling/defaults'
+
+class StdoutGtestlikeTestsReport < Plugin
+
+ def setup
+ @result_list = []
+ @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ template = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
+ @ceedling[:plugin_reportinator].register_test_results_template( template )
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ return if not (arg_hash[:context] == TEST_SYM)
+
+ @result_list << arg_hash[:result_file]
+ end
+
+ def post_build
+ return if not (@ceedling[:task_invoker].test_invoked?)
+
+ results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
+ hash = {
+ :header => '',
+ :results => results
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash)
+ end
+
+ def summary
+ result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS )
+
+ # get test results for only those tests in our configuration and of those only tests with results on disk
+ hash = {
+ :header => '',
+ :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml
new file mode 100755
index 00000000..c25acf51
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/config/stdout_ide_tests_report.yml
@@ -0,0 +1,4 @@
+---
+:plugins:
+ # tell Ceedling we got results display taken care of
+ :display_raw_test_results: FALSE
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb
new file mode 100755
index 00000000..48b3e819
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_ide_tests_report/lib/stdout_ide_tests_report.rb
@@ -0,0 +1,44 @@
+require 'ceedling/plugin'
+require 'ceedling/defaults'
+
+class StdoutIdeTestsReport < Plugin
+
+ def setup
+ @result_list = []
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ return if not (arg_hash[:context] == TEST_SYM)
+
+ @result_list << arg_hash[:result_file]
+ end
+
+ def post_build
+ return if (not @ceedling[:task_invoker].test_invoked?)
+
+ results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
+ hash = {
+ :header => '',
+ :results => results
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash) do
+ message = ''
+ message = 'Unit test failures.' if (hash[:results][:counts][:failed] > 0)
+ message
+ end
+ end
+
+ def summary
+ result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS )
+
+ # get test results for only those tests in our configuration and of those only tests with results on disk
+ hash = {
+ :header => '',
+ :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb
new file mode 100755
index 00000000..52b29f7f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/assets/template.erb
@@ -0,0 +1,59 @@
+% ignored = hash[:results][:counts][:ignored]
+% failed = hash[:results][:counts][:failed]
+% stdout_count = hash[:results][:counts][:stdout]
+% header_prepend = ((hash[:header].length > 0) ? "#{hash[:header]}: " : '')
+% banner_width = 25 + header_prepend.length # widest message
+
+% if (stdout_count > 0)
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'TEST OUTPUT')%>
+% hash[:results][:stdout].each do |string|
+[<%=string[:source][:file]%>]
+% string[:collection].each do |item|
+ - "<%=item%>"
+% end
+
+% end
+% end
+% if (ignored > 0)
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'IGNORED TEST SUMMARY')%>
+% hash[:results][:ignores].each do |ignore|
+[<%=ignore[:source][:file]%>]
+% ignore[:collection].each do |item|
+ Test: <%=item[:test]%>
+% if (not item[:message].empty?)
+ At line (<%=item[:line]%>): "<%=item[:message]%>"
+% else
+ At line (<%=item[:line]%>)
+% end
+
+% end
+% end
+% end
+% if (failed > 0)
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'FAILED TEST SUMMARY')%>
+% hash[:results][:failures].each do |failure|
+[<%=failure[:source][:file]%>]
+% failure[:collection].each do |item|
+ Test: <%=item[:test]%>
+% if (not item[:message].empty?)
+ At line (<%=item[:line]%>): "<%=item[:message]%>"
+% else
+ At line (<%=item[:line]%>)
+% end
+
+% end
+% end
+% end
+% total_string = hash[:results][:counts][:total].to_s
+% format_string = "%#{total_string.length}i"
+<%=@ceedling[:plugin_reportinator].generate_banner(header_prepend + 'OVERALL TEST SUMMARY')%>
+% if (hash[:results][:counts][:total] > 0)
+TESTED: <%=hash[:results][:counts][:total].to_s%>
+PASSED: <%=sprintf(format_string, hash[:results][:counts][:passed])%>
+FAILED: <%=sprintf(format_string, failed)%>
+IGNORED: <%=sprintf(format_string, ignored)%>
+% else
+
+No tests executed.
+% end
+
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/config/stdout_pretty_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/config/stdout_pretty_tests_report.yml
new file mode 100755
index 00000000..c25acf51
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/config/stdout_pretty_tests_report.yml
@@ -0,0 +1,4 @@
+---
+:plugins:
+ # tell Ceedling we got results display taken care of
+ :display_raw_test_results: FALSE
diff --git a/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb
new file mode 100755
index 00000000..018388fc
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/stdout_pretty_tests_report/lib/stdout_pretty_tests_report.rb
@@ -0,0 +1,47 @@
+require 'ceedling/plugin'
+require 'ceedling/defaults'
+
+class StdoutPrettyTestsReport < Plugin
+
+ def setup
+ @result_list = []
+ @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ template = @ceedling[:file_wrapper].read(File.join(@plugin_root, 'assets/template.erb'))
+ @ceedling[:plugin_reportinator].register_test_results_template( template )
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ return if not (arg_hash[:context] == TEST_SYM)
+
+ @result_list << arg_hash[:result_file]
+ end
+
+ def post_build
+ return if not (@ceedling[:task_invoker].test_invoked?)
+
+ results = @ceedling[:plugin_reportinator].assemble_test_results(@result_list)
+ hash = {
+ :header => '',
+ :results => results
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash) do
+ message = ''
+ message = 'Unit test failures.' if (results[:counts][:failed] > 0)
+ message
+ end
+ end
+
+ def summary
+ result_list = @ceedling[:file_path_utils].form_pass_results_filelist( PROJECT_TEST_RESULTS_PATH, COLLECTION_ALL_TESTS )
+
+ # get test results for only those tests in our configuration and of those only tests with results on disk
+ hash = {
+ :header => '',
+ :results => @ceedling[:plugin_reportinator].assemble_test_results(result_list, {:boom => false})
+ }
+
+ @ceedling[:plugin_reportinator].run_test_results_report(hash)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/README.md b/tinyusb/test/vendor/ceedling/plugins/subprojects/README.md
new file mode 100755
index 00000000..e51a4e60
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/README.md
@@ -0,0 +1,63 @@
+ceedling-subprojects
+====================
+
+Plugin for supporting subprojects that are built as static libraries. It continues to support
+dependency tracking, without getting confused between your main project files and your
+subproject files. It accepts different compiler flags and linker flags, allowing you to
+optimize for your situation.
+
+First, you're going to want to add the extension to your list of known extensions:
+
+```
+:extension:
+ :subprojects: '.a'
+```
+
+Define a new section called :subprojects. There, you can list as many subprojects
+as you may need under the :paths key. For each, you specify a unique place to build
+and a unique name.
+
+```
+:subprojects:
+ :paths:
+ - :name: libprojectA
+ :source:
+ - ./subprojectA/first/dir
+ - ./subprojectA/second/dir
+ :include:
+ - ./subprojectA/include/dir
+ :build_root: ./subprojectA/build/dir
+ :defines:
+ - DEFINE_JUST_FOR_THIS_FILE
+ - AND_ANOTHER
+ - :name: libprojectB
+ :source:
+ - ./subprojectB/only/dir
+ :include:
+ - ./subprojectB/first/include/dir
+ - ./subprojectB/second/include/dir
+ :build_root: ./subprojectB/build/dir
+ :defines: [] #none for this one
+```
+
+You can specify the compiler and linker, just as you would a release build:
+
+```
+:tools:
+ :subprojects_compiler:
+ :executable: gcc
+ :arguments:
+ - -g
+ - -I"$": COLLECTION_PATHS_SUBPROJECTS
+ - -D$: COLLECTION_DEFINES_SUBPROJECTS
+ - -c "${1}"
+ - -o "${2}"
+ :subprojects_linker:
+ :executable: ar
+ :arguments:
+ - rcs
+ - ${2}
+ - ${1}
+```
+
+That's all there is to it! Happy Hacking!
diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/config/defaults.yml b/tinyusb/test/vendor/ceedling/plugins/subprojects/config/defaults.yml
new file mode 100755
index 00000000..1045a595
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/config/defaults.yml
@@ -0,0 +1,33 @@
+---
+#:extension:
+# :subprojects: '.a'
+
+:subprojects:
+ :paths: []
+# - :name: subprojectA
+# :source:
+# - ./first/subproject/dir
+# - ./second/subproject/dir
+# :include:
+# - ./first/include/dir
+# :build_root: ./subproject/build/dir
+# :defines:
+# - FIRST_DEFINE
+
+:tools:
+ :subprojects_compiler:
+ :executable: gcc
+ :arguments:
+ - -g
+ - -I"$": COLLECTION_PATHS_SUBPROJECTS
+ - -D$: COLLECTION_DEFINES_SUBPROJECTS
+ - -c "${1}"
+ - -o "${2}"
+ :subprojects_linker:
+ :executable: ar
+ :arguments:
+ - rcs
+ - ${2}
+ - ${1}
+
+...
diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb b/tinyusb/test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb
new file mode 100755
index 00000000..1f5d4c2f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/lib/subprojects.rb
@@ -0,0 +1,92 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+
+SUBPROJECTS_ROOT_NAME = 'subprojects'
+SUBPROJECTS_TASK_ROOT = SUBPROJECTS_ROOT_NAME + ':'
+SUBPROJECTS_SYM = SUBPROJECTS_ROOT_NAME.to_sym
+
+class Subprojects < Plugin
+
+ def setup
+ @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+ # Add to the test paths
+ SUBPROJECTS_PATHS.each do |subproj|
+ subproj[:source].each do |path|
+ COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << path
+ end
+ subproj[:include].each do |path|
+ COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << path
+ end
+ end
+
+ #gather information about the subprojects
+ @subprojects = {}
+ @subproject_lookup_by_path = {}
+ SUBPROJECTS_PATHS.each do |subproj|
+ @subprojects[ subproj[:name] ] = subproj.clone
+ @subprojects[ subproj[:name] ][:c] = []
+ @subprojects[ subproj[:name] ][:asm] = []
+ subproj[:source].each do |path|
+ search_path = "#{path[-1].match(/\\|\//) ? path : "#{path}/"}*#{EXTENSION_SOURCE}"
+ @subprojects[ subproj[:name] ][:c] += Dir[search_path]
+ if (EXTENSION_ASSEMBLY && !EXTENSION_ASSEMBLY.empty?)
+ search_path = "#{path[-1].match(/\\|\//) ? path : "#{path}/"}*#{EXTENSION_ASSEMBLY}"
+ @subprojects[ subproj[:name] ][:asm] += Dir[search_path]
+ end
+ end
+ @subproject_lookup_by_path[ subproj[:build_root] ] = subproj[:name]
+ end
+ end
+
+ def find_my_project( c_file, file_type = :c )
+ @subprojects.each_pair do |subprojname, subproj|
+ return subprojname if (subproj[file_type].include?(c_file))
+ end
+ end
+
+ def find_my_paths( c_file, file_type = :c )
+ @subprojects.each_pair do |subprojname, subproj|
+ return (subproj[:source] + (subproj[:include] || [])) if (subproj[file_type].include?(c_file))
+ end
+ return []
+ end
+
+ def find_my_defines( c_file, file_type = :c )
+ @subprojects.each_pair do |subprojname, subproj|
+ return (subproj[:defines] || []) if (subproj[file_type].include?(c_file))
+ end
+ return []
+ end
+
+ def list_all_object_files_for_subproject( lib_name )
+ subproj = File.basename(lib_name, EXTENSION_SUBPROJECTS)
+ objpath = "#{@subprojects[subproj][:build_root]}/out/c"
+ bbb = @subprojects[subproj][:c].map{|f| "#{objpath}/#{File.basename(f,EXTENSION_SOURCE)}#{EXTENSION_OBJECT}" }
+ bbb
+ end
+
+ def find_library_source_file_for_object( obj_name )
+ cname = "#{File.basename(obj_name, EXTENSION_OBJECT)}#{EXTENSION_SOURCE}"
+ dname = File.dirname(obj_name)[0..-7]
+ pname = @subproject_lookup_by_path[dname]
+ return @ceedling[:file_finder].find_file_from_list(cname, @subprojects[pname][:c], :error)
+ end
+
+ def find_library_assembly_file_for_object( obj_name )
+ cname = "#{File.basename(obj_name, EXTENSION_OBJECT)}#{EXTENSION_ASEMBLY}"
+ dname = File.dirname(obj_name)[0..-7]
+ pname = @subproject_lookup_by_path[dname]
+ return @ceedling[:file_finder].find_file_from_list(cname, @subprojects[pname][:asm], :error)
+ end
+
+ def replace_constant(constant, new_value)
+ Object.send(:remove_const, constant.to_sym) if (Object.const_defined? constant)
+ Object.const_set(constant, new_value)
+ end
+
+end
+
+# end blocks always executed following rake run
+END {
+}
diff --git a/tinyusb/test/vendor/ceedling/plugins/subprojects/subprojects.rake b/tinyusb/test/vendor/ceedling/plugins/subprojects/subprojects.rake
new file mode 100755
index 00000000..0025c3ec
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/subprojects/subprojects.rake
@@ -0,0 +1,78 @@
+
+
+SUBPROJECTS_PATHS.each do |subproj|
+
+ subproj_source = subproj[:source]
+ subproj_include = subproj[:include]
+ subproj_name = subproj[:name]
+ subproj_build_root = subproj[:build_root]
+ subproj_build_out = "#{subproj[:build_root]}/out"
+ subproj_build_c = "#{subproj[:build_root]}/out/c"
+ subproj_build_asm = "#{subproj[:build_root]}/out/asm"
+ subproj_directories = [ subproj_build_root, subproj_build_out, subproj_build_c, subproj_build_asm ]
+
+ subproj_directories.each do |subdir|
+ directory(subdir)
+ end
+
+ CLEAN.include(File.join(subproj_build_root, '*'))
+ CLEAN.include(File.join(subproj_build_out, '*'))
+
+ CLOBBER.include(File.join(subproj_build_root, '**/*'))
+
+ # Add a rule for building the actual static library from our object files
+ rule(/#{subproj_build_root}#{'.+\\'+EXTENSION_SUBPROJECTS}$/ => [
+ proc do |task_name|
+ @ceedling[SUBPROJECTS_SYM].list_all_object_files_for_subproject(task_name)
+ end
+ ]) do |bin_file|
+ @ceedling[:generator].generate_executable_file(
+ TOOLS_SUBPROJECTS_LINKER,
+ SUBPROJECTS_SYM,
+ bin_file.prerequisites,
+ bin_file.name,
+ @ceedling[:file_path_utils].form_test_build_map_filepath(bin_file.name))
+ end
+
+ # Add a rule for building object files from assembly files to link into a library
+ if (RELEASE_BUILD_USE_ASSEMBLY)
+ rule(/#{subproj_build_asm}#{'.+\\'+EXTENSION_OBJECT}$/ => [
+ proc do |task_name|
+ @ceedling[SUBPROJECTS_SYM].find_library_assembly_file_for_object(task_name)
+ end
+ ]) do |object|
+ @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_PATHS_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_paths(object.source, :asm))
+ @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_DEFINES_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_defines(object.source, :asm))
+ @ceedling[:generator].generate_object_file(
+ TOOLS_SUBPROJECTS_ASSEMBLER,
+ OPERATION_ASSEMBLE_SYM,
+ SUBPROJECTS_SYM,
+ object.source,
+ object.name )
+ end
+ end
+
+ # Add a rule for building object files from C files to link into a library
+ rule(/#{subproj_build_c}#{'.+\\'+EXTENSION_OBJECT}$/ => [
+ proc do |task_name|
+ @ceedling[SUBPROJECTS_SYM].find_library_source_file_for_object(task_name)
+ end
+ ]) do |object|
+ @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_PATHS_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_paths(object.source, :c))
+ @ceedling[SUBPROJECTS_SYM].replace_constant(:COLLECTION_DEFINES_SUBPROJECTS, @ceedling[SUBPROJECTS_SYM].find_my_defines(object.source, :c))
+ @ceedling[:generator].generate_object_file(
+ TOOLS_SUBPROJECTS_COMPILER,
+ OPERATION_COMPILE_SYM,
+ SUBPROJECTS_SYM,
+ object.source,
+ object.name,
+ @ceedling[:file_path_utils].form_release_build_c_list_filepath( object.name ) )
+ end
+
+ # Add the subdirectories involved to our list of those that should be autogenerated
+ task :directories => subproj_directories.clone
+
+ # Finally, add the static library to our RELEASE build dependency list
+ task RELEASE_SYM => ["#{subproj_build_root}/#{subproj_name}#{EXTENSION_SUBPROJECTS}"]
+end
+
diff --git a/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml
new file mode 100755
index 00000000..c25acf51
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/config/teamcity_tests_report.yml
@@ -0,0 +1,4 @@
+---
+:plugins:
+ # tell Ceedling we got results display taken care of
+ :display_raw_test_results: FALSE
diff --git a/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb
new file mode 100755
index 00000000..33d8548f
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/teamcity_tests_report/lib/teamcity_tests_report.rb
@@ -0,0 +1,57 @@
+require 'ceedling/plugin'
+require 'ceedling/defaults'
+
+class TeamcityTestsReport < Plugin
+
+ def setup
+ @suite_started = nil
+ @output_enabled = !defined?(TEAMCITY_BUILD) || TEAMCITY_BUILD
+ end
+
+ def escape(string)
+ string.gsub(/['|\[\]]/, '|\0').gsub('\r', '|r').gsub('\n', '|n')
+ end
+
+ def pre_test(test)
+ teamcity_message "testSuiteStarted name='#{File.basename(test, '.c')}'"
+ @suite_started = Time.now
+ end
+
+ def post_test(test)
+ teamcity_message "testSuiteFinished name='#{File.basename(test, '.c')}'"
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ duration = (Time.now - @suite_started) * 1000
+ results = @ceedling[:plugin_reportinator].assemble_test_results([arg_hash[:result_file]])
+ avg_duration = (duration / [1, results[:counts][:passed] + results[:counts][:failed]].max).round
+
+ results[:successes].each do |success|
+ success[:collection].each do |test|
+ teamcity_message "testStarted name='#{test[:test]}'"
+ teamcity_message "testFinished name='#{test[:test]}' duration='#{avg_duration}'"
+ end
+ end
+
+ results[:failures].each do |failure|
+ failure[:collection].each do |test|
+ teamcity_message "testStarted name='#{test[:test]}'"
+ teamcity_message "testFailed name='#{test[:test]}' message='#{escape(test[:message])}' details='File: #{failure[:source][:path]}/#{failure[:source][:file]} Line: #{test[:line]}'"
+ teamcity_message "testFinished name='#{test[:test]}' duration='#{avg_duration}'"
+ end
+ end
+
+ results[:ignores].each do |failure|
+ failure[:collection].each do |test|
+ teamcity_message "testIgnored name='#{test[:test]}' message='#{escape(test[:message])}'"
+ end
+ end
+
+ # We ignore stdout
+ end
+
+ def teamcity_message(content)
+ puts "##teamcity[#{content}]" unless !@output_enabled
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb b/tinyusb/test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb
new file mode 100755
index 00000000..d4f43fb5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/warnings_report/lib/warnings_report.rb
@@ -0,0 +1,69 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+
+class WarningsReport < Plugin
+ def setup
+ @stderr_redirect = nil
+ @log_paths = {}
+ end
+
+ def pre_compile_execute(arg_hash)
+ # at beginning of compile, override tool's stderr_redirect so we can parse $stderr + $stdout
+ set_stderr_redirect(arg_hash)
+ end
+
+ def post_compile_execute(arg_hash)
+ # after compilation, grab output for parsing/logging, restore stderr_redirect, log warning if it exists
+ output = arg_hash[:shell_result][:output]
+ restore_stderr_redirect(arg_hash)
+ write_warning_log(arg_hash[:context], output)
+ end
+
+ def pre_link_execute(arg_hash)
+ # at beginning of link, override tool's stderr_redirect so we can parse $stderr + $stdout
+ set_stderr_redirect(arg_hash)
+ end
+
+ def post_link_execute(arg_hash)
+ # after linking, grab output for parsing/logging, restore stderr_redirect, log warning if it exists
+ output = arg_hash[:shell_result][:output]
+ restore_stderr_redirect(arg_hash)
+ write_warning_log(arg_hash[:context], output)
+ end
+
+ private
+
+ def set_stderr_redirect(hash)
+ @stderr_redirect = hash[:tool][:stderr_redirect]
+ hash[:tool][:stderr_redirect] = StdErrRedirect::AUTO
+ end
+
+ def restore_stderr_redirect(hash)
+ hash[:tool][:stderr_redirect] = @stderr_redirect
+ end
+
+ def write_warning_log(context, output)
+ # if $stderr/$stdout contain "warning", log it
+ if output =~ /warning/i
+ # generate a log path & file io write flags
+ logging = generate_log_path(context)
+ @ceedling[:file_wrapper].write(logging[:path], output + "\n", logging[:flags]) unless logging.nil?
+ end
+ end
+
+ def generate_log_path(context)
+ # if path has already been generated, return it & 'append' file io flags (append to log)
+ return { path: @log_paths[context], flags: 'a' } unless @log_paths[context].nil?
+
+ # first time through, generate path & 'write' file io flags (create new log)
+ base_path = File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s)
+ file_path = File.join(base_path, 'warnings.log')
+
+ if @ceedling[:file_wrapper].exist?(base_path)
+ @log_paths[context] = file_path
+ return { path: file_path, flags: 'w' }
+ end
+
+ nil
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/README.md b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/README.md
new file mode 100755
index 00000000..ce81eadf
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/README.md
@@ -0,0 +1,36 @@
+xml_tests_report
+====================
+
+## Overview
+
+The xml_tests_report plugin creates an XML file of test results in xUnit
+format, which is handy for Continuous Integration build servers or as input
+into other reporting tools. The XML file is output to the appropriate
+`<build_root>/artifacts/` directory (e.g. `artifacts/test/` for test tasks,
+`artifacts/gcov/` for gcov, or `artifacts/bullseye/` for bullseye runs).
+
+## Setup
+
+Enable the plugin in your project.yml by adding `xml_tests_report` to the list
+of enabled plugins.
+
+``` YAML
+:plugins:
+ :enabled:
+ - xml_tests_report
+```
+
+## Configuration
+
+Optionally configure the output / artifact filename in your project.yml with
+the `artifact_filename` configuration option. The default filename is
+`report.xml`.
+
+You can also configure the path that this artifact is stored. This can be done
+by setting `path`. The default is that it will be placed in a subfolder under
+the `build` directory.
+
+``` YAML
+:xml_tests_report:
+ :artifact_filename: report_xunit.xml
+```
diff --git a/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb
new file mode 100755
index 00000000..ed4e9960
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/plugins/xml_tests_report/lib/xml_tests_report.rb
@@ -0,0 +1,110 @@
+require 'ceedling/plugin'
+require 'ceedling/constants'
+
+class XmlTestsReport < Plugin
+ def setup
+ @results_list = {}
+ @test_counter = 0
+ end
+
+ def post_test_fixture_execute(arg_hash)
+ context = arg_hash[:context]
+
+ @results_list[context] = [] if @results_list[context].nil?
+
+ @results_list[context] << arg_hash[:result_file]
+ end
+
+ def post_build
+ @results_list.each_key do |context|
+ results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context])
+
+ artifact_filename = @ceedling[:configurator].project_config_hash[:xml_tests_report_artifact_filename] || 'report.xml'
+ artifact_fullpath = @ceedling[:configurator].project_config_hash[:xml_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s)
+ file_path = File.join(artifact_fullpath, artifact_filename)
+
+ @ceedling[:file_wrapper].open(file_path, 'w') do |f|
+ @test_counter = 1
+ write_results(results, f)
+ end
+ end
+ end
+
+ private
+
+ def write_results(results, stream)
+ write_header(stream)
+ write_failures(results[:failures], stream)
+ write_tests(results[:successes], stream, 'SuccessfulTests')
+ write_tests(results[:ignores], stream, 'IgnoredTests')
+ write_statistics(results[:counts], stream)
+ write_footer(stream)
+ end
+
+ def write_header(stream)
+ stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
+ stream.puts '<TestRun>'
+ end
+
+ def write_failures(results, stream)
+ if results.size.zero?
+ stream.puts "\t<FailedTests/>"
+ return
+ end
+
+ stream.puts "\t<FailedTests>"
+
+ results.each do |result|
+ result[:collection].each do |item|
+ filename = File.join(result[:source][:path], result[:source][:file])
+
+ stream.puts "\t\t<Test id=\"#{@test_counter}\">"
+ stream.puts "\t\t\t<Name>#{filename}::#{item[:test]}</Name>"
+ stream.puts "\t\t\t<FailureType>Assertion</FailureType>"
+ stream.puts "\t\t\t<Location>"
+ stream.puts "\t\t\t\t<File>#{filename}</File>"
+ stream.puts "\t\t\t\t<Line>#{item[:line]}</Line>"
+ stream.puts "\t\t\t</Location>"
+ stream.puts "\t\t\t<Message>#{item[:message]}</Message>"
+ stream.puts "\t\t</Test>"
+ @test_counter += 1
+ end
+ end
+
+ stream.puts "\t</FailedTests>"
+ end
+
+ def write_tests(results, stream, tag)
+ if results.size.zero?
+ stream.puts "\t<#{tag}/>"
+ return
+ end
+
+ stream.puts "\t<#{tag}>"
+
+ results.each do |result|
+ result[:collection].each do |item|
+ stream.puts "\t\t<Test id=\"#{@test_counter}\">"
+ stream.puts "\t\t\t<Name>#{File.join(result[:source][:path], result[:source][:file])}::#{item[:test]}</Name>"
+ stream.puts "\t\t</Test>"
+ @test_counter += 1
+ end
+ end
+
+ stream.puts "\t</#{tag}>"
+ end
+
+ def write_statistics(counts, stream)
+ stream.puts "\t<Statistics>"
+ stream.puts "\t\t<Tests>#{counts[:total]}</Tests>"
+ stream.puts "\t\t<Ignores>#{counts[:ignored]}</Ignores>"
+ stream.puts "\t\t<FailuresTotal>#{counts[:failed]}</FailuresTotal>"
+ stream.puts "\t\t<Errors>0</Errors>"
+ stream.puts "\t\t<Failures>#{counts[:failed]}</Failures>"
+ stream.puts "\t</Statistics>"
+ end
+
+ def write_footer(stream)
+ stream.puts '</TestRun>'
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.c b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.c
new file mode 100755
index 00000000..fdff8f47
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.c
@@ -0,0 +1,46 @@
+#include "CException.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+volatile CEXCEPTION_FRAME_T CExceptionFrames[CEXCEPTION_NUM_ID] = {{ 0 }};
+#pragma GCC diagnostic pop
+
+//------------------------------------------------------------------------------------------
+// Throw
+//------------------------------------------------------------------------------------------
+void Throw(CEXCEPTION_T ExceptionID)
+{
+ unsigned int MY_ID = CEXCEPTION_GET_ID;
+ CExceptionFrames[MY_ID].Exception = ExceptionID;
+ if (CExceptionFrames[MY_ID].pFrame)
+ {
+ longjmp(*CExceptionFrames[MY_ID].pFrame, 1);
+ }
+ CEXCEPTION_NO_CATCH_HANDLER(ExceptionID);
+}
+
+//------------------------------------------------------------------------------------------
+// Explanation of what it's all for:
+//------------------------------------------------------------------------------------------
+/*
+#define Try
+ { <- give us some local scope. most compilers are happy with this
+ jmp_buf *PrevFrame, NewFrame; <- prev frame points to the last try block's frame. new frame gets created on stack for this Try block
+ unsigned int MY_ID = CEXCEPTION_GET_ID; <- look up this task's id for use in frame array. always 0 if single-tasking
+ PrevFrame = CExceptionFrames[CEXCEPTION_GET_ID].pFrame; <- set pointer to point at old frame (which array is currently pointing at)
+ CExceptionFrames[MY_ID].pFrame = &NewFrame; <- set array to point at my new frame instead, now
+ CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; <- initialize my exception id to be NONE
+ if (setjmp(NewFrame) == 0) { <- do setjmp. it returns 1 if longjump called, otherwise 0
+ if (&PrevFrame) <- this is here to force proper scoping. it requires braces or a single line to be but after Try, otherwise won't compile. This is always true at this point.
+
+#define Catch(e)
+ else { } <- this also forces proper scoping. Without this they could stick their own 'else' in and it would get ugly
+ CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; <- no errors happened, so just set the exception id to NONE (in case it was corrupted)
+ }
+ else <- an exception occurred
+ { e = CExceptionFrames[MY_ID].Exception; e=e;} <- assign the caught exception id to the variable passed in.
+ CExceptionFrames[MY_ID].pFrame = PrevFrame; <- make the pointer in the array point at the previous frame again, as if NewFrame never existed.
+ } <- finish off that local scope we created to have our own variables
+ if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE) <- start the actual 'catch' processing if we have an exception id saved away
+ */
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.h b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.h
new file mode 100755
index 00000000..78f2f940
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/lib/CException.h
@@ -0,0 +1,115 @@
+#ifndef _CEXCEPTION_H
+#define _CEXCEPTION_H
+
+#include <setjmp.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#define CEXCEPTION_VERSION_MAJOR 1
+#define CEXCEPTION_VERSION_MINOR 3
+#define CEXCEPTION_VERSION_BUILD 2
+#define CEXCEPTION_VERSION ((CEXCEPTION_VERSION_MAJOR << 16) | (CEXCEPTION_VERSION_MINOR << 8) | CEXCEPTION_VERSION_BUILD)
+
+//To Use CException, you have a number of options:
+//1. Just include it and run with the defaults
+//2. Define any of the following symbols at the command line to override them
+//3. Include a header file before CException.h everywhere which defines any of these
+//4. Create an Exception.h in your path, and just define EXCEPTION_USE_CONFIG_FILE first
+
+#ifdef CEXCEPTION_USE_CONFIG_FILE
+#include "CExceptionConfig.h"
+#endif
+
+//This is the value to assign when there isn't an exception
+#ifndef CEXCEPTION_NONE
+#define CEXCEPTION_NONE (0x5A5A5A5A)
+#endif
+
+//This is number of exception stacks to keep track of (one per task)
+#ifndef CEXCEPTION_NUM_ID
+#define CEXCEPTION_NUM_ID (1) //there is only the one stack by default
+#endif
+
+//This is the method of getting the current exception stack index (0 if only one stack)
+#ifndef CEXCEPTION_GET_ID
+#define CEXCEPTION_GET_ID (0) //use the first index always because there is only one anyway
+#endif
+
+//The type to use to store the exception values.
+#ifndef CEXCEPTION_T
+#define CEXCEPTION_T unsigned int
+#endif
+
+//This is an optional special handler for when there is no global Catch
+#ifndef CEXCEPTION_NO_CATCH_HANDLER
+#define CEXCEPTION_NO_CATCH_HANDLER(id)
+#endif
+
+//These hooks allow you to inject custom code into places, particularly useful for saving and restoring additional state
+#ifndef CEXCEPTION_HOOK_START_TRY
+#define CEXCEPTION_HOOK_START_TRY
+#endif
+#ifndef CEXCEPTION_HOOK_HAPPY_TRY
+#define CEXCEPTION_HOOK_HAPPY_TRY
+#endif
+#ifndef CEXCEPTION_HOOK_AFTER_TRY
+#define CEXCEPTION_HOOK_AFTER_TRY
+#endif
+#ifndef CEXCEPTION_HOOK_START_CATCH
+#define CEXCEPTION_HOOK_START_CATCH
+#endif
+
+//exception frame structures
+typedef struct {
+ jmp_buf* pFrame;
+ CEXCEPTION_T volatile Exception;
+} CEXCEPTION_FRAME_T;
+
+//actual root frame storage (only one if single-tasking)
+extern volatile CEXCEPTION_FRAME_T CExceptionFrames[];
+
+//Try (see C file for explanation)
+#define Try \
+ { \
+ jmp_buf *PrevFrame, NewFrame; \
+ unsigned int MY_ID = CEXCEPTION_GET_ID; \
+ PrevFrame = CExceptionFrames[MY_ID].pFrame; \
+ CExceptionFrames[MY_ID].pFrame = (jmp_buf*)(&NewFrame); \
+ CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; \
+ CEXCEPTION_HOOK_START_TRY; \
+ if (setjmp(NewFrame) == 0) { \
+ if (1)
+
+//Catch (see C file for explanation)
+#define Catch(e) \
+ else { } \
+ CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; \
+ CEXCEPTION_HOOK_HAPPY_TRY; \
+ } \
+ else \
+ { \
+ e = CExceptionFrames[MY_ID].Exception; \
+ (void)e; \
+ CEXCEPTION_HOOK_START_CATCH; \
+ } \
+ CExceptionFrames[MY_ID].pFrame = PrevFrame; \
+ CEXCEPTION_HOOK_AFTER_TRY; \
+ } \
+ if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE)
+
+//Throw an Error
+void Throw(CEXCEPTION_T ExceptionID);
+
+//Just exit the Try block and skip the Catch.
+#define ExitTry() Throw(CEXCEPTION_NONE)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+#endif // _CEXCEPTION_H
diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/release/build.info b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/build.info
new file mode 100755
index 00000000..0cd525d8
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/build.info
@@ -0,0 +1,2 @@
+18
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/c_exception/release/version.info b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/version.info
new file mode 100755
index 00000000..1527a8de
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/c_exception/release/version.info
@@ -0,0 +1,2 @@
+1.3.1
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/config/production_environment.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/config/production_environment.rb
new file mode 100755
index 00000000..915582b7
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/config/production_environment.rb
@@ -0,0 +1,14 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+# Setup our load path:
+[
+ 'lib',
+].each do |dir|
+ $LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__)) + '/../', dir) )
+end
+
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/config/test_environment.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/config/test_environment.rb
new file mode 100755
index 00000000..fe1ed817
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/config/test_environment.rb
@@ -0,0 +1,16 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+# Setup our load path:
+[
+ './lib',
+ './vendor/behaviors/lib',
+ './vendor/hardmock/lib',
+ './vendor/unity/auto/',
+ './test/system/'
+].each do |dir|
+ $LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__) + "/../"), dir) )
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock.rb
new file mode 100755
index 00000000..8243ce58
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock.rb
@@ -0,0 +1,86 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+[ "../config/production_environment",
+ "cmock_header_parser",
+ "cmock_generator",
+ "cmock_file_writer",
+ "cmock_config",
+ "cmock_plugin_manager",
+ "cmock_generator_utils",
+ "cmock_unityhelper_parser"].each {|req| require "#{File.expand_path(File.dirname(__FILE__))}/#{req}"}
+
+class CMock
+
+ def initialize(options=nil)
+ cm_config = CMockConfig.new(options)
+ cm_unityhelper = CMockUnityHelperParser.new(cm_config)
+ cm_writer = CMockFileWriter.new(cm_config)
+ cm_gen_utils = CMockGeneratorUtils.new(cm_config, {:unity_helper => cm_unityhelper})
+ cm_gen_plugins = CMockPluginManager.new(cm_config, cm_gen_utils)
+ @cm_parser = CMockHeaderParser.new(cm_config)
+ @cm_generator = CMockGenerator.new(cm_config, cm_writer, cm_gen_utils, cm_gen_plugins)
+ @silent = (cm_config.verbosity < 2)
+ end
+
+ def setup_mocks(files)
+ [files].flatten.each do |src|
+ generate_mock src
+ end
+ end
+
+ private ###############################
+
+ def generate_mock(src)
+ name = File.basename(src, '.h')
+ puts "Creating mock for #{name}..." unless @silent
+ @cm_generator.create_mock(name, @cm_parser.parse(name, File.read(src)))
+ end
+end
+
+def option_maker(options, key, val)
+ options = options || {}
+ options[key.to_sym] =
+ if val.chr == ":"
+ val[1..-1].to_sym
+ elsif val.include? ";"
+ val.split(';')
+ elsif val == 'true'
+ true
+ elsif val == 'false'
+ false
+ elsif val =~ /^\d+$/
+ val.to_i
+ else
+ val
+ end
+ options
+end
+
+ # Command Line Support ###############################
+
+if ($0 == __FILE__)
+ usage = "usage: ruby #{__FILE__} (-oOptionsFile) File(s)ToMock"
+
+ if (!ARGV[0])
+ puts usage
+ exit 1
+ end
+
+ options = {}
+ filelist = []
+ ARGV.each do |arg|
+ if (arg =~ /^-o\"?([a-zA-Z0-9._\\\/:\s]+)\"?/)
+ options.merge! CMockConfig.load_config_file_from_yaml( arg.gsub(/^-o/,'') )
+ elsif (arg =~ /^--([a-zA-Z0-9._\\\/:\s]+)=\"?([a-zA-Z0-9._\-\\\/:\s\;]+)\"?/)
+ options = option_maker(options, $1, $2)
+ else
+ filelist << arg
+ end
+ end
+
+ CMock.new(options).setup_mocks(filelist)
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_config.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_config.rb
new file mode 100755
index 00000000..b21b61ed
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_config.rb
@@ -0,0 +1,153 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockConfig
+
+ CMockDefaultOptions =
+ {
+ :framework => :unity,
+ :mock_path => 'mocks',
+ :mock_prefix => 'Mock',
+ :mock_suffix => '',
+ :weak => '',
+ :subdir => nil,
+ :plugins => [],
+ :strippables => ['(?:__attribute__\s*\(+.*?\)+)'],
+ :attributes => ['__ramfunc', '__irq', '__fiq', 'register', 'extern'],
+ :c_calling_conventions => ['__stdcall', '__cdecl', '__fastcall'],
+ :enforce_strict_ordering => false,
+ :fail_on_unexpected_calls => true,
+ :unity_helper_path => false,
+ :treat_as => {},
+ :treat_as_array => {},
+ :treat_as_void => [],
+ :memcmp_if_unknown => true,
+ :when_no_prototypes => :warn, #the options being :ignore, :warn, or :error
+ :when_ptr => :compare_data, #the options being :compare_ptr, :compare_data, or :smart
+ :verbosity => 2, #the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose
+ :treat_externs => :exclude, #the options being :include or :exclude
+ :callback_include_count => true,
+ :callback_after_arg_check => false,
+ :includes => nil,
+ :includes_h_pre_orig_header => nil,
+ :includes_h_post_orig_header => nil,
+ :includes_c_pre_header => nil,
+ :includes_c_post_header => nil,
+ :orig_header_include_fmt => "#include \"%s\"",
+ :array_size_type => [],
+ :array_size_name => 'size|len',
+ }
+
+ def initialize(options=nil)
+ case(options)
+ when NilClass then options = CMockDefaultOptions.clone
+ when String then options = CMockDefaultOptions.clone.merge(load_config_file_from_yaml(options))
+ when Hash then options = CMockDefaultOptions.clone.merge(options)
+ else raise "If you specify arguments, it should be a filename or a hash of options"
+ end
+
+ #do some quick type verification
+ [:plugins, :attributes, :treat_as_void].each do |opt|
+ unless (options[opt].class == Array)
+ options[opt] = []
+ puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1)
+ end
+ end
+ [:includes, :includes_h_pre_orig_header, :includes_h_post_orig_header, :includes_c_pre_header, :includes_c_post_header].each do |opt|
+ unless (options[opt].nil? or (options[opt].class == Array))
+ options[opt] = []
+ puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1)
+ end
+ end
+ options[:unity_helper_path] ||= options[:unity_helper]
+ options[:unity_helper_path] = [options[:unity_helper_path]] if options[:unity_helper_path].is_a? String
+ options[:includes_c_post_header] = ((options[:includes_c_post_header] || []) + (options[:unity_helper_path] || [])).uniq
+ options[:plugins].compact!
+ options[:plugins].map! {|p| p.to_sym}
+ @options = options
+
+ treat_as_map = standard_treat_as_map()#.clone
+ treat_as_map.merge!(@options[:treat_as])
+ @options[:treat_as] = treat_as_map
+
+ @options.each_key do |key|
+ unless methods.include?(key)
+ eval("def #{key.to_s}() return @options[:#{key.to_s}] end")
+ end
+ end
+ end
+
+ def load_config_file_from_yaml yaml_filename
+ self.class.load_config_file_from_yaml yaml_filename
+ end
+
+ def self.load_config_file_from_yaml yaml_filename
+ require 'yaml'
+ require 'fileutils'
+ YAML.load_file(yaml_filename)[:cmock]
+ end
+
+ def set_path(path)
+ @src_path = path
+ end
+
+ def load_unity_helper
+ return nil unless (@options[:unity_helper_path])
+
+ return @options[:unity_helper_path].inject("") do |unity_helper, filename|
+ unity_helper + "\n" + File.new(filename).read
+ end
+ end
+
+ def standard_treat_as_map
+ {
+ 'int' => 'INT',
+ 'char' => 'INT8',
+ 'short' => 'INT16',
+ 'long' => 'INT',
+ 'int8' => 'INT8',
+ 'int16' => 'INT16',
+ 'int32' => 'INT',
+ 'int8_t' => 'INT8',
+ 'int16_t' => 'INT16',
+ 'int32_t' => 'INT',
+ 'INT8_T' => 'INT8',
+ 'INT16_T' => 'INT16',
+ 'INT32_T' => 'INT',
+ 'bool' => 'INT',
+ 'bool_t' => 'INT',
+ 'BOOL' => 'INT',
+ 'BOOL_T' => 'INT',
+ 'unsigned int' => 'HEX32',
+ 'unsigned long' => 'HEX32',
+ 'uint32' => 'HEX32',
+ 'uint32_t' => 'HEX32',
+ 'UINT32' => 'HEX32',
+ 'UINT32_T' => 'HEX32',
+ 'void*' => 'HEX8_ARRAY',
+ 'void const*' => 'HEX8_ARRAY',
+ 'const void*' => 'HEX8_ARRAY',
+ 'unsigned short' => 'HEX16',
+ 'uint16' => 'HEX16',
+ 'uint16_t' => 'HEX16',
+ 'UINT16' => 'HEX16',
+ 'UINT16_T' => 'HEX16',
+ 'unsigned char' => 'HEX8',
+ 'uint8' => 'HEX8',
+ 'uint8_t' => 'HEX8',
+ 'UINT8' => 'HEX8',
+ 'UINT8_T' => 'HEX8',
+ 'char*' => 'STRING',
+ 'char const*' => 'STRING',
+ 'const char*' => 'STRING',
+ 'pCHAR' => 'STRING',
+ 'cstring' => 'STRING',
+ 'CSTRING' => 'STRING',
+ 'float' => 'FLOAT',
+ 'double' => 'FLOAT'
+ }
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_file_writer.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_file_writer.rb
new file mode 100755
index 00000000..d2d954cb
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_file_writer.rb
@@ -0,0 +1,44 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockFileWriter
+
+ attr_reader :config
+
+ def initialize(config)
+ @config = config
+ end
+
+ def create_subdir(subdir)
+ if !Dir.exists?("#{@config.mock_path}/")
+ require 'fileutils'
+ FileUtils.mkdir_p "#{@config.mock_path}/"
+ end
+ if subdir && !Dir.exists?("#{@config.mock_path}/#{subdir+'/' if subdir}")
+ require 'fileutils'
+ FileUtils.mkdir_p "#{@config.mock_path}/#{subdir+'/' if subdir}"
+ end
+ end
+
+ def create_file(filename, subdir)
+ raise "Where's the block of data to create?" unless block_given?
+ full_file_name_temp = "#{@config.mock_path}/#{subdir+'/' if subdir}#{filename}.new"
+ full_file_name_done = "#{@config.mock_path}/#{subdir+'/' if subdir}#{filename}"
+ File.open(full_file_name_temp, 'w') do |file|
+ yield(file, filename)
+ end
+ update_file(full_file_name_done, full_file_name_temp)
+ end
+
+ private ###################################
+
+ def update_file(dest, src)
+ require 'fileutils'
+ FileUtils.rm(dest) if (File.exist?(dest))
+ FileUtils.cp(src, dest)
+ FileUtils.rm(src)
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb
new file mode 100755
index 00000000..42725a60
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator.rb
@@ -0,0 +1,268 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGenerator
+
+ attr_accessor :config, :file_writer, :module_name, :clean_mock_name, :mock_name, :utils, :plugins, :weak, :ordered
+
+ def initialize(config, file_writer, utils, plugins)
+ @file_writer = file_writer
+ @utils = utils
+ @plugins = plugins
+ @config = config
+ @prefix = @config.mock_prefix
+ @suffix = @config.mock_suffix
+ @weak = @config.weak
+ @ordered = @config.enforce_strict_ordering
+ @framework = @config.framework.to_s
+ @fail_on_unexpected_calls = @config.fail_on_unexpected_calls
+
+ @subdir = @config.subdir
+
+ @includes_h_pre_orig_header = (@config.includes || @config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+ @includes_h_post_orig_header = (@config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+ @includes_c_pre_header = (@config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+ @includes_c_post_header = (@config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
+
+ here = File.dirname __FILE__
+ unity_path_in_ceedling = "#{here}/../../unity" # path to Unity from within Ceedling
+ unity_path_in_cmock = "#{here}/../vendor/unity" # path to Unity from within CMock
+ # path to Unity as specified by env var
+ unity_path_in_env = ENV.has_key?("UNITY_DIR") ? File.expand_path(ENV.fetch("UNITY_DIR")) : nil
+
+ if unity_path_in_env and File.exist? unity_path_in_env
+ require "#{unity_path_in_env}/auto/type_sanitizer"
+ elsif File.exist? unity_path_in_ceedling
+ require "#{unity_path_in_ceedling}/auto/type_sanitizer"
+ elsif File.exist? unity_path_in_cmock
+ require "#{unity_path_in_cmock}/auto/type_sanitizer"
+ else
+ raise "Failed to find an instance of Unity to pull in type_sanitizer module!"
+ end
+
+ end
+
+ def create_mock(module_name, parsed_stuff)
+ @module_name = module_name
+ @mock_name = @prefix + @module_name + @suffix
+ @clean_mock_name = TypeSanitizer.sanitize_c_identifier(@mock_name)
+ create_mock_subdir()
+ create_mock_header_file(parsed_stuff)
+ create_mock_source_file(parsed_stuff)
+ end
+
+ private if $ThisIsOnlyATest.nil? ##############################
+
+ def create_mock_subdir()
+ @file_writer.create_subdir(@subdir)
+ end
+
+ def create_mock_header_file(parsed_stuff)
+ @file_writer.create_file(@mock_name + ".h", @subdir) do |file, filename|
+ create_mock_header_header(file, filename)
+ create_mock_header_service_call_declarations(file)
+ create_typedefs(file, parsed_stuff[:typedefs])
+ parsed_stuff[:functions].each do |function|
+ file << @plugins.run(:mock_function_declarations, function)
+ end
+ create_mock_header_footer(file)
+ end
+ end
+
+ def create_mock_source_file(parsed_stuff)
+ @file_writer.create_file(@mock_name + ".c", @subdir) do |file, filename|
+ create_source_header_section(file, filename, parsed_stuff[:functions])
+ create_instance_structure(file, parsed_stuff[:functions])
+ create_extern_declarations(file)
+ create_mock_verify_function(file, parsed_stuff[:functions])
+ create_mock_init_function(file)
+ create_mock_destroy_function(file, parsed_stuff[:functions])
+ parsed_stuff[:functions].each do |function|
+ create_mock_implementation(file, function)
+ create_mock_interfaces(file, function)
+ end
+ end
+ end
+
+ def create_mock_header_header(file, filename)
+ define_name = @clean_mock_name.upcase
+ orig_filename = (@subdir ? @subdir + "/" : "") + @module_name + ".h"
+ file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
+ file << "#ifndef _#{define_name}_H\n"
+ file << "#define _#{define_name}_H\n\n"
+ file << "#include \"#{@framework}.h\"\n"
+ @includes_h_pre_orig_header.each {|inc| file << "#include #{inc}\n"}
+ file << @config.orig_header_include_fmt.gsub(/%s/, "#{orig_filename}") + "\n"
+ @includes_h_post_orig_header.each {|inc| file << "#include #{inc}\n"}
+ plugin_includes = @plugins.run(:include_files)
+ file << plugin_includes if (!plugin_includes.empty?)
+ file << "\n"
+ file << "/* Ignore the following warnings, since we are copying code */\n"
+ file << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n"
+ file << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n"
+ file << "#pragma GCC diagnostic push\n"
+ file << "#endif\n"
+ file << "#if !defined(__clang__)\n"
+ file << "#pragma GCC diagnostic ignored \"-Wpragmas\"\n"
+ file << "#endif\n"
+ file << "#pragma GCC diagnostic ignored \"-Wunknown-pragmas\"\n"
+ file << "#pragma GCC diagnostic ignored \"-Wduplicate-decl-specifier\"\n"
+ file << "#endif\n"
+ file << "\n"
+ end
+
+ def create_typedefs(file, typedefs)
+ file << "\n"
+ typedefs.each {|typedef| file << "#{typedef}\n" }
+ file << "\n\n"
+ end
+
+ def create_mock_header_service_call_declarations(file)
+ file << "void #{@clean_mock_name}_Init(void);\n"
+ file << "void #{@clean_mock_name}_Destroy(void);\n"
+ file << "void #{@clean_mock_name}_Verify(void);\n\n"
+ end
+
+ def create_mock_header_footer(header)
+ header << "\n"
+ header << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n"
+ header << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n"
+ header << "#pragma GCC diagnostic pop\n"
+ header << "#endif\n"
+ header << "#endif\n"
+ header << "\n"
+ header << "#endif\n"
+ end
+
+ def create_source_header_section(file, filename, functions)
+ header_file = (@subdir ? @subdir + '/' : '') + filename.gsub(".c",".h")
+ file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
+ file << "#include <string.h>\n"
+ file << "#include <stdlib.h>\n"
+ file << "#include <setjmp.h>\n"
+ file << "#include \"cmock.h\"\n"
+ @includes_c_pre_header.each {|inc| file << "#include #{inc}\n"}
+ file << "#include \"#{header_file}\"\n"
+ @includes_c_post_header.each {|inc| file << "#include #{inc}\n"}
+ file << "\n"
+ strs = []
+ functions.each do |func|
+ strs << func[:name]
+ func[:args].each {|arg| strs << arg[:name] }
+ end
+ strs.uniq.sort.each do |str|
+ file << "static const char* CMockString_#{str} = \"#{str}\";\n"
+ end
+ file << "\n"
+ end
+
+ def create_instance_structure(file, functions)
+ functions.each do |function|
+ file << "typedef struct _CMOCK_#{function[:name]}_CALL_INSTANCE\n{\n"
+ file << " UNITY_LINE_TYPE LineNumber;\n"
+ file << @plugins.run(:instance_typedefs, function)
+ file << "\n} CMOCK_#{function[:name]}_CALL_INSTANCE;\n\n"
+ end
+ file << "static struct #{@clean_mock_name}Instance\n{\n"
+ if (functions.size == 0)
+ file << " unsigned char placeHolder;\n"
+ end
+ functions.each do |function|
+ file << @plugins.run(:instance_structure, function)
+ file << " CMOCK_MEM_INDEX_TYPE #{function[:name]}_CallInstance;\n"
+ end
+ file << "} Mock;\n\n"
+ end
+
+ def create_extern_declarations(file)
+ file << "extern jmp_buf AbortFrame;\n"
+ if (@ordered)
+ file << "extern int GlobalExpectCount;\n"
+ file << "extern int GlobalVerifyOrder;\n"
+ end
+ file << "\n"
+ end
+
+ def create_mock_verify_function(file, functions)
+ file << "void #{@clean_mock_name}_Verify(void)\n{\n"
+ verifications = functions.collect do |function|
+ v = @plugins.run(:mock_verify, function)
+ v.empty? ? v : [" call_instance = Mock.#{function[:name]}_CallInstance;\n", v]
+ end.join
+ unless verifications.empty?
+ file << " UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n"
+ file << " CMOCK_MEM_INDEX_TYPE call_instance;\n"
+ file << verifications
+ end
+ file << "}\n\n"
+ end
+
+ def create_mock_init_function(file)
+ file << "void #{@clean_mock_name}_Init(void)\n{\n"
+ file << " #{@clean_mock_name}_Destroy();\n"
+ file << "}\n\n"
+ end
+
+ def create_mock_destroy_function(file, functions)
+ file << "void #{@clean_mock_name}_Destroy(void)\n{\n"
+ file << " CMock_Guts_MemFreeAll();\n"
+ file << " memset(&Mock, 0, sizeof(Mock));\n"
+ file << functions.collect {|function| @plugins.run(:mock_destroy, function)}.join
+
+ unless (@fail_on_unexpected_calls)
+ file << functions.collect {|function| @plugins.run(:mock_ignore, function)}.join
+ end
+
+ if (@ordered)
+ file << " GlobalExpectCount = 0;\n"
+ file << " GlobalVerifyOrder = 0;\n"
+ end
+ file << "}\n\n"
+ end
+
+ def create_mock_implementation(file, function)
+ # prepare return value and arguments
+ function_mod_and_rettype = (function[:modifier].empty? ? '' : "#{function[:modifier]} ") +
+ (function[:return][:type]) +
+ (function[:c_calling_convention] ? " #{function[:c_calling_convention]}" : '')
+ args_string = function[:args_string]
+ args_string += (", " + function[:var_arg]) unless (function[:var_arg].nil?)
+
+ # Create mock function
+ if (not @weak.empty?)
+ file << "#if defined (__IAR_SYSTEMS_ICC__)\n"
+ file << "#pragma weak #{function[:name]}\n"
+ file << "#else\n"
+ file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string}) #{weak};\n"
+ file << "#endif\n\n"
+ end
+ file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string})\n"
+ file << "{\n"
+ file << " UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n"
+ file << " CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance;\n"
+ file << " UNITY_SET_DETAIL(CMockString_#{function[:name]});\n"
+ file << " cmock_call_instance = (CMOCK_#{function[:name]}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.#{function[:name]}_CallInstance);\n"
+ file << " Mock.#{function[:name]}_CallInstance = CMock_Guts_MemNext(Mock.#{function[:name]}_CallInstance);\n"
+ file << @plugins.run(:mock_implementation_precheck, function)
+ file << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore);\n"
+ file << " cmock_line = cmock_call_instance->LineNumber;\n"
+ if (@ordered)
+ file << " if (cmock_call_instance->CallOrder > ++GlobalVerifyOrder)\n"
+ file << " UNITY_TEST_FAIL(cmock_line, CMockStringCalledEarly);\n"
+ file << " if (cmock_call_instance->CallOrder < GlobalVerifyOrder)\n"
+ file << " UNITY_TEST_FAIL(cmock_line, CMockStringCalledLate);\n"
+ end
+ file << @plugins.run(:mock_implementation, function)
+ file << " UNITY_CLR_DETAILS();\n"
+ file << " return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?])
+ file << "}\n\n"
+ end
+
+ def create_mock_interfaces(file, function)
+ file << @utils.code_add_argument_loader(function)
+ file << @plugins.run(:mock_interfaces, function)
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_array.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_array.rb
new file mode 100755
index 00000000..3b73708e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_array.rb
@@ -0,0 +1,63 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGeneratorPluginArray
+
+ attr_reader :priority
+ attr_accessor :config, :utils, :unity_helper, :ordered
+ def initialize(config, utils)
+ @config = config
+ @ptr_handling = @config.when_ptr
+ @ordered = @config.enforce_strict_ordering
+ @utils = utils
+ @unity_helper = @utils.helpers[:unity_helper]
+ @priority = 8
+ end
+
+ def instance_typedefs(function)
+ function[:args].inject("") do |all, arg|
+ (arg[:ptr?]) ? all + " int Expected_#{arg[:name]}_Depth;\n" : all
+ end
+ end
+
+ def mock_function_declarations(function)
+ return nil unless function[:contains_ptr?]
+ args_call = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : "#{m[:name]}"}.join(', ')
+ args_string = function[:args].map do |m|
+ type = @utils.arg_type_with_const(m)
+ m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
+ end.join(', ')
+ if (function[:return][:void?])
+ return "#define #{function[:name]}_ExpectWithArray(#{args_call}) #{function[:name]}_CMockExpectWithArray(__LINE__, #{args_call})\n" +
+ "void #{function[:name]}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string});\n"
+ else
+ return "#define #{function[:name]}_ExpectWithArrayAndReturn(#{args_call}, cmock_retval) #{function[:name]}_CMockExpectWithArrayAndReturn(__LINE__, #{args_call}, cmock_retval)\n" +
+ "void #{function[:name]}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]});\n"
+ end
+ end
+
+ def mock_interfaces(function)
+ return nil unless function[:contains_ptr?]
+ lines = []
+ func_name = function[:name]
+ args_string = function[:args].map do |m|
+ type = @utils.arg_type_with_const(m)
+ m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
+ end.join(', ')
+ call_string = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name]}.join(', ')
+ if (function[:return][:void?])
+ lines << "void #{func_name}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string})\n"
+ else
+ lines << "void #{func_name}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]})\n"
+ end
+ lines << "{\n"
+ lines << @utils.code_add_base_expectation(func_name)
+ lines << " CMockExpectParameters_#{func_name}(cmock_call_instance, #{call_string});\n"
+ lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n" unless (function[:return][:void?])
+ lines << "}\n\n"
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_callback.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_callback.rb
new file mode 100755
index 00000000..564e0ac2
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_callback.rb
@@ -0,0 +1,88 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGeneratorPluginCallback
+
+ attr_accessor :include_count
+ attr_reader :priority
+ attr_reader :config, :utils
+
+ def initialize(config, utils)
+ @config = config
+ @utils = utils
+ @priority = 6
+
+ @include_count = @config.callback_include_count
+ end
+
+ def instance_structure(function)
+ func_name = function[:name]
+ " int #{func_name}_CallbackBool;\n" \
+ " CMOCK_#{func_name}_CALLBACK #{func_name}_CallbackFunctionPointer;\n" \
+ " int #{func_name}_CallbackCalls;\n"
+ end
+
+ def mock_function_declarations(function)
+ func_name = function[:name]
+ return_type = function[:return][:type]
+ action = @config.callback_after_arg_check ? 'AddCallback' : 'Stub'
+ style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2)
+ styles = [ "void", "int cmock_num_calls", function[:args_string], "#{function[:args_string]}, int cmock_num_calls" ]
+ "typedef #{return_type} (* CMOCK_#{func_name}_CALLBACK)(#{styles[style]});\n" \
+ "void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" \
+ "void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback);\n" \
+ "#define #{func_name}_StubWithCallback #{func_name}_#{action}\n"
+ end
+
+ def generate_call(function)
+ args = function[:args].map { |m| m[:name] }
+ args << "Mock.#{function[:name]}_CallbackCalls++" if @include_count
+ "Mock.#{function[:name]}_CallbackFunctionPointer(#{args.join(', ')})"
+ end
+
+ def mock_implementation(function)
+ " if (Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n {\n" +
+ if function[:return][:void?]
+ " #{generate_call(function)};\n }\n"
+ else
+ " cmock_call_instance->ReturnVal = #{generate_call(function)};\n }\n"
+ end
+ end
+
+ def mock_implementation_precheck(function)
+ " if (!Mock.#{function[:name]}_CallbackBool &&\n" \
+ " Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n {\n" +
+ if function[:return][:void?]
+ " #{generate_call(function)};\n" \
+ " UNITY_CLR_DETAILS();\n" \
+ " return;\n }\n"
+ else
+ " #{function[:return][:type]} ret = #{generate_call(function)};\n" \
+ " UNITY_CLR_DETAILS();\n" \
+ " return ret;\n }\n"
+ end
+ end
+
+ def mock_interfaces(function)
+ func_name = function[:name]
+ has_ignore = @config.plugins.include? :ignore
+ lines = ""
+ lines << "void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
+ lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore
+ lines << " Mock.#{func_name}_CallbackBool = (int)1;\n"
+ lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
+ lines << "void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
+ lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore
+ lines << " Mock.#{func_name}_CallbackBool = (int)0;\n"
+ lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
+ end
+
+ def mock_verify(function)
+ func_name = function[:name]
+ " if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n call_instance = CMOCK_GUTS_NONE;\n"
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_cexception.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_cexception.rb
new file mode 100755
index 00000000..39d36d64
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_cexception.rb
@@ -0,0 +1,51 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGeneratorPluginCexception
+
+ attr_reader :priority
+ attr_reader :config, :utils
+
+ def initialize(config, utils)
+ @config = config
+ @utils = utils
+ @priority = 7
+ end
+
+ def include_files
+ return "#include \"CException.h\"\n"
+ end
+
+ def instance_typedefs(function)
+ " CEXCEPTION_T ExceptionToThrow;\n"
+ end
+
+ def mock_function_declarations(function)
+ if (function[:args_string] == "void")
+ return "#define #{function[:name]}_ExpectAndThrow(cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, cmock_to_throw)\n" +
+ "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, CEXCEPTION_T cmock_to_throw);\n"
+ else
+ return "#define #{function[:name]}_ExpectAndThrow(#{function[:args_call]}, cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, #{function[:args_call]}, cmock_to_throw)\n" +
+ "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, CEXCEPTION_T cmock_to_throw);\n"
+ end
+ end
+
+ def mock_implementation(function)
+ " if (cmock_call_instance->ExceptionToThrow != CEXCEPTION_NONE)\n {\n" +
+ " UNITY_CLR_DETAILS();\n" +
+ " Throw(cmock_call_instance->ExceptionToThrow);\n }\n"
+ end
+
+ def mock_interfaces(function)
+ arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, "
+ [ "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{arg_insert}CEXCEPTION_T cmock_to_throw)\n{\n",
+ @utils.code_add_base_expectation(function[:name]),
+ @utils.code_call_argument_loader(function),
+ " cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n",
+ "}\n\n" ].join
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect.rb
new file mode 100755
index 00000000..dcf96f2e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect.rb
@@ -0,0 +1,103 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGeneratorPluginExpect
+
+ attr_reader :priority
+ attr_accessor :config, :utils, :unity_helper, :ordered
+
+ def initialize(config, utils)
+ @config = config
+ @ptr_handling = @config.when_ptr
+ @ordered = @config.enforce_strict_ordering
+ @utils = utils
+ @unity_helper = @utils.helpers[:unity_helper]
+ @priority = 5
+
+ if (@config.plugins.include? :expect_any_args)
+ alias :mock_implementation :mock_implementation_might_check_args
+ else
+ alias :mock_implementation :mock_implementation_always_check_args
+ end
+ end
+
+ def instance_typedefs(function)
+ lines = ""
+ lines << " #{function[:return][:type]} ReturnVal;\n" unless (function[:return][:void?])
+ lines << " int CallOrder;\n" if (@ordered)
+ function[:args].each do |arg|
+ lines << " #{arg[:type]} Expected_#{arg[:name]};\n"
+ end
+ lines
+ end
+
+ def mock_function_declarations(function)
+ if (function[:args].empty?)
+ if (function[:return][:void?])
+ return "#define #{function[:name]}_Expect() #{function[:name]}_CMockExpect(__LINE__)\n" +
+ "void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line);\n"
+ else
+ return "#define #{function[:name]}_ExpectAndReturn(cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, cmock_retval)\n" +
+ "void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
+ end
+ else
+ if (function[:return][:void?])
+ return "#define #{function[:name]}_Expect(#{function[:args_call]}) #{function[:name]}_CMockExpect(__LINE__, #{function[:args_call]})\n" +
+ "void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]});\n"
+ else
+ return "#define #{function[:name]}_ExpectAndReturn(#{function[:args_call]}, cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, #{function[:args_call]}, cmock_retval)\n" +
+ "void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]});\n"
+ end
+ end
+ end
+
+ def mock_implementation_always_check_args(function)
+ lines = ""
+ function[:args].each do |arg|
+ lines << @utils.code_verify_an_arg_expectation(function, arg)
+ end
+ lines
+ end
+
+ def mock_implementation_might_check_args(function)
+ return "" if (function[:args].empty?)
+ lines = " if (!cmock_call_instance->ExpectAnyArgsBool)\n {\n"
+ function[:args].each do |arg|
+ lines << @utils.code_verify_an_arg_expectation(function, arg)
+ end
+ lines << " }\n"
+ lines
+ end
+
+ def mock_interfaces(function)
+ lines = ""
+ func_name = function[:name]
+ if (function[:return][:void?])
+ if (function[:args_string] == "void")
+ lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line)\n{\n"
+ else
+ lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]})\n{\n"
+ end
+ else
+ if (function[:args_string] == "void")
+ lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
+ else
+ lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]})\n{\n"
+ end
+ end
+ lines << @utils.code_add_base_expectation(func_name)
+ lines << @utils.code_call_argument_loader(function)
+ lines << @utils.code_assign_argument_quickly("cmock_call_instance->ReturnVal", function[:return]) unless (function[:return][:void?])
+ lines << "}\n\n"
+ end
+
+ def mock_verify(function)
+ " UNITY_SET_DETAIL(CMockString_#{function[:name]});\n" +
+ " UNITY_TEST_ASSERT(CMOCK_GUTS_NONE == call_instance, cmock_line, CMockStringCalledLess);\n" +
+ " UNITY_CLR_DETAILS();\n"
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect_any_args.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect_any_args.rb
new file mode 100755
index 00000000..0c1c74e9
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_expect_any_args.rb
@@ -0,0 +1,53 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGeneratorPluginExpectAnyArgs
+
+ attr_reader :priority
+ attr_reader :config, :utils
+
+ def initialize(config, utils)
+ @config = config
+ @utils = utils
+ @priority = 3
+ end
+
+ def instance_typedefs(function)
+ " int ExpectAnyArgsBool;\n"
+ end
+
+ def mock_function_declarations(function)
+ unless (function[:args].empty?)
+ if (function[:return][:void?])
+ return "#define #{function[:name]}_ExpectAnyArgs() #{function[:name]}_CMockExpectAnyArgs(__LINE__)\n" +
+ "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line);\n"
+ else
+ return "#define #{function[:name]}_ExpectAnyArgsAndReturn(cmock_retval) #{function[:name]}_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval)\n" +
+ "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
+ end
+ else
+ ""
+ end
+ end
+
+ def mock_interfaces(function)
+ lines = ""
+ unless (function[:args].empty?)
+ if (function[:return][:void?])
+ lines << "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line)\n{\n"
+ else
+ lines << "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
+ end
+ lines << @utils.code_add_base_expectation(function[:name], true)
+ unless (function[:return][:void?])
+ lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n"
+ end
+ lines << " cmock_call_instance->ExpectAnyArgsBool = (int)1;\n"
+ lines << "}\n\n"
+ end
+ return lines
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore.rb
new file mode 100755
index 00000000..8f31967a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore.rb
@@ -0,0 +1,75 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGeneratorPluginIgnore
+
+ attr_reader :priority
+ attr_reader :config, :utils
+
+ def initialize(config, utils)
+ @config = config
+ @utils = utils
+ @priority = 2
+ end
+
+ def instance_structure(function)
+ if (function[:return][:void?])
+ " int #{function[:name]}_IgnoreBool;\n"
+ else
+ " int #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
+ end
+ end
+
+ def mock_function_declarations(function)
+ if (function[:return][:void?])
+ return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" +
+ "void #{function[:name]}_CMockIgnore(void);\n"
+ else
+ return "#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n" +
+ "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
+ end
+ end
+
+ def mock_implementation_precheck(function)
+ lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n"
+ lines << " UNITY_CLR_DETAILS();\n"
+ if (function[:return][:void?])
+ lines << " return;\n }\n"
+ else
+ retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} )
+ lines << " if (cmock_call_instance == NULL)\n return Mock.#{function[:name]}_FinalReturn;\n"
+ lines << " " + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless (retval[:void?])
+ lines << " return cmock_call_instance->ReturnVal;\n }\n"
+ end
+ lines
+ end
+
+ def mock_interfaces(function)
+ lines = ""
+ if (function[:return][:void?])
+ lines << "void #{function[:name]}_CMockIgnore(void)\n{\n"
+ else
+ lines << "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
+ end
+ if (!function[:return][:void?])
+ lines << @utils.code_add_base_expectation(function[:name], false)
+ end
+ unless (function[:return][:void?])
+ lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n"
+ end
+ lines << " Mock.#{function[:name]}_IgnoreBool = (int)1;\n"
+ lines << "}\n\n"
+ end
+
+ def mock_ignore(function)
+ " Mock.#{function[:name]}_IgnoreBool = (int) 1;\n"
+ end
+
+ def mock_verify(function)
+ func_name = function[:name]
+ " if (Mock.#{func_name}_IgnoreBool)\n call_instance = CMOCK_GUTS_NONE;\n"
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb
new file mode 100755
index 00000000..ef40e503
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_ignore_arg.rb
@@ -0,0 +1,42 @@
+class CMockGeneratorPluginIgnoreArg
+ attr_reader :priority
+ attr_accessor :utils
+
+ def initialize(config, utils)
+ @utils = utils
+ @priority = 10
+ end
+
+ def instance_typedefs(function)
+ lines = ""
+ function[:args].each do |arg|
+ lines << " int IgnoreArg_#{arg[:name]};\n"
+ end
+ lines
+ end
+
+ def mock_function_declarations(function)
+ lines = ""
+ function[:args].each do |arg|
+ lines << "#define #{function[:name]}_IgnoreArg_#{arg[:name]}()"
+ lines << " #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(__LINE__)\n"
+ lines << "void #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line);\n"
+ end
+ lines
+ end
+
+ def mock_interfaces(function)
+ lines = []
+ func_name = function[:name]
+ function[:args].each do |arg|
+ lines << "void #{func_name}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line)\n"
+ lines << "{\n"
+ lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = " +
+ "(CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.#{func_name}_CallInstance));\n"
+ lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp);\n"
+ lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 1;\n"
+ lines << "}\n\n"
+ end
+ lines
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb
new file mode 100755
index 00000000..1c1af061
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_plugin_return_thru_ptr.rb
@@ -0,0 +1,79 @@
+class CMockGeneratorPluginReturnThruPtr
+ attr_reader :priority
+ attr_accessor :utils
+
+ def initialize(config, utils)
+ @utils = utils
+ @priority = 9
+ end
+
+ def instance_typedefs(function)
+ lines = ""
+ function[:args].each do |arg|
+ if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
+ lines << " int ReturnThruPtr_#{arg[:name]}_Used;\n"
+ lines << " #{arg[:type]} ReturnThruPtr_#{arg[:name]}_Val;\n"
+ lines << " int ReturnThruPtr_#{arg[:name]}_Size;\n"
+ end
+ end
+ lines
+ end
+
+ def mock_function_declarations(function)
+ lines = ""
+ function[:args].each do |arg|
+ if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
+ lines << "#define #{function[:name]}_ReturnThruPtr_#{arg[:name]}(#{arg[:name]})"
+ # If the pointer type actually contains an asterisk, we can do sizeof the type (super safe), otherwise
+ # we need to do a sizeof the dereferenced pointer (which could be a problem if give the wrong size
+ if (arg[:type][-1] == '*')
+ lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(#{arg[:type][0..-2]}))\n"
+ else
+ lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(*#{arg[:name]}))\n"
+ end
+ lines << "#define #{function[:name]}_ReturnArrayThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_len)"
+ lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, (int)(cmock_len * (int)sizeof(*#{arg[:name]})))\n"
+ lines << "#define #{function[:name]}_ReturnMemThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_size)"
+ lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, cmock_size)\n"
+ lines << "void #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg[:name]}, int cmock_size);\n"
+ end
+ end
+ lines
+ end
+
+ def mock_interfaces(function)
+ lines = []
+ func_name = function[:name]
+ function[:args].each do |arg|
+ arg_name = arg[:name]
+ if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
+ lines << "void #{func_name}_CMockReturnMemThruPtr_#{arg_name}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg_name}, int cmock_size)\n"
+ lines << "{\n"
+ lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = " +
+ "(CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.#{func_name}_CallInstance));\n"
+ lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringPtrPreExp);\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Used = 1;\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Val = #{arg_name};\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size = cmock_size;\n"
+ lines << "}\n\n"
+ end
+ end
+ lines
+ end
+
+ def mock_implementation(function)
+ lines = []
+ function[:args].each do |arg|
+ arg_name = arg[:name]
+ if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
+ lines << " if (cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n"
+ lines << " {\n"
+ lines << " UNITY_TEST_ASSERT_NOT_NULL(#{arg_name}, cmock_line, CMockStringPtrIsNULL);\n"
+ lines << " memcpy((void*)#{arg_name}, (void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size);\n"
+ lines << " }\n"
+ end
+ end
+ lines
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_utils.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_utils.rb
new file mode 100755
index 00000000..994e85c5
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_generator_utils.rb
@@ -0,0 +1,253 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockGeneratorUtils
+
+ attr_accessor :config, :helpers, :ordered, :ptr_handling, :arrays, :cexception
+
+ def initialize(config, helpers={})
+ @config = config
+ @ptr_handling = @config.when_ptr
+ @ordered = @config.enforce_strict_ordering
+ @arrays = @config.plugins.include? :array
+ @cexception = @config.plugins.include? :cexception
+ @expect_any = @config.plugins.include? :expect_any_args
+ @return_thru_ptr = @config.plugins.include? :return_thru_ptr
+ @ignore_arg = @config.plugins.include? :ignore_arg
+ @ignore = @config.plugins.include? :ignore
+ @treat_as = @config.treat_as
+ @helpers = helpers
+ end
+
+ def self.arg_type_with_const(arg)
+ # Restore any "const" that was removed in header parsing
+ if arg[:type].include?('*')
+ arg[:const_ptr?] ? "#{arg[:type]} const" : arg[:type]
+ else
+ arg[:const?] ? "const #{arg[:type]}" : arg[:type]
+ end
+ end
+
+ def arg_type_with_const(arg)
+ self.class.arg_type_with_const(arg)
+ end
+
+ def code_verify_an_arg_expectation(function, arg)
+ if (@arrays)
+ case(@ptr_handling)
+ when :smart then code_verify_an_arg_expectation_with_smart_arrays(function, arg)
+ when :compare_data then code_verify_an_arg_expectation_with_normal_arrays(function, arg)
+ when :compare_ptr then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only. Disable one option."
+ end
+ else
+ code_verify_an_arg_expectation_with_no_arrays(function, arg)
+ end
+ end
+
+ def code_add_base_expectation(func_name, global_ordering_supported=true)
+ lines = " CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n"
+ lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index);\n"
+ lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory);\n"
+ lines << " memset(cmock_call_instance, 0, sizeof(*cmock_call_instance));\n"
+ lines << " Mock.#{func_name}_CallInstance = CMock_Guts_MemChain(Mock.#{func_name}_CallInstance, cmock_guts_index);\n"
+ lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if (@ignore)
+ lines << " cmock_call_instance->LineNumber = cmock_line;\n"
+ lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if (@ordered and global_ordering_supported)
+ lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if (@cexception)
+ lines << " cmock_call_instance->ExpectAnyArgsBool = (int)0;\n" if (@expect_any)
+ lines
+ end
+
+ def code_add_an_arg_expectation(arg, depth=1)
+ lines = code_assign_argument_quickly("cmock_call_instance->Expected_#{arg[:name]}", arg)
+ lines << " cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if (@arrays and (depth.class == String))
+ lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if (@ignore_arg)
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if (@return_thru_ptr and ptr_or_str?(arg[:type]) and not arg[:const?])
+ lines
+ end
+
+ def code_assign_argument_quickly(dest, arg)
+ if (arg[:ptr?] or @treat_as.include?(arg[:type]))
+ " #{dest} = #{arg[:name]};\n"
+ else
+ assert_expr = "sizeof(#{arg[:name]}) == sizeof(#{arg[:type]}) ? 1 : -1"
+ comment = "/* add #{arg[:type]} to :treat_as_array if this causes an error */"
+ " memcpy((void*)(&#{dest}), (void*)(&#{arg[:name]}),\n" +
+ " sizeof(#{arg[:type]}[#{assert_expr}])); #{comment}\n"
+ end
+ end
+
+ def code_add_argument_loader(function)
+ if (function[:args_string] != "void")
+ if (@arrays)
+ args_string = function[:args].map do |m|
+ type = arg_type_with_const(m)
+ m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
+ end.join(', ')
+ "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string});\n" +
+ "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" +
+ function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1) ) } +
+ "}\n\n"
+ else
+ "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]});\n" +
+ "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" +
+ function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg) } +
+ "}\n\n"
+ end
+ else
+ ""
+ end
+ end
+
+ def code_call_argument_loader(function)
+ if (function[:args_string] != "void")
+ args = function[:args].map do |m|
+ if (@arrays and m[:ptr?] and not m[:array_data?])
+ "#{m[:name]}, 1"
+ elsif (@arrays and m[:array_size?])
+ "#{m[:name]}, #{m[:name]}"
+ else
+ m[:name]
+ end
+ end
+ " CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n"
+ else
+ ""
+ end
+ end
+
+ def ptr_or_str?(arg_type)
+ return (arg_type.include? '*' or
+ @treat_as.fetch(arg_type, "").include? '*')
+ end
+
+ #private ######################
+
+ def lookup_expect_type(function, arg)
+ c_type = arg[:type]
+ arg_name = arg[:name]
+ expected = "cmock_call_instance->Expected_#{arg_name}"
+ ignore = "cmock_call_instance->IgnoreArg_#{arg_name}"
+ unity_func = if ((arg[:ptr?]) and ((c_type =~ /\*\*/) or (@ptr_handling == :compare_ptr)))
+ ['UNITY_TEST_ASSERT_EQUAL_PTR', '']
+ else
+ (@helpers.nil? or @helpers[:unity_helper].nil?) ? ["UNITY_TEST_ASSERT_EQUAL",''] : @helpers[:unity_helper].get_helper(c_type)
+ end
+ return c_type, arg_name, expected, ignore, unity_func[0], unity_func[1]
+ end
+
+ def code_verify_an_arg_expectation_with_no_arrays(function, arg)
+ c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
+ lines = ""
+ lines << " if (!#{ignore})\n" if @ignore_arg
+ lines << " {\n"
+ lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
+ case(unity_func)
+ when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
+ c_type_local = c_type.gsub(/\*$/,'')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
+ when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
+ if (pre == '&')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch); }\n"
+ end
+ when /_ARRAY/
+ if (pre == '&')
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch); }\n"
+ end
+ else
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
+ end
+ lines << " }\n"
+ lines
+ end
+
+ def code_verify_an_arg_expectation_with_normal_arrays(function, arg)
+ c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
+ depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
+ lines = ""
+ lines << " if (!#{ignore})\n" if @ignore_arg
+ lines << " {\n"
+ lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
+ lines << " if (#{pre}#{expected} != #{pre}#{arg_name}) {\n"
+ case(unity_func)
+ when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
+ c_type_local = c_type.gsub(/\*$/,'')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
+ when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
+ if (pre == '&')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ when /_ARRAY/
+ if (pre == '&')
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ else
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
+ end
+ lines << " }\n }\n"
+ lines
+ end
+
+ def code_verify_an_arg_expectation_with_smart_arrays(function, arg)
+ c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
+ depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
+ lines = ""
+ lines << " if (!#{ignore})\n" if @ignore_arg
+ lines << " {\n"
+ lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
+ lines << " if (#{pre}#{expected} != #{pre}#{arg_name}) {\n"
+ case(unity_func)
+ when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
+ c_type_local = c_type.gsub(/\*$/,'')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
+ when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
+ if (pre == '&')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << ((depth_name != 1) ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : "")
+ lines << " else\n"
+ lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ when /_ARRAY/
+ if (pre == '&')
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << ((depth_name != 1) ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : "")
+ lines << " else\n"
+ lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ else
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
+ end
+ lines << " }\n }\n"
+ lines
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb
new file mode 100755
index 00000000..0cf19478
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_header_parser.rb
@@ -0,0 +1,364 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockHeaderParser
+
+ attr_accessor :funcs, :c_attr_noconst, :c_attributes, :treat_as_void, :treat_externs
+
+ def initialize(cfg)
+ @funcs = []
+ @c_strippables = cfg.strippables
+ @c_attr_noconst = cfg.attributes.uniq - ['const']
+ @c_attributes = ['const'] + c_attr_noconst
+ @c_calling_conventions = cfg.c_calling_conventions.uniq
+ @treat_as_array = cfg.treat_as_array
+ @treat_as_void = (['void'] + cfg.treat_as_void).uniq
+ @declaration_parse_matcher = /([\w\s\*\(\),\[\]]+??)\(([\w\s\*\(\),\.\[\]+-]*)\)$/m
+ @standards = (['int','short','char','long','unsigned','signed'] + cfg.treat_as.keys).uniq
+ @array_size_name = cfg.array_size_name
+ @array_size_type = (['int', 'size_t'] + cfg.array_size_type).uniq
+ @when_no_prototypes = cfg.when_no_prototypes
+ @local_as_void = @treat_as_void
+ @verbosity = cfg.verbosity
+ @treat_externs = cfg.treat_externs
+ @c_strippables += ['extern'] if (@treat_externs == :include) #we'll need to remove the attribute if we're allowing externs
+ end
+
+ def parse(name, source)
+ @module_name = name.gsub(/\W/,'')
+ @typedefs = []
+ @funcs = []
+ function_names = []
+
+ parse_functions( import_source(source) ).map do |decl|
+ func = parse_declaration(decl)
+ unless (function_names.include? func[:name])
+ @funcs << func
+ function_names << func[:name]
+ end
+ end
+
+ { :includes => nil,
+ :functions => @funcs,
+ :typedefs => @typedefs
+ }
+ end
+
+ private if $ThisIsOnlyATest.nil? ################
+
+ def import_source(source)
+
+ # let's clean up the encoding in case they've done anything weird with the characters we might find
+ source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil)
+
+ # void must be void for cmock _ExpectAndReturn calls to process properly, not some weird typedef which equates to void
+ # to a certain extent, this action assumes we're chewing on pre-processed header files, otherwise we'll most likely just get stuff from @treat_as_void
+ @local_as_void = @treat_as_void
+ void_types = source.scan(/typedef\s+(?:\(\s*)?void(?:\s*\))?\s+([\w]+)\s*;/)
+ if void_types
+ @local_as_void += void_types.flatten.uniq.compact
+ end
+
+ # smush multiline macros into single line (checking for continuation character at end of line '\')
+ source.gsub!(/\s*\\\s*/m, ' ')
+
+ #remove comments (block and line, in three steps to ensure correct precedence)
+ source.gsub!(/(?<!\*)\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
+ source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
+ source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
+
+ # remove assembler pragma sections
+ source.gsub!(/^\s*#\s*pragma\s+asm\s+.*?#\s*pragma\s+endasm/m, '')
+
+ # remove gcc's __attribute__ tags
+ source.gsub!(/__attribute(?:__)?\s*\(\(+.*\)\)+/, '')
+
+ # remove preprocessor statements and extern "C"
+ source.gsub!(/^\s*#.*/, '')
+ source.gsub!(/extern\s+\"C\"\s*\{/, '')
+
+ # enums, unions, structs, and typedefs can all contain things (e.g. function pointers) that parse like function prototypes, so yank them
+ # forward declared structs are removed before struct definitions so they don't mess up real thing later. we leave structs keywords in function prototypes
+ source.gsub!(/^[\w\s]*struct[^;\{\}\(\)]+;/m, '') # remove forward declared structs
+ source.gsub!(/^[\w\s]*(enum|union|struct|typedef)[\w\s]*\{[^\}]+\}[\w\s\*\,]*;/m, '') # remove struct, union, and enum definitions and typedefs with braces
+ source.gsub!(/(\W)(?:register|auto|static|restrict)(\W)/, '\1\2') # remove problem keywords
+ source.gsub!(/\s*=\s*['"a-zA-Z0-9_\.]+\s*/, '') # remove default value statements from argument lists
+ source.gsub!(/^(?:[\w\s]*\W)?typedef\W[^;]*/m, '') # remove typedef statements
+ source.gsub!(/\)(\w)/, ') \1') # add space between parenthese and alphanumeric
+ source.gsub!(/(^|\W+)(?:#{@c_strippables.join('|')})(?=$|\W+)/,'\1') unless @c_strippables.empty? # remove known attributes slated to be stripped
+
+ #scan standalone function pointers and remove them, because they can just be ignored
+ source.gsub!(/\w+\s*\(\s*\*\s*\w+\s*\)\s*\([^)]*\)\s*;/,';')
+
+ #scan for functions which return function pointers, because they are a pain
+ source.gsub!(/([\w\s\*]+)\(*\(\s*\*([\w\s\*]+)\s*\(([\w\s\*,]*)\)\)\s*\(([\w\s\*,]*)\)\)*/) do |m|
+ functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}"
+ @typedefs << "typedef #{$1.strip}(*#{functype})(#{$4});"
+ "#{functype} #{$2.strip}(#{$3});"
+ end
+
+ # remove nested pairs of braces because no function declarations will be inside of them (leave outer pair for function definition detection)
+ if (RUBY_VERSION.split('.')[0].to_i > 1)
+ #we assign a string first because (no joke) if Ruby 1.9.3 sees this line as a regex, it will crash.
+ r = "\\{([^\\{\\}]*|\\g<0>)*\\}"
+ source.gsub!(/#{r}/m, '{ }')
+ else
+ while source.gsub!(/\{[^\{\}]*\{[^\{\}]*\}[^\{\}]*\}/m, '{ }')
+ end
+ end
+
+ # remove function definitions by stripping off the arguments right now
+ source.gsub!(/\([^\)]*\)\s*\{[^\}]*\}/m, ";")
+
+ #drop extra white space to make the rest go faster
+ source.gsub!(/^\s+/, '') # remove extra white space from beginning of line
+ source.gsub!(/\s+$/, '') # remove extra white space from end of line
+ source.gsub!(/\s*\(\s*/, '(') # remove extra white space from before left parens
+ source.gsub!(/\s*\)\s*/, ')') # remove extra white space from before right parens
+ source.gsub!(/\s+/, ' ') # remove remaining extra white space
+
+ #split lines on semicolons and remove things that are obviously not what we are looking for
+ src_lines = source.split(/\s*;\s*/).uniq
+ src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines
+ src_lines.delete_if {|line| !(line =~ /[\w\s\*]+\(+\s*\*[\*\s]*[\w\s]+(?:\[[\w\s]*\]\s*)+\)+\s*\((?:[\w\s\*]*,?)*\s*\)/).nil?} #remove function pointer arrays
+ if (@treat_externs == :include)
+ src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:inline)\s+/).nil?} # remove inline functions
+ else
+ src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:extern|inline)\s+/).nil?} # remove inline and extern functions
+ end
+ src_lines.delete_if {|line| line.empty? } #drop empty lines
+ end
+
+ def parse_functions(source)
+ funcs = []
+ source.each {|line| funcs << line.strip.gsub(/\s+/, ' ') if (line =~ @declaration_parse_matcher)}
+ if funcs.empty?
+ case @when_no_prototypes
+ when :error
+ raise "ERROR: No function prototypes found!"
+ when :warn
+ puts "WARNING: No function prototypes found!" unless (@verbosity < 1)
+ end
+ end
+ return funcs
+ end
+
+ def parse_type_and_name(arg)
+ # Split up words and remove known attributes. For pointer types, make sure
+ # to remove 'const' only when it applies to the pointer itself, not when it
+ # applies to the type pointed to. For non-pointer types, remove any
+ # occurrence of 'const'.
+ arg.gsub!(/(\w)\*/,'\1 *') # pull asterisks away from preceding word
+ arg.gsub!(/\*(\w)/,'* \1') # pull asterisks away from following word
+ arg_array = arg.split
+ arg_info = divine_ptr_and_const(arg)
+ arg_info[:name] = arg_array[-1]
+
+ attributes = arg.include?('*') ? @c_attr_noconst : @c_attributes
+ attr_array = []
+ type_array = []
+
+ arg_array[0..-2].each do |word|
+ if attributes.include?(word)
+ attr_array << word
+ elsif @c_calling_conventions.include?(word)
+ arg_info[:c_calling_convention] = word
+ else
+ type_array << word
+ end
+ end
+
+ if arg_info[:const_ptr?]
+ attr_array << 'const'
+ type_array.delete_at(type_array.rindex('const'))
+ end
+
+ arg_info[:modifier] = attr_array.join(' ')
+ arg_info[:type] = type_array.join(' ').gsub(/\s+\*/,'*') # remove space before asterisks
+ return arg_info
+ end
+
+ def parse_args(arg_list)
+ args = []
+ arg_list.split(',').each do |arg|
+ arg.strip!
+ return args if (arg =~ /^\s*((\.\.\.)|(void))\s*$/) # we're done if we reach void by itself or ...
+
+ arg_info = parse_type_and_name(arg)
+ arg_info.delete(:modifier) # don't care about this
+ arg_info.delete(:c_calling_convention) # don't care about this
+
+ # in C, array arguments implicitly degrade to pointers
+ # make the translation explicit here to simplify later logic
+ if @treat_as_array[arg_info[:type]] and not arg_info[:ptr?] then
+ arg_info[:type] = "#{@treat_as_array[arg_info[:type]]}*"
+ arg_info[:type] = "const #{arg_info[:type]}" if arg_info[:const?]
+ arg_info[:ptr?] = true
+ end
+
+ args << arg_info
+ end
+
+ # Try to find array pair in parameters following this pattern : <type> * <name>, <@array_size_type> <@array_size_name>
+ args.each_with_index {|val, index|
+ next_index = index + 1
+ if (args.length > next_index)
+ if (val[:ptr?] == true and args[next_index][:name].match(@array_size_name) and @array_size_type.include?(args[next_index][:type]))
+ val[:array_data?] = true
+ args[next_index][:array_size?] = true
+ end
+ end
+ }
+
+ return args
+ end
+
+ def divine_ptr(arg)
+ return false unless arg.include? '*'
+ # treat "const char *" and similar as a string, not a pointer
+ return false if /(^|\s)(const\s+)?char(\s+const)?\s*\*(?!.*\*)/ =~ arg
+ return true
+ end
+
+ def divine_const(arg)
+ # a non-pointer arg containing "const" is a constant
+ # an arg containing "const" before the last * is a pointer to a constant
+ return ( arg.include?('*') ? (/(^|\s|\*)const(\s(\w|\s)*)?\*(?!.*\*)/ =~ arg)
+ : (/(^|\s)const(\s|$)/ =~ arg) ) ? true : false
+ end
+
+ def divine_ptr_and_const(arg)
+ divination = {}
+
+ divination[:ptr?] = divine_ptr(arg)
+ divination[:const?] = divine_const(arg)
+
+ # an arg containing "const" after the last * is a constant pointer
+ divination[:const_ptr?] = (/\*(?!.*\*)\s*const(\s|$)/ =~ arg) ? true : false
+
+ return divination
+ end
+
+ def clean_args(arg_list)
+ if ((@local_as_void.include?(arg_list.strip)) or (arg_list.empty?))
+ return 'void'
+ else
+ c=0
+ arg_list.gsub!(/(\w+)(?:\s*\[\s*\(*[\s\w+-]*\)*\s*\])+/,'*\1') # magically turn brackets into asterisks, also match for parentheses that come from macros
+ arg_list.gsub!(/\s+\*/,'*') # remove space to place asterisks with type (where they belong)
+ arg_list.gsub!(/\*(\w)/,'* \1') # pull asterisks away from arg to place asterisks with type (where they belong)
+
+ #scan argument list for function pointers and replace them with custom types
+ arg_list.gsub!(/([\w\s\*]+)\(+\s*\*[\*\s]*([\w\s]*)\s*\)+\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |m|
+
+ functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}"
+ funcret = $1.strip
+ funcname = $2.strip
+ funcargs = $3.strip
+ funconst = ''
+ if (funcname.include? 'const')
+ funcname.gsub!('const','').strip!
+ funconst = 'const '
+ end
+ @typedefs << "typedef #{funcret}(*#{functype})(#{funcargs});"
+ funcname = "cmock_arg#{c+=1}" if (funcname.empty?)
+ "#{functype} #{funconst}#{funcname}"
+ end
+
+ #automatically name unnamed arguments (those that only had a type)
+ arg_list.split(/\s*,\s*/).map { |arg|
+ parts = (arg.split - ['struct', 'union', 'enum', 'const', 'const*'])
+ if ((parts.size < 2) or (parts[-1][-1].chr == '*') or (@standards.include?(parts[-1])))
+ "#{arg} cmock_arg#{c+=1}"
+ else
+ arg
+ end
+ }.join(', ')
+ end
+ end
+
+ def parse_declaration(declaration)
+ decl = {}
+
+ regex_match = @declaration_parse_matcher.match(declaration)
+ raise "Failed parsing function declaration: '#{declaration}'" if regex_match.nil?
+
+ #grab argument list
+ args = regex_match[2].strip
+
+ #process function attributes, return type, and name
+ parsed = parse_type_and_name(regex_match[1])
+
+ decl[:name] = parsed[:name]
+ decl[:modifier] = parsed[:modifier]
+ unless parsed[:c_calling_convention].nil?
+ decl[:c_calling_convention] = parsed[:c_calling_convention]
+ end
+
+ rettype = parsed[:type]
+ rettype = 'void' if (@local_as_void.include?(rettype.strip))
+ decl[:return] = { :type => rettype,
+ :name => 'cmock_to_return',
+ :str => "#{rettype} cmock_to_return",
+ :void? => (rettype == 'void'),
+ :ptr? => parsed[:ptr?],
+ :const? => parsed[:const?],
+ :const_ptr? => parsed[:const_ptr?]
+ }
+
+ #remove default argument statements from mock definitions
+ args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ')
+
+ #check for var args
+ if (args =~ /\.\.\./)
+ decl[:var_arg] = args.match( /[\w\s]*\.\.\./ ).to_s.strip
+ if (args =~ /\,[\w\s]*\.\.\./)
+ args = args.gsub!(/\,[\w\s]*\.\.\./,'')
+ else
+ args = 'void'
+ end
+ else
+ decl[:var_arg] = nil
+ end
+ args = clean_args(args)
+ decl[:args_string] = args
+ decl[:args] = parse_args(args)
+ decl[:args_call] = decl[:args].map{|a| a[:name]}.join(', ')
+ decl[:contains_ptr?] = decl[:args].inject(false) {|ptr, arg| arg[:ptr?] ? true : ptr }
+
+ if (decl[:return][:type].nil? or decl[:name].nil? or decl[:args].nil? or
+ decl[:return][:type].empty? or decl[:name].empty?)
+ raise "Failed Parsing Declaration Prototype!\n" +
+ " declaration: '#{declaration}'\n" +
+ " modifier: '#{decl[:modifier]}'\n" +
+ " return: #{prototype_inspect_hash(decl[:return])}\n" +
+ " function: '#{decl[:name]}'\n" +
+ " args: #{prototype_inspect_array_of_hashes(decl[:args])}\n"
+ end
+
+ return decl
+ end
+
+ def prototype_inspect_hash(hash)
+ pairs = []
+ hash.each_pair { |name, value| pairs << ":#{name} => #{"'" if (value.class == String)}#{value}#{"'" if (value.class == String)}" }
+ return "{#{pairs.join(', ')}}"
+ end
+
+ def prototype_inspect_array_of_hashes(array)
+ hashes = []
+ array.each { |hash| hashes << prototype_inspect_hash(hash) }
+ case (array.size)
+ when 0
+ return "[]"
+ when 1
+ return "[#{hashes[0]}]"
+ else
+ return "[\n #{hashes.join("\n ")}\n ]\n"
+ end
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_plugin_manager.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_plugin_manager.rb
new file mode 100755
index 00000000..cc5ced2a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_plugin_manager.rb
@@ -0,0 +1,55 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require 'thread'
+
+class CMockPluginManager
+
+ attr_accessor :plugins
+
+ def initialize(config, utils)
+ @plugins = []
+ plugins_to_load = [:expect, config.plugins].flatten.uniq.compact
+ plugins_to_load.each do |plugin|
+ plugin_name = plugin.to_s
+ object_name = "CMockGeneratorPlugin" + camelize(plugin_name)
+ self.class.plugin_require_mutex.synchronize { load_plugin(plugin_name, object_name, config, utils) }
+ end
+ @plugins.sort! {|a,b| a.priority <=> b.priority }
+ end
+
+ def run(method, args=nil)
+ if args.nil?
+ return @plugins.collect{ |plugin| plugin.send(method) if plugin.respond_to?(method) }.flatten.join
+ else
+ return @plugins.collect{ |plugin| plugin.send(method, args) if plugin.respond_to?(method) }.flatten.join
+ end
+ end
+
+ def camelize(lower_case_and_underscored_word)
+ lower_case_and_underscored_word.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
+ end
+
+ private
+
+ def self.plugin_require_mutex
+ @mutex ||= Mutex.new
+ end
+
+ def load_plugin(plugin_name, object_name, config, utils)
+ begin
+ unless (Object.const_defined? object_name)
+ file_name = "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
+ require file_name
+ end
+ class_name = Object.const_get(object_name)
+ @plugins << class_name.new(config, utils)
+ rescue
+ file_name = "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
+ raise "ERROR: CMock unable to load plugin '#{plugin_name}' '#{object_name}' #{file_name}"
+ end
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_unityhelper_parser.rb b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_unityhelper_parser.rb
new file mode 100755
index 00000000..c22db7aa
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/lib/cmock_unityhelper_parser.rb
@@ -0,0 +1,75 @@
+# ==========================================
+# CMock Project - Automatic Mock Generation for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class CMockUnityHelperParser
+
+ attr_accessor :c_types
+
+ def initialize(config)
+ @config = config
+ @fallback = @config.plugins.include?(:array) ? 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY' : 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
+ @c_types = map_C_types.merge(import_source)
+ end
+
+ def get_helper(ctype)
+ lookup = ctype.gsub(/(?:^|(\S?)(\s*)|(\W))const(?:$|(\s*)(\S)|(\W))/,'\1\3\5\6').strip.gsub(/\s+/,'_')
+ return [@c_types[lookup], ''] if (@c_types[lookup])
+ if (lookup =~ /\*$/)
+ lookup = lookup.gsub(/\*$/,'')
+ return [@c_types[lookup], '*'] if (@c_types[lookup])
+ else
+ lookup = lookup + '*'
+ return [@c_types[lookup], '&'] if (@c_types[lookup])
+ end
+ return ['UNITY_TEST_ASSERT_EQUAL_PTR', ''] if (ctype =~ /cmock_\w+_ptr\d+/)
+ raise("Don't know how to test #{ctype} and memory tests are disabled!") unless @config.memcmp_if_unknown
+ return (lookup =~ /\*$/) ? [@fallback, '&'] : [@fallback, '']
+ end
+
+ private ###########################
+
+ def map_C_types
+ c_types = {}
+ @config.treat_as.each_pair do |ctype, expecttype|
+ c_type = ctype.gsub(/\s+/,'_')
+ if (expecttype =~ /\*/)
+ c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype.gsub(/\*/,'')}_ARRAY"
+ else
+ c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}"
+ c_types[c_type+'*'] ||= "UNITY_TEST_ASSERT_EQUAL_#{expecttype}_ARRAY"
+ end
+ end
+ c_types
+ end
+
+ def import_source
+ source = @config.load_unity_helper
+ return {} if source.nil?
+ c_types = {}
+ source = source.gsub(/\/\/.*$/, '') #remove line comments
+ source = source.gsub(/\/\*.*?\*\//m, '') #remove block comments
+
+ #scan for comparison helpers
+ match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+))\s*\(' + Array.new(4,'\s*\w+\s*').join(',') + '\)')
+ pairs = source.scan(match_regex).flatten.compact
+ (pairs.size/2).times do |i|
+ expect = pairs[i*2]
+ ctype = pairs[(i*2)+1]
+ c_types[ctype] = expect unless expect.include?("_ARRAY")
+ end
+
+ #scan for array variants of those helpers
+ match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+_ARRAY))\s*\(' + Array.new(5,'\s*\w+\s*').join(',') + '\)')
+ pairs = source.scan(match_regex).flatten.compact
+ (pairs.size/2).times do |i|
+ expect = pairs[i*2]
+ ctype = pairs[(i*2)+1]
+ c_types[ctype.gsub('_ARRAY','*')] = expect
+ end
+
+ c_types
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/release/build.info b/tinyusb/test/vendor/ceedling/vendor/cmock/release/build.info
new file mode 100755
index 00000000..a62fe117
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/release/build.info
@@ -0,0 +1,2 @@
+217
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/release/version.info b/tinyusb/test/vendor/ceedling/vendor/cmock/release/version.info
new file mode 100755
index 00000000..1b6799f8
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/release/version.info
@@ -0,0 +1,2 @@
+2.4.6
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.c b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.c
new file mode 100755
index 00000000..5e5cb6c7
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.c
@@ -0,0 +1,216 @@
+/* ==========================================
+ CMock Project - Automatic Mock Generation for C
+ Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include "cmock.h"
+
+//public constants to be used by mocks
+const char* CMockStringOutOfMemory = "CMock has run out of memory. Please allocate more.";
+const char* CMockStringCalledMore = "Called more times than expected.";
+const char* CMockStringCalledLess = "Called fewer times than expected.";
+const char* CMockStringCalledEarly = "Called earlier than expected.";
+const char* CMockStringCalledLate = "Called later than expected.";
+const char* CMockStringCallOrder = "Called out of order.";
+const char* CMockStringIgnPreExp = "IgnoreArg called before Expect.";
+const char* CMockStringPtrPreExp = "ReturnThruPtr called before Expect.";
+const char* CMockStringPtrIsNULL = "Pointer is NULL.";
+const char* CMockStringExpNULL = "Expected NULL.";
+const char* CMockStringMismatch = "Function called with unexpected argument value.";
+
+//private variables
+#ifdef CMOCK_MEM_DYNAMIC
+static unsigned char* CMock_Guts_Buffer = NULL;
+static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_ALIGN_SIZE;
+static CMOCK_MEM_INDEX_TYPE CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE;
+#else
+static unsigned char CMock_Guts_Buffer[CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE];
+static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE;
+static CMOCK_MEM_INDEX_TYPE CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE;
+#endif
+
+//-------------------------------------------------------
+// CMock_Guts_MemNew
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size)
+{
+ CMOCK_MEM_INDEX_TYPE index;
+
+ //verify arguments valid (we must be allocating space for at least 1 byte, and the existing chain must be in memory somewhere)
+ if (size < 1)
+ return CMOCK_GUTS_NONE;
+
+ //verify we have enough room
+ size = size + CMOCK_MEM_INDEX_SIZE;
+ if (size & CMOCK_MEM_ALIGN_MASK)
+ size = (size + CMOCK_MEM_ALIGN_MASK) & ~CMOCK_MEM_ALIGN_MASK;
+ if ((CMock_Guts_BufferSize - CMock_Guts_FreePtr) < size)
+ {
+#ifndef CMOCK_MEM_DYNAMIC
+ return CMOCK_GUTS_NONE; // nothing we can do; our static buffer is out of memory
+#else
+ // our dynamic buffer does not have enough room; request more via realloc()
+ CMOCK_MEM_INDEX_TYPE new_buffersize = CMock_Guts_BufferSize + CMOCK_MEM_SIZE + size;
+ unsigned char* new_buffer = realloc(CMock_Guts_Buffer, (size_t)new_buffersize);
+ if (new_buffer == NULL)
+ return CMOCK_GUTS_NONE; // realloc() failed; out of memory
+ CMock_Guts_Buffer = new_buffer;
+ CMock_Guts_BufferSize = new_buffersize;
+#endif
+ }
+
+ //determine where we're putting this new block, and init its pointer to be the end of the line
+ index = CMock_Guts_FreePtr + CMOCK_MEM_INDEX_SIZE;
+ *(CMOCK_MEM_INDEX_TYPE*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]) = CMOCK_GUTS_NONE;
+ CMock_Guts_FreePtr += size;
+
+ return index;
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemChain
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index)
+{
+ CMOCK_MEM_INDEX_TYPE index;
+ void* root;
+ void* obj;
+ void* next;
+
+ if (root_index == CMOCK_GUTS_NONE)
+ {
+ //if there is no root currently, we return this object as the root of the chain
+ return obj_index;
+ }
+ else
+ {
+ //reject illegal nodes
+ if ((root_index < CMOCK_MEM_ALIGN_SIZE) || (root_index >= CMock_Guts_FreePtr))
+ {
+ return CMOCK_GUTS_NONE;
+ }
+ if ((obj_index < CMOCK_MEM_ALIGN_SIZE) || (obj_index >= CMock_Guts_FreePtr))
+ {
+ return CMOCK_GUTS_NONE;
+ }
+
+ root = (void*)(&CMock_Guts_Buffer[root_index]);
+ obj = (void*)(&CMock_Guts_Buffer[obj_index]);
+
+ //find the end of the existing chain and add us
+ next = root;
+ do {
+ index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE);
+ if (index >= CMock_Guts_FreePtr)
+ return CMOCK_GUTS_NONE;
+ if (index > 0)
+ next = (void*)(&CMock_Guts_Buffer[index]);
+ } while (index > 0);
+ *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE) = (CMOCK_MEM_INDEX_TYPE)((CMOCK_MEM_PTR_AS_INT)obj - (CMOCK_MEM_PTR_AS_INT)CMock_Guts_Buffer);
+ return root_index;
+ }
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemNext
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index)
+{
+ CMOCK_MEM_INDEX_TYPE index;
+ void* previous_item;
+
+ //There is nothing "next" if the pointer isn't from our buffer
+ if ((previous_item_index < CMOCK_MEM_ALIGN_SIZE) || (previous_item_index >= CMock_Guts_FreePtr))
+ return CMOCK_GUTS_NONE;
+ previous_item = (void*)(&CMock_Guts_Buffer[previous_item_index]);
+
+ //if the pointer is good, then use it to look up the next index
+ //(we know the first element always goes in zero, so NEXT must always be > 1)
+ index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)previous_item - CMOCK_MEM_INDEX_SIZE);
+ if ((index > 1) && (index < CMock_Guts_FreePtr))
+ return index;
+ else
+ return CMOCK_GUTS_NONE;
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemEndOfChain
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index)
+{
+ CMOCK_MEM_INDEX_TYPE index = root_index;
+ CMOCK_MEM_INDEX_TYPE next_index;
+
+ for (next_index = root_index;
+ next_index != CMOCK_GUTS_NONE;
+ next_index = CMock_Guts_MemNext(index))
+ {
+ index = next_index;
+ }
+
+ return index;
+}
+
+//-------------------------------------------------------
+// CMock_GetAddressFor
+//-------------------------------------------------------
+void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index)
+{
+ if ((index >= CMOCK_MEM_ALIGN_SIZE) && (index < CMock_Guts_FreePtr))
+ {
+ return (void*)(&CMock_Guts_Buffer[index]);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemBytesCapacity
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesCapacity(void)
+{
+ return (sizeof(CMock_Guts_Buffer) - CMOCK_MEM_ALIGN_SIZE);
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemBytesFree
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void)
+{
+ return CMock_Guts_BufferSize - CMock_Guts_FreePtr;
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemBytesUsed
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void)
+{
+ return CMock_Guts_FreePtr - CMOCK_MEM_ALIGN_SIZE;
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemFreeAll
+//-------------------------------------------------------
+void CMock_Guts_MemFreeAll(void)
+{
+ CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; //skip the very beginning
+}
+
+//-------------------------------------------------------
+// CMock_Guts_MemFreeFinal
+//-------------------------------------------------------
+void CMock_Guts_MemFreeFinal(void)
+{
+ CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE;
+#ifdef CMOCK_MEM_DYNAMIC
+ if (CMock_Guts_Buffer)
+ {
+ free(CMock_Guts_Buffer);
+ CMock_Guts_Buffer = NULL;
+ }
+#endif
+}
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.h b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.h
new file mode 100755
index 00000000..e96546da
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock.h
@@ -0,0 +1,40 @@
+/* ==========================================
+ CMock Project - Automatic Mock Generation for C
+ Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef CMOCK_FRAMEWORK_H
+#define CMOCK_FRAMEWORK_H
+
+#include "cmock_internals.h"
+
+#define CMOCK_VERSION_MAJOR 2
+#define CMOCK_VERSION_MINOR 5
+#define CMOCK_VERSION_BUILD 0
+#define CMOCK_VERSION ((CMOCK_VERSION_MAJOR << 16) | (CMOCK_VERSION_MINOR << 8) | CMOCK_VERSION_BUILD)
+
+//should be big enough to index full range of CMOCK_MEM_MAX
+#ifndef CMOCK_MEM_INDEX_TYPE
+#define CMOCK_MEM_INDEX_TYPE unsigned int
+#endif
+
+#define CMOCK_GUTS_NONE (0)
+
+//-------------------------------------------------------
+// Memory API
+//-------------------------------------------------------
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size);
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index);
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index);
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index);
+
+void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index);
+
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesCapacity(void);
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void);
+CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void);
+void CMock_Guts_MemFreeAll(void);
+void CMock_Guts_MemFreeFinal(void);
+
+#endif //CMOCK_FRAMEWORK
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock_internals.h b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock_internals.h
new file mode 100755
index 00000000..ae2e4962
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/cmock_internals.h
@@ -0,0 +1,91 @@
+/* ==========================================
+ CMock Project - Automatic Mock Generation for C
+ Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef CMOCK_FRAMEWORK_INTERNALS_H
+#define CMOCK_FRAMEWORK_INTERNALS_H
+
+#include "unity.h"
+
+//These are constants that the generated mocks have access to
+extern const char* CMockStringOutOfMemory;
+extern const char* CMockStringCalledMore;
+extern const char* CMockStringCalledLess;
+extern const char* CMockStringCalledEarly;
+extern const char* CMockStringCalledLate;
+extern const char* CMockStringCallOrder;
+extern const char* CMockStringIgnPreExp;
+extern const char* CMockStringPtrPreExp;
+extern const char* CMockStringPtrIsNULL;
+extern const char* CMockStringExpNULL;
+extern const char* CMockStringMismatch;
+
+//define CMOCK_MEM_DYNAMIC to grab memory as needed with malloc
+//when you do that, CMOCK_MEM_SIZE is used for incremental size instead of total
+#ifdef CMOCK_MEM_STATIC
+#undef CMOCK_MEM_DYNAMIC
+#endif
+
+#ifdef CMOCK_MEM_DYNAMIC
+#include <stdlib.h>
+#endif
+
+//this is used internally during pointer arithmetic. make sure this type is the same size as the target's pointer type
+#ifndef CMOCK_MEM_PTR_AS_INT
+#ifdef UNITY_POINTER_WIDTH
+#ifdef UNITY_INT_WIDTH
+#if UNITY_POINTER_WIDTH == UNITY_INT_WIDTH
+#define CMOCK_MEM_PTR_AS_INT unsigned int
+#endif
+#endif
+#endif
+#endif
+
+#ifndef CMOCK_MEM_PTR_AS_INT
+#ifdef UNITY_POINTER_WIDTH
+#ifdef UNITY_LONG_WIDTH
+#if UNITY_POINTER_WIDTH == UNITY_LONG_WIDTH
+#define CMOCK_MEM_PTR_AS_INT unsigned long
+#endif
+#if UNITY_POINTER_WIDTH > UNITY_LONG_WIDTH
+#define CMOCK_MEM_PTR_AS_INT unsigned long long
+#endif
+#endif
+#endif
+#endif
+
+#ifndef CMOCK_MEM_PTR_AS_INT
+#define CMOCK_MEM_PTR_AS_INT unsigned long
+#endif
+
+//0 for no alignment, 1 for 16-bit, 2 for 32-bit, 3 for 64-bit
+#ifndef CMOCK_MEM_ALIGN
+ #ifdef UNITY_LONG_WIDTH
+ #if (UNITY_LONG_WIDTH == 16)
+ #define CMOCK_MEM_ALIGN (1)
+ #elif (UNITY_LONG_WIDTH == 32)
+ #define CMOCK_MEM_ALIGN (2)
+ #elif (UNITY_LONG_WIDTH == 64)
+ #define CMOCK_MEM_ALIGN (3)
+ #else
+ #define CMOCK_MEM_ALIGN (2)
+ #endif
+ #else
+ #define CMOCK_MEM_ALIGN (2)
+ #endif
+#endif
+
+//amount of memory to allow cmock to use in its internal heap
+#ifndef CMOCK_MEM_SIZE
+#define CMOCK_MEM_SIZE (32768)
+#endif
+
+//automatically calculated defs for easier reading
+#define CMOCK_MEM_ALIGN_SIZE (CMOCK_MEM_INDEX_TYPE)(1u << CMOCK_MEM_ALIGN)
+#define CMOCK_MEM_ALIGN_MASK (CMOCK_MEM_INDEX_TYPE)(CMOCK_MEM_ALIGN_SIZE - 1)
+#define CMOCK_MEM_INDEX_SIZE (CMOCK_MEM_INDEX_TYPE)(CMOCK_MEM_PTR_AS_INT)((sizeof(CMOCK_MEM_INDEX_TYPE) > CMOCK_MEM_ALIGN_SIZE) ? sizeof(CMOCK_MEM_INDEX_TYPE) : CMOCK_MEM_ALIGN_SIZE)
+
+
+#endif //CMOCK_FRAMEWORK_INTERNALS
diff --git a/tinyusb/test/vendor/ceedling/vendor/cmock/src/meson.build b/tinyusb/test/vendor/ceedling/vendor/cmock/src/meson.build
new file mode 100755
index 00000000..e375e81a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/cmock/src/meson.build
@@ -0,0 +1,17 @@
+###################################################################################
+# #
+# NAME: meson.build #
+# #
+# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams. #
+# WRITTEN BY: Michael Brockus. #
+# #
+# License: MIT #
+# #
+###################################################################################
+
+cmock_dir = include_directories('.')
+
+cmock_lib = static_library(meson.project_name(),
+ sources: ['cmock.c'],
+ dependencies: [unity_dep],
+ include_directories: cmock_dir)
diff --git a/tinyusb/test/vendor/ceedling/vendor/deep_merge/lib/deep_merge.rb b/tinyusb/test/vendor/ceedling/vendor/deep_merge/lib/deep_merge.rb
new file mode 100755
index 00000000..4c4b7610
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/deep_merge/lib/deep_merge.rb
@@ -0,0 +1,211 @@
+module DeepMerge
+
+ MAJOR_VERSION = 0
+ MINOR_VERSION = 1
+ FIX_VERSION = 0
+ VERSION = "#{MAJOR_VERSION}.#{MINOR_VERSION}.#{FIX_VERSION}"
+
+ class InvalidParameter < StandardError; end
+
+ DEFAULT_FIELD_KNOCKOUT_PREFIX = '--'
+
+ module DeepMergeHash
+ # ko_hash_merge! will merge and knockout elements prefixed with DEFAULT_FIELD_KNOCKOUT_PREFIX
+ def ko_deep_merge!(source, options = {})
+ default_opts = {:knockout_prefix => "--", :preserve_unmergeables => false}
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
+ end
+
+ # deep_merge! will merge and overwrite any unmergeables in destination hash
+ def deep_merge!(source, options = {})
+ default_opts = {:preserve_unmergeables => false}
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
+ end
+
+ # deep_merge will merge and skip any unmergeables in destination hash
+ def deep_merge(source, options = {})
+ default_opts = {:preserve_unmergeables => true}
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
+ end
+
+ end # DeepMergeHashExt
+
+ # Deep Merge core documentation.
+ # deep_merge! method permits merging of arbitrary child elements. The two top level
+ # elements must be hashes. These hashes can contain unlimited (to stack limit) levels
+ # of child elements. These child elements to not have to be of the same types.
+ # Where child elements are of the same type, deep_merge will attempt to merge them together.
+ # Where child elements are not of the same type, deep_merge will skip or optionally overwrite
+ # the destination element with the contents of the source element at that level.
+ # So if you have two hashes like this:
+ # source = {:x => [1,2,3], :y => 2}
+ # dest = {:x => [4,5,'6'], :y => [7,8,9]}
+ # dest.deep_merge!(source)
+ # Results: {:x => [1,2,3,4,5,'6'], :y => 2}
+ # By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
+ # To avoid this, use "deep_merge" (no bang/exclamation mark)
+ #
+ # Options:
+ # Options are specified in the last parameter passed, which should be in hash format:
+ # hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
+ # :preserve_unmergeables DEFAULT: false
+ # Set to true to skip any unmergeable elements from source
+ # :knockout_prefix DEFAULT: nil
+ # Set to string value to signify prefix which deletes elements from existing element
+ # :sort_merged_arrays DEFAULT: false
+ # Set to true to sort all arrays that are merged together
+ # :unpack_arrays DEFAULT: nil
+ # Set to string value to run "Array::join" then "String::split" against all arrays
+ # :merge_debug DEFAULT: false
+ # Set to true to get console output of merge process for debugging
+ #
+ # Selected Options Details:
+ # :knockout_prefix => The purpose of this is to provide a way to remove elements
+ # from existing Hash by specifying them in a special way in incoming hash
+ # source = {:x => ['--1', '2']}
+ # dest = {:x => ['1', '3']}
+ # dest.ko_deep_merge!(source)
+ # Results: {:x => ['2','3']}
+ # Additionally, if the knockout_prefix is passed alone as a string, it will cause
+ # the entire element to be removed:
+ # source = {:x => '--'}
+ # dest = {:x => [1,2,3]}
+ # dest.ko_deep_merge!(source)
+ # Results: {:x => ""}
+ # :unpack_arrays => The purpose of this is to permit compound elements to be passed
+ # in as strings and to be converted into discrete array elements
+ # irsource = {:x => ['1,2,3', '4']}
+ # dest = {:x => ['5','6','7,8']}
+ # dest.deep_merge!(source, {:unpack_arrays => ','})
+ # Results: {:x => ['1','2','3','4','5','6','7','8'}
+ # Why: If receiving data from an HTML form, this makes it easy for a checkbox
+ # to pass multiple values from within a single HTML element
+ #
+ # There are many tests for this library - and you can learn more about the features
+ # and usages of deep_merge! by just browsing the test examples
+ def DeepMerge.deep_merge!(source, dest, options = {})
+ # turn on this line for stdout debugging text
+ merge_debug = options[:merge_debug] || false
+ overwrite_unmergeable = !options[:preserve_unmergeables]
+ knockout_prefix = options[:knockout_prefix] || nil
+ if knockout_prefix == "" then raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!"; end
+ if knockout_prefix && !overwrite_unmergeable then raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!"; end
+ # if present: we will split and join arrays on this char before merging
+ array_split_char = options[:unpack_arrays] || false
+ # request that we sort together any arrays when they are merged
+ sort_merged_arrays = options[:sort_merged_arrays] || false
+ di = options[:debug_indent] || ''
+ # do nothing if source is nil
+ if source.nil? || (source.respond_to?(:blank?) && source.blank?) then return dest; end
+ # if dest doesn't exist, then simply copy source to it
+ if dest.nil? && overwrite_unmergeable then dest = source; return dest; end
+
+ puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
+ if source.kind_of?(Hash)
+ puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
+ source.each do |src_key, src_value|
+ if dest.kind_of?(Hash)
+ puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
+ if not dest[src_key].nil?
+ puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
+ dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + ' '))
+ else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
+ puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
+ # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
+ begin
+ src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
+ rescue TypeError
+ src_dup = src_value
+ end
+ dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + ' '))
+ end
+ else # dest isn't a hash, so we overwrite it completely (if permitted)
+ if overwrite_unmergeable
+ puts "#{di} overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over-> #{dest.inspect}" if merge_debug
+ dest = overwrite_unmergeables(source, dest, options)
+ end
+ end
+ end
+ elsif source.kind_of?(Array)
+ puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
+ # if we are instructed, join/split any source arrays before processing
+ if array_split_char
+ puts "#{di} split/join on source: #{source.inspect}" if merge_debug
+ source = source.join(array_split_char).split(array_split_char)
+ if dest.kind_of?(Array) then dest = dest.join(array_split_char).split(array_split_char); end
+ end
+ # if there's a naked knockout_prefix in source, that means we are to truncate dest
+ if source.index(knockout_prefix) then dest = clear_or_nil(dest); source.delete(knockout_prefix); end
+ if dest.kind_of?(Array)
+ if knockout_prefix
+ print "#{di} knocking out: " if merge_debug
+ # remove knockout prefix items from both source and dest
+ source.delete_if do |ko_item|
+ retval = false
+ item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
+ if item != ko_item
+ print "#{ko_item} - " if merge_debug
+ dest.delete(item)
+ dest.delete(ko_item)
+ retval = true
+ end
+ retval
+ end
+ puts if merge_debug
+ end
+ puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
+ dest = dest | source
+ if sort_merged_arrays then dest.sort!; end
+ elsif overwrite_unmergeable
+ puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
+ dest = overwrite_unmergeables(source, dest, options)
+ end
+ else # src_hash is not an array or hash, so we'll have to overwrite dest
+ puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
+ dest = overwrite_unmergeables(source, dest, options)
+ end
+ puts "#{di}Returning #{dest.inspect}" if merge_debug
+ dest
+ end # deep_merge!
+
+ # allows deep_merge! to uniformly handle overwriting of unmergeable entities
+ def DeepMerge::overwrite_unmergeables(source, dest, options)
+ merge_debug = options[:merge_debug] || false
+ overwrite_unmergeable = !options[:preserve_unmergeables]
+ knockout_prefix = options[:knockout_prefix] || false
+ di = options[:debug_indent] || ''
+ if knockout_prefix && overwrite_unmergeable
+ if source.kind_of?(String) # remove knockout string from source before overwriting dest
+ src_tmp = source.gsub(%r{^#{knockout_prefix}},"")
+ elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest
+ src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) }
+ else
+ src_tmp = source
+ end
+ if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest
+ puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug
+ dest = src_tmp
+ else # if we do find a knockout_prefix, then we just delete dest
+ puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug
+ dest = ""
+ end
+ elsif overwrite_unmergeable
+ dest = source
+ end
+ dest
+ end
+
+ def DeepMerge::clear_or_nil(obj)
+ if obj.respond_to?(:clear)
+ obj.clear
+ else
+ obj = nil
+ end
+ obj
+ end
+
+end # module DeepMerge
+
+class Hash
+ include DeepMerge::DeepMergeHash
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy.rb b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy.rb
new file mode 100755
index 00000000..581afc7e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy.rb
@@ -0,0 +1,403 @@
+require 'diy/factory.rb'
+require 'yaml'
+require 'set'
+
+module DIY #:nodoc:#
+ VERSION = '1.1.2'
+ class Context
+
+ class << self
+ # Enable / disable automatic requiring of libraries. Default: true
+ attr_accessor :auto_require
+ end
+ @auto_require = true
+
+ # Accepts a Hash defining the object context (usually loaded from objects.yml), and an additional
+ # Hash containing objects to inject into the context.
+ def initialize(context_hash, extra_inputs={})
+ raise "Nil context hash" unless context_hash
+ raise "Need a hash" unless context_hash.kind_of?(Hash)
+ [ "[]", "keys" ].each do |mname|
+ unless extra_inputs.respond_to?(mname)
+ raise "Extra inputs must respond to hash-like [] operator and methods #keys and #each"
+ end
+ end
+
+ # store extra inputs
+ if extra_inputs.kind_of?(Hash)
+ @extra_inputs= {}
+ extra_inputs.each { |k,v| @extra_inputs[k.to_s] = v } # smooth out the names
+ else
+ @extra_inputs = extra_inputs
+ end
+
+ collect_object_and_subcontext_defs context_hash
+
+ # init the cache
+ @cache = {}
+ @cache['this_context'] = self
+ end
+
+
+ # Convenience: create a new DIY::Context by loading from a String (or open file handle.)
+ def self.from_yaml(io_or_string, extra_inputs={})
+ raise "nil input to YAML" unless io_or_string
+ Context.new(YAML.load(io_or_string), extra_inputs)
+ end
+
+ # Convenience: create a new DIY::Context by loading from the named file.
+ def self.from_file(fname, extra_inputs={})
+ raise "nil file name" unless fname
+ self.from_yaml(File.read(fname), extra_inputs)
+ end
+
+ # Return a reference to the object named. If necessary, the object will
+ # be instantiated on first use. If the object is non-singleton, a new
+ # object will be produced each time.
+ def get_object(obj_name)
+ key = obj_name.to_s
+ obj = @cache[key]
+ unless obj
+ if extra_inputs_has(key)
+ obj = @extra_inputs[key]
+ else
+ case @defs[key]
+ when MethodDef
+ obj = construct_method(key)
+ when FactoryDef
+ obj = construct_factory(key)
+ @cache[key] = obj
+ else
+ obj = construct_object(key)
+ @cache[key] = obj if @defs[key].singleton?
+ end
+ end
+ end
+ obj
+ end
+ alias :[] :get_object
+
+ # Inject a named object into the Context. This must be done before the Context has instantiated the
+ # object in question.
+ def set_object(obj_name,obj)
+ key = obj_name.to_s
+ raise "object '#{key}' already exists in context" if @cache.keys.include?(key)
+ @cache[key] = obj
+ end
+ alias :[]= :set_object
+
+ # Provide a listing of object names
+ def keys
+ (@defs.keys.to_set + @extra_inputs.keys.to_set).to_a
+ end
+
+ # Instantiate and yield the named subcontext
+ def within(sub_context_name)
+ # Find the subcontext definitaion:
+ context_def = @sub_context_defs[sub_context_name.to_s]
+ raise "No sub-context named #{sub_context_name}" unless context_def
+ # Instantiate a new context using self as parent:
+ context = Context.new( context_def, self )
+
+ yield context
+ end
+
+ # Returns true if the context contains an object with the given name
+ def contains_object(obj_name)
+ key = obj_name.to_s
+ @defs.keys.member?(key) or extra_inputs_has(key)
+ end
+
+ # Every top level object in the Context is instantiated. This is especially useful for
+ # systems that have "floating observers"... objects that are never directly accessed, who
+ # would thus never be instantiated by coincedence. This does not build any subcontexts
+ # that may exist.
+ def build_everything
+ @defs.keys.each { |k| self[k] }
+ end
+ alias :build_all :build_everything
+ alias :preinstantiate_singletons :build_everything
+
+ private
+
+ def collect_object_and_subcontext_defs(context_hash)
+ @defs = {}
+ @sub_context_defs = {}
+ get_defs_from context_hash
+ end
+
+ def get_defs_from(hash, namespace=nil)
+ hash.each do |name,info|
+ # we modify the info hash below so it's important to have a new
+ # instance to play with
+ info = info.dup if info
+
+ # see if we are building a factory
+ if info and info.has_key?('builds')
+ unless info.has_key?('auto_require')
+ info['auto_require'] = self.class.auto_require
+ end
+
+ if namespace
+ info['builds'] = namespace.build_classname(info['builds'])
+ end
+ @defs[name] = FactoryDef.new({:name => name,
+ :target => info['builds'],
+ :library => info['library'],
+ :auto_require => info['auto_require']})
+ next
+ end
+
+ name = name.to_s
+ case name
+ when /^\+/
+ # subcontext
+ @sub_context_defs[name.gsub(/^\+/,'')] = info
+
+ when /^using_namespace/
+ # namespace: use a module(s) prefix for the classname of contained object defs
+ # NOTE: namespacing is NOT scope... it's just a convenient way to setup class names for a group of objects.
+ get_defs_from info, parse_namespace(name)
+ when /^method\s/
+ key_name = name.gsub(/^method\s/, "")
+ @defs[key_name] = MethodDef.new(:name => key_name,
+ :object => info['object'],
+ :method => info['method'],
+ :attach => info['attach'])
+ else
+ # Normal object def
+ info ||= {}
+ if extra_inputs_has(name)
+ raise ConstructionError.new(name, "Object definition conflicts with parent context")
+ end
+ unless info.has_key?('auto_require')
+ info['auto_require'] = self.class.auto_require
+ end
+ if namespace
+ if info['class']
+ info['class'] = namespace.build_classname(info['class'])
+ else
+ info['class'] = namespace.build_classname(name)
+ end
+ end
+
+ @defs[name] = ObjectDef.new(:name => name, :info => info)
+
+ end
+ end
+ end
+
+ def construct_method(key)
+ method_definition = @defs[key]
+ object = get_object(method_definition.object)
+ method = object.method(method_definition.method)
+
+ unless method_definition.attach.nil?
+ instance_var_name = "@__diy_#{method_definition.object}"
+
+ method_definition.attach.each do |object_key|
+ get_object(object_key).instance_eval do
+ instance_variable_set(instance_var_name, object)
+ eval %|def #{key}(*args)
+ #{instance_var_name}.#{method_definition.method}(*args)
+ end|
+ end
+ end
+ end
+
+ return method
+ rescue Exception => oops
+ build_and_raise_construction_error(key, oops)
+ end
+
+ def construct_object(key)
+ # Find the object definition
+ obj_def = @defs[key]
+ raise "No object definition for '#{key}'" unless obj_def
+ # If object def mentions a library, load it
+ require obj_def.library if obj_def.library
+
+ # Resolve all components for the object
+ arg_hash = {}
+ obj_def.components.each do |name,value|
+ case value
+ when Lookup
+ arg_hash[name.to_sym] = get_object(value.name)
+ when StringValue
+ arg_hash[name.to_sym] = value.literal_value
+ else
+ raise "Cannot cope with component definition '#{value.inspect}'"
+ end
+ end
+ # Get a reference to the class for the object
+ big_c = get_class_for_name_with_module_delimeters(obj_def.class_name)
+ # Make and return the instance
+ if obj_def.use_class_directly?
+ return big_c
+ elsif arg_hash.keys.size > 0
+ return big_c.new(arg_hash)
+ else
+ return big_c.new
+ end
+ rescue Exception => oops
+ build_and_raise_construction_error(key, oops)
+ end
+
+ def build_and_raise_construction_error(key, oops)
+ cerr = ConstructionError.new(key,oops)
+ cerr.set_backtrace(oops.backtrace)
+ raise cerr
+ end
+
+ def get_class_for_name_with_module_delimeters(class_name)
+ class_name.split(/::/).inject(Object) do |mod,const_name| mod.const_get(const_name) end
+ end
+
+ def extra_inputs_has(key)
+ if key.nil? or key.strip == ''
+ raise ArgumentError.new("Cannot lookup objects with nil keys")
+ end
+ @extra_inputs.keys.member?(key) or @extra_inputs.keys.member?(key.to_sym)
+ end
+
+ def parse_namespace(str)
+ Namespace.new(str)
+ end
+ end
+
+ class Namespace #:nodoc:#
+ def initialize(str)
+ # 'using_namespace Animal Reptile'
+ parts = str.split(/\s+/)
+ raise "Namespace definitions must begin with 'using_namespace'" unless parts[0] == 'using_namespace'
+ parts.shift
+
+ if parts.length > 0 and parts[0] =~ /::/
+ parts = parts[0].split(/::/)
+ end
+
+ raise NamespaceError, "Namespace needs to indicate a module" if parts.empty?
+
+ @module_nest = parts
+ end
+
+ def build_classname(name)
+ [ @module_nest, Infl.camelize(name) ].flatten.join("::")
+ end
+ end
+
+ class Lookup #:nodoc:
+ attr_reader :name
+ def initialize(obj_name)
+ @name = obj_name
+ end
+ end
+
+ class MethodDef #:nodoc:
+ attr_accessor :name, :object, :method, :attach
+
+ def initialize(opts)
+ @name, @object, @method, @attach = opts[:name], opts[:object], opts[:method], opts[:attach]
+ end
+ end
+
+ class ObjectDef #:nodoc:
+ attr_accessor :name, :class_name, :library, :components
+ def initialize(opts)
+ name = opts[:name]
+ raise "Can't make an ObjectDef without a name" if name.nil?
+
+ info = opts[:info] || {}
+ info = info.clone
+
+ @components = {}
+
+ # Object name
+ @name = name
+
+ # Class name
+ @class_name = info.delete 'class'
+ @class_name ||= info.delete 'type'
+ @class_name ||= Infl.camelize(@name)
+
+ # Auto Require
+ @auto_require = info.delete 'auto_require'
+
+ # Library
+ @library = info.delete 'library'
+ @library ||= info.delete 'lib'
+ @library ||= Infl.underscore(@class_name) if @auto_require
+
+ # Use Class Directly
+ @use_class_directly = info.delete 'use_class_directly'
+
+ # Auto-compose
+ compose = info.delete 'compose'
+ if compose
+ case compose
+ when Array
+ auto_names = compose.map { |x| x.to_s }
+ when String
+ auto_names = compose.split(',').map { |x| x.to_s.strip }
+ when Symbol
+ auto_names = [ compose.to_s ]
+ else
+ raise "Cannot auto compose object #{@name}, bad 'compose' format: #{compose.inspect}"
+ end
+ end
+ auto_names ||= []
+ auto_names.each do |cname|
+ @components[cname] = Lookup.new(cname)
+ end
+
+ # Singleton status
+ if info['singleton'].nil?
+ @singleton = true
+ else
+ @singleton = info['singleton']
+ end
+ info.delete 'singleton'
+
+ # Remaining keys
+ info.each do |key,val|
+ @components[key.to_s] = Lookup.new(val.to_s)
+ end
+
+ end
+
+ def singleton?
+ @singleton
+ end
+
+ def use_class_directly?
+ @use_class_directly == true
+ end
+
+ end
+
+ class ConstructionError < RuntimeError #:nodoc:#
+ def initialize(object_name, cause=nil)
+ object_name = object_name
+ cause = cause
+ m = "Failed to construct '#{object_name}'"
+ if cause
+ m << "\n ...caused by:\n >>> #{cause}"
+ end
+ super m
+ end
+ end
+
+ class NamespaceError < RuntimeError #:nodoc:#
+ end
+
+ module Infl #:nodoc:#
+ # Ganked this from Inflector:
+ def self.camelize(lower_case_and_underscored_word)
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
+ end
+ # Ganked this from Inflector:
+ def self.underscore(camel_cased_word)
+ camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
+ end
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy/factory.rb b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy/factory.rb
new file mode 100755
index 00000000..d2566c5d
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/diy/lib/diy/factory.rb
@@ -0,0 +1,36 @@
+module DIY #:nodoc:#
+ class FactoryDef #:nodoc:
+ attr_accessor :name, :target, :class_name, :library
+
+ def initialize(opts)
+ @name, @target, @library, @auto_require =
+ opts[:name], opts[:target], opts[:library], opts[:auto_require]
+
+ @class_name = Infl.camelize(@target)
+ @library ||= Infl.underscore(@class_name) if @auto_require
+ end
+ end
+
+ class Context
+ def construct_factory(key)
+ factory_def = @defs[key]
+# puts "requiring #{factory_def.library}"
+ require factory_def.library if factory_def.library
+
+ big_c = get_class_for_name_with_module_delimeters(factory_def.class_name)
+
+ FactoryFactory.new(big_c)
+ end
+ end
+
+ class FactoryFactory
+ def initialize(clazz)
+ @class_to_create = clazz
+ end
+
+ def create(*args)
+ @class_to_create.new(*args)
+ end
+ end
+end
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_prompt.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_prompt.rb
new file mode 100755
index 00000000..85cbfd80
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_prompt.rb
@@ -0,0 +1,119 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+if RUBY_PLATFORM =~ /(win|w)32$/
+ begin
+ require 'Win32API'
+ rescue LoadError
+ puts 'ERROR! "Win32API" library not found'
+ puts '"Win32API" is required for colour on a windows machine'
+ puts ' try => "gem install Win32API" on the command line'
+ puts
+ end
+ # puts
+ # puts 'Windows Environment Detected...'
+ # puts 'Win32API Library Found.'
+ # puts
+end
+
+class ColourCommandLine
+ def initialize
+ return unless RUBY_PLATFORM =~ /(win|w)32$/
+
+ get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
+ @set_console_txt_attrb =
+ Win32API.new('kernel32', 'SetConsoleTextAttribute', %w[L N], 'I')
+ @hout = get_std_handle.call(-11)
+ end
+
+ def change_to(new_colour)
+ if RUBY_PLATFORM =~ /(win|w)32$/
+ @set_console_txt_attrb.call(@hout, win32_colour(new_colour))
+ else
+ "\033[30;#{posix_colour(new_colour)};22m"
+ end
+ end
+
+ def win32_colour(colour)
+ case colour
+ when :black then 0
+ when :dark_blue then 1
+ when :dark_green then 2
+ when :dark_cyan then 3
+ when :dark_red then 4
+ when :dark_purple then 5
+ when :dark_yellow, :narrative then 6
+ when :default_white, :default, :dark_white then 7
+ when :silver then 8
+ when :blue then 9
+ when :green, :success then 10
+ when :cyan, :output then 11
+ when :red, :failure then 12
+ when :purple then 13
+ when :yellow then 14
+ when :white then 15
+ else
+ 0
+ end
+ end
+
+ def posix_colour(colour)
+ # ANSI Escape Codes - Foreground colors
+ # | Code | Color |
+ # | 39 | Default foreground color |
+ # | 30 | Black |
+ # | 31 | Red |
+ # | 32 | Green |
+ # | 33 | Yellow |
+ # | 34 | Blue |
+ # | 35 | Magenta |
+ # | 36 | Cyan |
+ # | 37 | Light gray |
+ # | 90 | Dark gray |
+ # | 91 | Light red |
+ # | 92 | Light green |
+ # | 93 | Light yellow |
+ # | 94 | Light blue |
+ # | 95 | Light magenta |
+ # | 96 | Light cyan |
+ # | 97 | White |
+
+ case colour
+ when :black then 30
+ when :red, :failure then 31
+ when :green, :success then 32
+ when :yellow then 33
+ when :blue, :narrative then 34
+ when :purple, :magenta then 35
+ when :cyan, :output then 36
+ when :white, :default_white then 37
+ when :default then 39
+ else
+ 39
+ end
+ end
+
+ def out_c(mode, colour, str)
+ case RUBY_PLATFORM
+ when /(win|w)32$/
+ change_to(colour)
+ $stdout.puts str if mode == :puts
+ $stdout.print str if mode == :print
+ change_to(:default_white)
+ else
+ $stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts
+ $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print
+ end
+ end
+end
+
+def colour_puts(role, str)
+ ColourCommandLine.new.out_c(:puts, role, str)
+end
+
+def colour_print(role, str)
+ ColourCommandLine.new.out_c(:print, role, str)
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_reporter.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_reporter.rb
new file mode 100755
index 00000000..1c3bc216
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/colour_reporter.rb
@@ -0,0 +1,39 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require_relative 'colour_prompt'
+
+$colour_output = true
+
+def report(message)
+ if !$colour_output
+ $stdout.puts(message)
+ else
+ message = message.join('\n') if message.class == Array
+ message.each_line do |line|
+ line.chomp!
+ colour = case line
+ when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i
+ Regexp.last_match(1).to_i.zero? ? :green : :red
+ when /PASS/
+ :green
+ when /^OK$/
+ :green
+ when /(?:FAIL|ERROR)/
+ :red
+ when /IGNORE/
+ :yellow
+ when /^(?:Creating|Compiling|Linking)/
+ :white
+ else
+ :silver
+ end
+ colour_puts(colour, line)
+ end
+ end
+ $stdout.flush
+ $stderr.flush
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_config.yml b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_config.yml
new file mode 100755
index 00000000..4a5e4742
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_config.yml
@@ -0,0 +1,36 @@
+#this is a sample configuration file for generate_module
+#you would use it by calling generate_module with the -ygenerate_config.yml option
+#files like this are useful for customizing generate_module to your environment
+:generate_module:
+ :defaults:
+ #these defaults are used in place of any missing options at the command line
+ :path_src: ../src/
+ :path_inc: ../src/
+ :path_tst: ../test/
+ :update_svn: true
+ :includes:
+ #use [] for no additional includes, otherwise list the includes on separate lines
+ :src:
+ - Defs.h
+ - Board.h
+ :inc: []
+ :tst:
+ - Defs.h
+ - Board.h
+ - Exception.h
+ :boilerplates:
+ #these are inserted at the top of generated files.
+ #just comment out or remove if not desired.
+ #use %1$s where you would like the file name to appear (path/extension not included)
+ :src: |
+ //-------------------------------------------
+ // %1$s.c
+ //-------------------------------------------
+ :inc: |
+ //-------------------------------------------
+ // %1$s.h
+ //-------------------------------------------
+ :tst: |
+ //-------------------------------------------
+ // Test%1$s.c : Units tests for %1$s.c
+ //-------------------------------------------
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_module.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_module.rb
new file mode 100755
index 00000000..eb2cebd4
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_module.rb
@@ -0,0 +1,309 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+# This script creates all the files with start code necessary for a new module.
+# A simple module only requires a source file, header file, and test file.
+# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware).
+
+require 'rubygems'
+require 'fileutils'
+require 'pathname'
+
+# TEMPLATE_TST
+TEMPLATE_TST ||= '#include "unity.h"
+
+%2$s#include "%1$s.h"
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_%1$s_NeedToImplement(void)
+{
+ TEST_IGNORE_MESSAGE("Need to Implement %1$s");
+}
+'.freeze
+
+# TEMPLATE_SRC
+TEMPLATE_SRC ||= '%2$s#include "%1$s.h"
+'.freeze
+
+# TEMPLATE_INC
+TEMPLATE_INC ||= '#ifndef %3$s_H
+#define %3$s_H
+%2$s
+
+#endif // %3$s_H
+'.freeze
+
+class UnityModuleGenerator
+ ############################
+ def initialize(options = nil)
+ @options = UnityModuleGenerator.default_options
+ case options
+ when NilClass then @options
+ when String then @options.merge!(UnityModuleGenerator.grab_config(options))
+ when Hash then @options.merge!(options)
+ else raise 'If you specify arguments, it should be a filename or a hash of options'
+ end
+
+ # Create default file paths if none were provided
+ @options[:path_src] = "#{__dir__}/../src/" if @options[:path_src].nil?
+ @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil?
+ @options[:path_tst] = "#{__dir__}/../test/" if @options[:path_tst].nil?
+ @options[:path_src] += '/' unless @options[:path_src][-1] == 47
+ @options[:path_inc] += '/' unless @options[:path_inc][-1] == 47
+ @options[:path_tst] += '/' unless @options[:path_tst][-1] == 47
+
+ # Built in patterns
+ @patterns = {
+ 'src' => {
+ '' => { inc: [] }
+ },
+ 'test' => {
+ '' => { inc: [] }
+ },
+ 'dh' => {
+ 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h')] },
+ 'Hardware' => { inc: [] }
+ },
+ 'dih' => {
+ 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] },
+ 'Interrupt' => { inc: [create_filename('%1$s', 'Hardware.h')] },
+ 'Hardware' => { inc: [] }
+ },
+ 'mch' => {
+ 'Model' => { inc: [] },
+ 'Conductor' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] },
+ 'Hardware' => { inc: [] }
+ },
+ 'mvp' => {
+ 'Model' => { inc: [] },
+ 'Presenter' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] },
+ 'View' => { inc: [] }
+ }
+ }
+ end
+
+ ############################
+ def self.default_options
+ {
+ pattern: 'src',
+ includes: {
+ src: [],
+ inc: [],
+ tst: []
+ },
+ update_svn: false,
+ boilerplates: {},
+ test_prefix: 'Test',
+ mock_prefix: 'Mock'
+ }
+ end
+
+ ############################
+ def self.grab_config(config_file)
+ options = default_options
+ unless config_file.nil? || config_file.empty?
+ require 'yaml'
+ yaml_guts = YAML.load_file(config_file)
+ options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
+ raise "No :unity or :cmock section found in #{config_file}" unless options
+ end
+ options
+ end
+
+ ############################
+ def files_to_operate_on(module_name, pattern = nil)
+ # strip any leading path information from the module name and save for later
+ subfolder = File.dirname(module_name)
+ module_name = File.basename(module_name)
+
+ # create triad definition
+ prefix = @options[:test_prefix] || 'Test'
+ triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] },
+ { ext: '.h', path: @options[:path_inc], prefix: '', template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] },
+ { ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst] }]
+
+ # prepare the pattern for use
+ pattern = (pattern || @options[:pattern] || 'src').downcase
+ patterns = @patterns[pattern]
+ raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil?
+
+ # single file patterns (currently just 'test') can reject the other parts of the triad
+ triad.select! { |v| v[:inc] == :tst } if pattern == 'test'
+
+ # Assemble the path/names of the files we need to work with.
+ files = []
+ triad.each do |cfg|
+ patterns.each_pair do |pattern_file, pattern_traits|
+ submodule_name = create_filename(module_name, pattern_file)
+ filename = cfg[:prefix] + submodule_name + cfg[:ext]
+ files << {
+ path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath,
+ name: submodule_name,
+ template: cfg[:template],
+ boilerplate: cfg[:boilerplate],
+ includes: case (cfg[:inc])
+ when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) })
+ when :inc then (@options[:includes][:inc] || [])
+ when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) })
+ end
+ }
+ end
+ end
+
+ files
+ end
+
+ ############################
+ def create_filename(part1, part2 = '')
+ if part2.empty?
+ case (@options[:naming])
+ when 'bumpy' then part1
+ when 'camel' then part1
+ when 'snake' then part1.downcase
+ when 'caps' then part1.upcase
+ else part1
+ end
+ else
+ case (@options[:naming])
+ when 'bumpy' then part1 + part2
+ when 'camel' then part1 + part2
+ when 'snake' then part1.downcase + '_' + part2.downcase
+ when 'caps' then part1.upcase + '_' + part2.upcase
+ else part1 + '_' + part2
+ end
+ end
+ end
+
+ ############################
+ def generate(module_name, pattern = nil)
+ files = files_to_operate_on(module_name, pattern)
+
+ # Abort if all of the module files already exist
+ all_files_exist = true
+ files.each do |file|
+ all_files_exist = false unless File.exist?(file[:path])
+ end
+ raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist
+
+ # Create Source Modules
+ files.each_with_index do |file, _i|
+ # If this file already exists, don't overwrite it.
+ if File.exist?(file[:path])
+ puts "File #{file[:path]} already exists!"
+ next
+ end
+ # Create the path first if necessary.
+ FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false)
+ File.open(file[:path], 'w') do |f|
+ f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil?
+ f.write(file[:template] % [file[:name],
+ file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join,
+ file[:name].upcase])
+ end
+ if @options[:update_svn]
+ `svn add \"#{file[:path]}\"`
+ if $!.exitstatus.zero?
+ puts "File #{file[:path]} created and added to source control"
+ else
+ puts "File #{file[:path]} created but FAILED adding to source control!"
+ end
+ else
+ puts "File #{file[:path]} created"
+ end
+ end
+ puts 'Generate Complete'
+ end
+
+ ############################
+ def destroy(module_name, pattern = nil)
+ files_to_operate_on(module_name, pattern).each do |filespec|
+ file = filespec[:path]
+ if File.exist?(file)
+ if @options[:update_svn]
+ `svn delete \"#{file}\" --force`
+ puts "File #{file} deleted and removed from source control"
+ else
+ FileUtils.remove(file)
+ puts "File #{file} deleted"
+ end
+ else
+ puts "File #{file} does not exist so cannot be removed."
+ end
+ end
+ puts 'Destroy Complete'
+ end
+end
+
+############################
+# Handle As Command Line If Called That Way
+if $0 == __FILE__
+ destroy = false
+ options = {}
+ module_name = nil
+
+ # Parse the command line parameters.
+ ARGV.each do |arg|
+ case arg
+ when /^-d/ then destroy = true
+ when /^-u/ then options[:update_svn] = true
+ when /^-p\"?(\w+)\"?/ then options[:pattern] = Regexp.last_match(1)
+ when /^-s\"?(.+)\"?/ then options[:path_src] = Regexp.last_match(1)
+ when /^-i\"?(.+)\"?/ then options[:path_inc] = Regexp.last_match(1)
+ when /^-t\"?(.+)\"?/ then options[:path_tst] = Regexp.last_match(1)
+ when /^-n\"?(.+)\"?/ then options[:naming] = Regexp.last_match(1)
+ when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config(Regexp.last_match(1))
+ when /^(\w+)/
+ raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil?
+
+ module_name = arg
+ when /^-(h|-help)/
+ ARGV = [].freeze
+ else
+ raise "ERROR: Unknown option specified '#{arg}'"
+ end
+ end
+
+ unless ARGV[0]
+ puts ["\nGENERATE MODULE\n-------- ------",
+ "\nUsage: ruby generate_module [options] module_name",
+ " -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)",
+ " -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)",
+ " -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)",
+ ' -p"MCH" sets the output pattern to MCH.',
+ ' dh - driver hardware.',
+ ' dih - driver interrupt hardware.',
+ ' mch - model conductor hardware.',
+ ' mvp - model view presenter.',
+ ' src - just a source module, header and test. (DEFAULT)',
+ ' test - just a test file.',
+ ' -d destroy module instead of creating it.',
+ ' -n"camel" sets the file naming convention.',
+ ' bumpy - BumpyCaseFilenames.',
+ ' camel - camelCaseFilenames.',
+ ' snake - snake_case_filenames.',
+ ' caps - CAPS_CASE_FILENAMES.',
+ ' -u update subversion too (requires subversion command line)',
+ ' -y"my.yml" selects a different yaml config file for module generation',
+ ''].join("\n")
+ exit
+ end
+
+ raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil?
+
+ if destroy
+ UnityModuleGenerator.new(options).destroy(module_name)
+ else
+ UnityModuleGenerator.new(options).generate(module_name)
+ end
+
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb
new file mode 100755
index 00000000..5053210d
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/generate_test_runner.rb
@@ -0,0 +1,495 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+class UnityTestRunnerGenerator
+ def initialize(options = nil)
+ @options = UnityTestRunnerGenerator.default_options
+ case options
+ when NilClass
+ @options
+ when String
+ @options.merge!(UnityTestRunnerGenerator.grab_config(options))
+ when Hash
+ # Check if some of these have been specified
+ @options[:has_setup] = !options[:setup_name].nil?
+ @options[:has_teardown] = !options[:teardown_name].nil?
+ @options[:has_suite_setup] = !options[:suite_setup].nil?
+ @options[:has_suite_teardown] = !options[:suite_teardown].nil?
+ @options.merge!(options)
+ else
+ raise 'If you specify arguments, it should be a filename or a hash of options'
+ end
+ require_relative 'type_sanitizer'
+ end
+
+ def self.default_options
+ {
+ includes: [],
+ defines: [],
+ plugins: [],
+ framework: :unity,
+ test_prefix: 'test|spec|should',
+ mock_prefix: 'Mock',
+ mock_suffix: '',
+ setup_name: 'setUp',
+ teardown_name: 'tearDown',
+ test_reset_name: 'resetTest',
+ test_verify_name: 'verifyTest',
+ main_name: 'main', # set to :auto to automatically generate each time
+ main_export_decl: '',
+ cmdline_args: false,
+ omit_begin_end: false,
+ use_param_tests: false
+ }
+ end
+
+ def self.grab_config(config_file)
+ options = default_options
+ unless config_file.nil? || config_file.empty?
+ require 'yaml'
+ yaml_guts = YAML.load_file(config_file)
+ options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
+ raise "No :unity or :cmock section found in #{config_file}" unless options
+ end
+ options
+ end
+
+ def run(input_file, output_file, options = nil)
+ @options.merge!(options) unless options.nil?
+
+ # pull required data from source file
+ source = File.read(input_file)
+ source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
+ tests = find_tests(source)
+ headers = find_includes(source)
+ testfile_includes = (headers[:local] + headers[:system])
+ used_mocks = find_mocks(testfile_includes)
+ testfile_includes = (testfile_includes - used_mocks)
+ testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
+ find_setup_and_teardown(source)
+
+ # build runner file
+ generate(input_file, output_file, tests, used_mocks, testfile_includes)
+
+ # determine which files were used to return them
+ all_files_used = [input_file, output_file]
+ all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty?
+ all_files_used += @options[:includes] unless @options[:includes].empty?
+ all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
+ all_files_used.uniq
+ end
+
+ def generate(input_file, output_file, tests, used_mocks, testfile_includes)
+ File.open(output_file, 'w') do |output|
+ create_header(output, used_mocks, testfile_includes)
+ create_externs(output, tests, used_mocks)
+ create_mock_management(output, used_mocks)
+ create_setup(output)
+ create_teardown(output)
+ create_suite_setup(output)
+ create_suite_teardown(output)
+ create_reset(output)
+ create_run_test(output)
+ create_args_wrappers(output, tests)
+ create_main(output, input_file, tests, used_mocks)
+ end
+
+ return unless @options[:header_file] && !@options[:header_file].empty?
+
+ File.open(@options[:header_file], 'w') do |output|
+ create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
+ end
+ end
+
+ def find_tests(source)
+ tests_and_line_numbers = []
+
+ # contains characters which will be substituted from within strings, doing
+ # this prevents these characters from interferring with scrubbers
+ # @ is not a valid C character, so there should be no clashes with files genuinely containing these markers
+ substring_subs = { '{' => '@co@', '}' => '@cc@', ';' => '@ss@', '/' => '@fs@' }
+ substring_re = Regexp.union(substring_subs.keys)
+ substring_unsubs = substring_subs.invert # the inverse map will be used to fix the strings afterwords
+ substring_unsubs['@quote@'] = '\\"'
+ substring_unsubs['@apos@'] = '\\\''
+ substring_unre = Regexp.union(substring_unsubs.keys)
+ source_scrubbed = source.clone
+ source_scrubbed = source_scrubbed.gsub(/\\"/, '@quote@') # hide escaped quotes to allow capture of the full string/char
+ source_scrubbed = source_scrubbed.gsub(/\\'/, '@apos@') # hide escaped apostrophes to allow capture of the full string/char
+ source_scrubbed = source_scrubbed.gsub(/("[^"\n]*")|('[^'\n]*')/) { |s| s.gsub(substring_re, substring_subs) } # temporarily hide problematic characters within strings
+ source_scrubbed = source_scrubbed.gsub(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
+ source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments
+ source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments (all that remain)
+ lines = source_scrubbed.split(/(^\s*\#.*$) | (;|\{|\}) /x) # Treat preprocessor directives as a logical line. Match ;, {, and } as end of lines
+ .map { |line| line.gsub(substring_unre, substring_unsubs) } # unhide the problematic characters previously removed
+
+ lines.each_with_index do |line, _index|
+ # find tests
+ next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m
+
+ arguments = Regexp.last_match(1)
+ name = Regexp.last_match(2)
+ call = Regexp.last_match(3)
+ params = Regexp.last_match(4)
+ args = nil
+
+ if @options[:use_param_tests] && !arguments.empty?
+ args = []
+ arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] }
+ end
+
+ tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 }
+ end
+
+ tests_and_line_numbers.uniq! { |v| v[:test] }
+
+ # determine line numbers and create tests to run
+ source_lines = source.split("\n")
+ source_index = 0
+ tests_and_line_numbers.size.times do |i|
+ source_lines[source_index..-1].each_with_index do |line, index|
+ next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/
+
+ source_index += index
+ tests_and_line_numbers[i][:line_number] = source_index + 1
+ break
+ end
+ end
+
+ tests_and_line_numbers
+ end
+
+ def find_includes(source)
+ # remove comments (block and line, in three steps to ensure correct precedence)
+ source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
+ source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
+ source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
+
+ # parse out includes
+ includes = {
+ local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten,
+ system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
+ linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten
+ }
+ includes
+ end
+
+ def find_mocks(includes)
+ mock_headers = []
+ includes.each do |include_path|
+ include_file = File.basename(include_path)
+ mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}.*#{@options[:mock_suffix]}$/i
+ end
+ mock_headers
+ end
+
+ def find_setup_and_teardown(source)
+ @options[:has_setup] = source =~ /void\s+#{@options[:setup_name]}\s*\(/
+ @options[:has_teardown] = source =~ /void\s+#{@options[:teardown_name]}\s*\(/
+ @options[:has_suite_setup] ||= (source =~ /void\s+suiteSetUp\s*\(/)
+ @options[:has_suite_teardown] ||= (source =~ /void\s+suiteTearDown\s*\(/)
+ end
+
+ def create_header(output, mocks, testfile_includes = [])
+ output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
+ output.puts("\n/*=======Automagically Detected Files To Include=====*/")
+ output.puts("#include \"#{@options[:framework]}.h\"")
+ output.puts('#include "cmock.h"') unless mocks.empty?
+ if @options[:defines] && !@options[:defines].empty?
+ @options[:defines].each { |d| output.puts("#ifndef #{d}\n#define #{d}\n#endif /* #{d} */") }
+ end
+ if @options[:header_file] && !@options[:header_file].empty?
+ output.puts("#include \"#{File.basename(@options[:header_file])}\"")
+ else
+ @options[:includes].flatten.uniq.compact.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ testfile_includes.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ end
+ mocks.each do |mock|
+ output.puts("#include \"#{mock.gsub('.h', '')}.h\"")
+ end
+ output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
+
+ return unless @options[:enforce_strict_ordering]
+
+ output.puts('')
+ output.puts('int GlobalExpectCount;')
+ output.puts('int GlobalVerifyOrder;')
+ output.puts('char* GlobalOrderError;')
+ end
+
+ def create_externs(output, tests, _mocks)
+ output.puts("\n/*=======External Functions This Runner Calls=====*/")
+ output.puts("extern void #{@options[:setup_name]}(void);")
+ output.puts("extern void #{@options[:teardown_name]}(void);")
+ output.puts("\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif") if @options[:externc]
+ tests.each do |test|
+ output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
+ end
+ output.puts("#ifdef __cplusplus\n}\n#endif") if @options[:externc]
+ output.puts('')
+ end
+
+ def create_mock_management(output, mock_headers)
+ output.puts("\n/*=======Mock Management=====*/")
+ output.puts('static void CMock_Init(void)')
+ output.puts('{')
+
+ if @options[:enforce_strict_ordering]
+ output.puts(' GlobalExpectCount = 0;')
+ output.puts(' GlobalVerifyOrder = 0;')
+ output.puts(' GlobalOrderError = NULL;')
+ end
+
+ mocks = mock_headers.map { |mock| File.basename(mock) }
+ mocks.each do |mock|
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+ output.puts(" #{mock_clean}_Init();")
+ end
+ output.puts("}\n")
+
+ output.puts('static void CMock_Verify(void)')
+ output.puts('{')
+ mocks.each do |mock|
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+ output.puts(" #{mock_clean}_Verify();")
+ end
+ output.puts("}\n")
+
+ output.puts('static void CMock_Destroy(void)')
+ output.puts('{')
+ mocks.each do |mock|
+ mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+ output.puts(" #{mock_clean}_Destroy();")
+ end
+ output.puts("}\n")
+ end
+
+ def create_setup(output)
+ return if @options[:has_setup]
+
+ output.puts("\n/*=======Setup (stub)=====*/")
+ output.puts("void #{@options[:setup_name]}(void) {}")
+ end
+
+ def create_teardown(output)
+ return if @options[:has_teardown]
+
+ output.puts("\n/*=======Teardown (stub)=====*/")
+ output.puts("void #{@options[:teardown_name]}(void) {}")
+ end
+
+ def create_suite_setup(output)
+ return if @options[:suite_setup].nil?
+
+ output.puts("\n/*=======Suite Setup=====*/")
+ output.puts('void suiteSetUp(void)')
+ output.puts('{')
+ output.puts(@options[:suite_setup])
+ output.puts('}')
+ end
+
+ def create_suite_teardown(output)
+ return if @options[:suite_teardown].nil?
+
+ output.puts("\n/*=======Suite Teardown=====*/")
+ output.puts('int suiteTearDown(int num_failures)')
+ output.puts('{')
+ output.puts(@options[:suite_teardown])
+ output.puts('}')
+ end
+
+ def create_reset(output)
+ output.puts("\n/*=======Test Reset Options=====*/")
+ output.puts("void #{@options[:test_reset_name]}(void);")
+ output.puts("void #{@options[:test_reset_name]}(void)")
+ output.puts('{')
+ output.puts(" #{@options[:teardown_name]}();")
+ output.puts(' CMock_Verify();')
+ output.puts(' CMock_Destroy();')
+ output.puts(' CMock_Init();')
+ output.puts(" #{@options[:setup_name]}();")
+ output.puts('}')
+ output.puts("void #{@options[:test_verify_name]}(void);")
+ output.puts("void #{@options[:test_verify_name]}(void)")
+ output.puts('{')
+ output.puts(' CMock_Verify();')
+ output.puts('}')
+ end
+
+ def create_run_test(output)
+ require 'erb'
+ template = ERB.new(File.read(File.join(__dir__, 'run_test.erb')))
+ output.puts(template.result(binding))
+ end
+
+ def create_args_wrappers(output, tests)
+ return unless @options[:use_param_tests]
+
+ output.puts("\n/*=======Parameterized Test Wrappers=====*/")
+ tests.each do |test|
+ next if test[:args].nil? || test[:args].empty?
+
+ test[:args].each.with_index(1) do |args, idx|
+ output.puts("static void runner_args#{idx}_#{test[:test]}(void)")
+ output.puts('{')
+ output.puts(" #{test[:test]}(#{args});")
+ output.puts("}\n")
+ end
+ end
+ end
+
+ def create_main(output, filename, tests, used_mocks)
+ output.puts("\n\n/*=======MAIN=====*/")
+ main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s
+ if @options[:cmdline_args]
+ if main_name != 'main'
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);")
+ end
+ output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
+ output.puts('{')
+ output.puts(' int parse_status = UnityParseOptions(argc, argv);')
+ output.puts(' if (parse_status != 0)')
+ output.puts(' {')
+ output.puts(' if (parse_status < 0)')
+ output.puts(' {')
+ output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");")
+ output.puts(' UNITY_PRINT_EOL();')
+ tests.each do |test|
+ if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty?
+ output.puts(" UnityPrint(\" #{test[:test]}\");")
+ output.puts(' UNITY_PRINT_EOL();')
+ else
+ test[:args].each do |args|
+ output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");")
+ output.puts(' UNITY_PRINT_EOL();')
+ end
+ end
+ end
+ output.puts(' return 0;')
+ output.puts(' }')
+ output.puts(' return parse_status;')
+ output.puts(' }')
+ else
+ main_return = @options[:omit_begin_end] ? 'void' : 'int'
+ if main_name != 'main'
+ output.puts("#{@options[:main_export_decl]} #{main_return} #{main_name}(void);")
+ end
+ output.puts("#{main_return} #{main_name}(void)")
+ output.puts('{')
+ end
+ output.puts(' suiteSetUp();') if @options[:has_suite_setup]
+ if @options[:omit_begin_end]
+ output.puts(" UnitySetTestFile(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
+ else
+ output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
+ end
+ tests.each do |test|
+ if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty?
+ output.puts(" run_test(#{test[:test]}, \"#{test[:test]}\", #{test[:line_number]});")
+ else
+ test[:args].each.with_index(1) do |args, idx|
+ wrapper = "runner_args#{idx}_#{test[:test]}"
+ testname = "#{test[:test]}(#{args})".dump
+ output.puts(" run_test(#{wrapper}, #{testname}, #{test[:line_number]});")
+ end
+ end
+ end
+ output.puts
+ output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
+ if @options[:has_suite_teardown]
+ if @options[:omit_begin_end]
+ output.puts(' (void) suite_teardown(0);')
+ else
+ output.puts(' return suiteTearDown(UnityEnd());')
+ end
+ else
+ output.puts(' return UnityEnd();') if not @options[:omit_begin_end]
+ end
+ output.puts('}')
+ end
+
+ def create_h_file(output, filename, tests, testfile_includes, used_mocks)
+ filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase
+ output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
+ output.puts("#ifndef _#{filename}")
+ output.puts("#define _#{filename}\n\n")
+ output.puts("#include \"#{@options[:framework]}.h\"")
+ output.puts('#include "cmock.h"') unless used_mocks.empty?
+ @options[:includes].flatten.uniq.compact.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ testfile_includes.each do |inc|
+ output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
+ end
+ output.puts "\n"
+ tests.each do |test|
+ if test[:params].nil? || test[:params].empty?
+ output.puts("void #{test[:test]}(void);")
+ else
+ output.puts("void #{test[:test]}(#{test[:params]});")
+ end
+ end
+ output.puts("#endif\n\n")
+ end
+end
+
+if $0 == __FILE__
+ options = { includes: [] }
+
+ # parse out all the options first (these will all be removed as we go)
+ ARGV.reject! do |arg|
+ case arg
+ when '-cexception'
+ options[:plugins] = [:cexception]
+ true
+ when /\.*\.ya?ml/
+ options = UnityTestRunnerGenerator.grab_config(arg)
+ true
+ when /--(\w+)=\"?(.*)\"?/
+ options[Regexp.last_match(1).to_sym] = Regexp.last_match(2)
+ true
+ when /\.*\.h/
+ options[:includes] << arg
+ true
+ else false
+ end
+ end
+
+ # make sure there is at least one parameter left (the input file)
+ unless ARGV[0]
+ puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)",
+ "\n input_test_file - this is the C file you want to create a runner for",
+ ' output - this is the name of the runner file to generate',
+ ' defaults to (input_test_file)_Runner',
+ ' files:',
+ ' *.yml / *.yaml - loads configuration from here in :unity or :cmock',
+ ' *.h - header files are added as #includes in runner',
+ ' options:',
+ ' -cexception - include cexception support',
+ ' -externc - add extern "C" for cpp support',
+ ' --setup_name="" - redefine setUp func name to something else',
+ ' --teardown_name="" - redefine tearDown func name to something else',
+ ' --main_name="" - redefine main func name to something else',
+ ' --test_prefix="" - redefine test prefix from default test|spec|should',
+ ' --test_reset_name="" - redefine resetTest func name to something else',
+ ' --test_verify_name="" - redefine verifyTest func name to something else',
+ ' --suite_setup="" - code to execute for setup of entire suite',
+ ' --suite_teardown="" - code to execute for teardown of entire suite',
+ ' --use_param_tests=1 - enable parameterized tests (disabled by default)',
+ ' --omit_begin_end=1 - omit calls to UnityBegin and UnityEnd (disabled by default)',
+ ' --header_file="" - path/name of test header file to generate too'].join("\n")
+ exit 1
+ end
+
+ # create the default test runner name if not specified
+ ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1]
+
+ UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/parse_output.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/parse_output.rb
new file mode 100755
index 00000000..d72c6e8b
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/parse_output.rb
@@ -0,0 +1,322 @@
+#============================================================
+# Author: John Theofanopoulos
+# A simple parser. Takes the output files generated during the
+# build process and extracts information relating to the tests.
+#
+# Notes:
+# To capture an output file under VS builds use the following:
+# devenv [build instructions] > Output.txt & type Output.txt
+#
+# To capture an output file under Linux builds use the following:
+# make | tee Output.txt
+#
+# This script can handle the following output formats:
+# - normal output (raw unity)
+# - fixture output (unity_fixture.h/.c)
+# - fixture output with verbose flag set ("-v")
+#
+# To use this parser use the following command
+# ruby parseOutput.rb [options] [file]
+# options: -xml : produce a JUnit compatible XML file
+# file: file to scan for results
+#============================================================
+
+# Parser class for handling the input file
+class ParseOutput
+ def initialize
+ # internal data
+ @class_name_idx = 0
+ @path_delim = nil
+
+ # xml output related
+ @xml_out = false
+ @array_list = false
+
+ # current suite name and statistics
+ @test_suite = nil
+ @total_tests = 0
+ @test_passed = 0
+ @test_failed = 0
+ @test_ignored = 0
+ end
+
+ # Set the flag to indicate if there will be an XML output file or not
+ def set_xml_output
+ @xml_out = true
+ end
+
+ # If write our output to XML
+ def write_xml_output
+ output = File.open('report.xml', 'w')
+ output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ @array_list.each do |item|
+ output << item << "\n"
+ end
+ end
+
+ # Pushes the suite info as xml to the array list, which will be written later
+ def push_xml_output_suite_info
+ # Insert opening tag at front
+ heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + @test_failed.to_s + '"' + ' skips="' + @test_ignored.to_s + '">'
+ @array_list.insert(0, heading)
+ # Push back the closing tag
+ @array_list.push '</testsuite>'
+ end
+
+ # Pushes xml output data to the array list, which will be written later
+ def push_xml_output_passed(test_name)
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
+ end
+
+ # Pushes xml output data to the array list, which will be written later
+ def push_xml_output_failed(test_name, reason)
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
+ @array_list.push ' <failure type="ASSERT FAILED">' + reason + '</failure>'
+ @array_list.push ' </testcase>'
+ end
+
+ # Pushes xml output data to the array list, which will be written later
+ def push_xml_output_ignored(test_name, reason)
+ @array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
+ @array_list.push ' <skipped type="TEST IGNORED">' + reason + '</skipped>'
+ @array_list.push ' </testcase>'
+ end
+
+ # This function will try and determine when the suite is changed. This is
+ # is the name that gets added to the classname parameter.
+ def test_suite_verify(test_suite_name)
+ # Split the path name
+ test_name = test_suite_name.split(@path_delim)
+
+ # Remove the extension and extract the base_name
+ base_name = test_name[test_name.size - 1].split('.')[0]
+
+ # Return if the test suite hasn't changed
+ return unless base_name.to_s != @test_suite.to_s
+
+ @test_suite = base_name
+ printf "New Test: %s\n", @test_suite
+ end
+
+ # Prepares the line for verbose fixture output ("-v")
+ def prepare_fixture_line(line)
+ line = line.sub('IGNORE_TEST(', '')
+ line = line.sub('TEST(', '')
+ line = line.sub(')', ',')
+ line = line.chomp
+ array = line.split(',')
+ array.map { |x| x.to_s.lstrip.chomp }
+ end
+
+ # Test was flagged as having passed so format the output.
+ # This is using the Unity fixture output and not the original Unity output.
+ def test_passed_unity_fixture(array)
+ class_name = array[0]
+ test_name = array[1]
+ test_suite_verify(class_name)
+ printf "%-40s PASS\n", test_name
+
+ push_xml_output_passed(test_name) if @xml_out
+ end
+
+ # Test was flagged as having failed so format the output.
+ # This is using the Unity fixture output and not the original Unity output.
+ def test_failed_unity_fixture(array)
+ class_name = array[0]
+ test_name = array[1]
+ test_suite_verify(class_name)
+ reason_array = array[2].split(':')
+ reason = reason_array[-1].lstrip.chomp + ' at line: ' + reason_array[-4]
+
+ printf "%-40s FAILED\n", test_name
+
+ push_xml_output_failed(test_name, reason) if @xml_out
+ end
+
+ # Test was flagged as being ignored so format the output.
+ # This is using the Unity fixture output and not the original Unity output.
+ def test_ignored_unity_fixture(array)
+ class_name = array[0]
+ test_name = array[1]
+ reason = 'No reason given'
+ if array.size > 2
+ reason_array = array[2].split(':')
+ tmp_reason = reason_array[-1].lstrip.chomp
+ reason = tmp_reason == 'IGNORE' ? 'No reason given' : tmp_reason
+ end
+ test_suite_verify(class_name)
+ printf "%-40s IGNORED\n", test_name
+
+ push_xml_output_ignored(test_name, reason) if @xml_out
+ end
+
+ # Test was flagged as having passed so format the output
+ def test_passed(array)
+ last_item = array.length - 1
+ test_name = array[last_item - 1]
+ test_suite_verify(array[@class_name_idx])
+ printf "%-40s PASS\n", test_name
+
+ return unless @xml_out
+
+ push_xml_output_passed(test_name) if @xml_out
+ end
+
+ # Test was flagged as having failed so format the line
+ def test_failed(array)
+ last_item = array.length - 1
+ test_name = array[last_item - 2]
+ reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3]
+ class_name = array[@class_name_idx]
+
+ if test_name.start_with? 'TEST('
+ array2 = test_name.split(' ')
+
+ test_suite = array2[0].sub('TEST(', '')
+ test_suite = test_suite.sub(',', '')
+ class_name = test_suite
+
+ test_name = array2[1].sub(')', '')
+ end
+
+ test_suite_verify(class_name)
+ printf "%-40s FAILED\n", test_name
+
+ push_xml_output_failed(test_name, reason) if @xml_out
+ end
+
+ # Test was flagged as being ignored so format the output
+ def test_ignored(array)
+ last_item = array.length - 1
+ test_name = array[last_item - 2]
+ reason = array[last_item].chomp.lstrip
+ class_name = array[@class_name_idx]
+
+ if test_name.start_with? 'TEST('
+ array2 = test_name.split(' ')
+
+ test_suite = array2[0].sub('TEST(', '')
+ test_suite = test_suite.sub(',', '')
+ class_name = test_suite
+
+ test_name = array2[1].sub(')', '')
+ end
+
+ test_suite_verify(class_name)
+ printf "%-40s IGNORED\n", test_name
+
+ push_xml_output_ignored(test_name, reason) if @xml_out
+ end
+
+ # Adjusts the os specific members according to the current path style
+ # (Windows or Unix based)
+ def detect_os_specifics(line)
+ if line.include? '\\'
+ # Windows X:\Y\Z
+ @class_name_idx = 1
+ @path_delim = '\\'
+ else
+ # Unix Based /X/Y/Z
+ @class_name_idx = 0
+ @path_delim = '/'
+ end
+ end
+
+ # Main function used to parse the file that was captured.
+ def process(file_name)
+ @array_list = []
+
+ puts 'Parsing file: ' + file_name
+
+ @test_passed = 0
+ @test_failed = 0
+ @test_ignored = 0
+ puts ''
+ puts '=================== RESULTS ====================='
+ puts ''
+ File.open(file_name).each do |line|
+ # Typical test lines look like these:
+ # ----------------------------------------------------
+ # 1. normal output:
+ # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
+ # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
+ # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
+ #
+ # 2. fixture output
+ # <path>/<test_file>.c:63:TEST(<test_group>, <test_function>):FAIL: Expected 0x00001234 Was 0x00005A5A
+ # <path>/<test_file>.c:36:TEST(<test_group>, <test_function>):IGNORE
+ # Note: "PASS" information won't be generated in this mode
+ #
+ # 3. fixture output with verbose information ("-v")
+ # TEST(<test_group, <test_file>)<path>/<test_file>:168::FAIL: Expected 0x8D Was 0x8C
+ # TEST(<test_group>, <test_file>)<path>/<test_file>:22::IGNORE: This Test Was Ignored On Purpose
+ # IGNORE_TEST(<test_group, <test_file>)
+ # TEST(<test_group, <test_file>) PASS
+ #
+ # Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)!
+ detect_os_specifics(line)
+ line_array = line.split(':')
+
+ # If we were able to split the line then we can look to see if any of our target words
+ # were found. Case is important.
+ next unless (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
+
+ # check if the output is fixture output (with verbose flag "-v")
+ if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
+ line_array = prepare_fixture_line(line)
+ if line.include? ' PASS'
+ test_passed_unity_fixture(line_array)
+ @test_passed += 1
+ elsif line.include? 'FAIL'
+ test_failed_unity_fixture(line_array)
+ @test_failed += 1
+ elsif line.include? 'IGNORE'
+ test_ignored_unity_fixture(line_array)
+ @test_ignored += 1
+ end
+ # normal output / fixture output (without verbose "-v")
+ elsif line.include? ':PASS'
+ test_passed(line_array)
+ @test_passed += 1
+ elsif line.include? ':FAIL'
+ test_failed(line_array)
+ @test_failed += 1
+ elsif line.include? ':IGNORE:'
+ test_ignored(line_array)
+ @test_ignored += 1
+ elsif line.include? ':IGNORE'
+ line_array.push('No reason given')
+ test_ignored(line_array)
+ @test_ignored += 1
+ end
+ @total_tests = @test_passed + @test_failed + @test_ignored
+ end
+ puts ''
+ puts '=================== SUMMARY ====================='
+ puts ''
+ puts 'Tests Passed : ' + @test_passed.to_s
+ puts 'Tests Failed : ' + @test_failed.to_s
+ puts 'Tests Ignored : ' + @test_ignored.to_s
+
+ return unless @xml_out
+
+ # push information about the suite
+ push_xml_output_suite_info
+ # write xml output file
+ write_xml_output
+ end
+end
+
+# If the command line has no values in, used a default value of Output.txt
+parse_my_file = ParseOutput.new
+
+if ARGV.size >= 1
+ ARGV.each do |arg|
+ if arg == '-xml'
+ parse_my_file.set_xml_output
+ else
+ parse_my_file.process(arg)
+ break
+ end
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/run_test.erb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/run_test.erb
new file mode 100755
index 00000000..3d3b6d1e
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/run_test.erb
@@ -0,0 +1,36 @@
+/*=======Test Runner Used To Run Each Test=====*/
+static void run_test(UnityTestFunction func, const char* name, int line_num)
+{
+ Unity.CurrentTestName = name;
+ Unity.CurrentTestLineNumber = line_num;
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+ if (!UnityTestMatches())
+ return;
+#endif
+ Unity.NumberOfTests++;
+ UNITY_CLR_DETAILS();
+ UNITY_EXEC_TIME_START();
+ CMock_Init();
+ if (TEST_PROTECT())
+ {
+<% if @options[:plugins].include?(:cexception) %>
+ CEXCEPTION_T e;
+ Try {
+<% end %>
+ <%= @options[:setup_name] %>();
+ func();
+<% if @options[:plugins].include?(:cexception) %>
+ } Catch(e) {
+ TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!");
+ }
+<% end %>
+ }
+ if (TEST_PROTECT())
+ {
+ <%= @options[:teardown_name] %>();
+ CMock_Verify();
+ }
+ CMock_Destroy();
+ UNITY_EXEC_TIME_STOP();
+ UnityConcludeTest();
+}
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/stylize_as_junit.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/stylize_as_junit.rb
new file mode 100755
index 00000000..e01f7912
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/stylize_as_junit.rb
@@ -0,0 +1,251 @@
+#!/usr/bin/ruby
+#
+# unity_to_junit.rb
+#
+require 'fileutils'
+require 'optparse'
+require 'ostruct'
+require 'set'
+
+require 'pp'
+
+VERSION = 1.0
+
+class ArgvParser
+ #
+ # Return a structure describing the options.
+ #
+ def self.parse(args)
+ # The options specified on the command line will be collected in *options*.
+ # We set default values here.
+ options = OpenStruct.new
+ options.results_dir = '.'
+ options.root_path = '.'
+ options.out_file = 'results.xml'
+
+ opts = OptionParser.new do |o|
+ o.banner = 'Usage: unity_to_junit.rb [options]'
+
+ o.separator ''
+ o.separator 'Specific options:'
+
+ o.on('-r', '--results <dir>', 'Look for Unity Results files here.') do |results|
+ # puts "results #{results}"
+ options.results_dir = results
+ end
+
+ o.on('-p', '--root_path <path>', 'Prepend this path to files in results.') do |root_path|
+ options.root_path = root_path
+ end
+
+ o.on('-o', '--output <filename>', 'XML file to generate.') do |out_file|
+ # puts "out_file: #{out_file}"
+ options.out_file = out_file
+ end
+
+ o.separator ''
+ o.separator 'Common options:'
+
+ # No argument, shows at tail. This will print an options summary.
+ o.on_tail('-h', '--help', 'Show this message') do
+ puts o
+ exit
+ end
+
+ # Another typical switch to print the version.
+ o.on_tail('--version', 'Show version') do
+ puts "unity_to_junit.rb version #{VERSION}"
+ exit
+ end
+ end
+
+ opts.parse!(args)
+ options
+ end
+end
+
+class UnityToJUnit
+ include FileUtils::Verbose
+ attr_reader :report, :total_tests, :failures, :ignored
+ attr_writer :targets, :root, :out_file
+
+ def initialize
+ @report = ''
+ @unit_name = ''
+ end
+
+ def run
+ # Clean up result file names
+ results = @targets.map { |target| target.tr('\\', '/') }
+ # puts "Output File: #{@out_file}"
+ f = File.new(@out_file, 'w')
+ write_xml_header(f)
+ write_suites_header(f)
+ results.each do |result_file|
+ lines = File.readlines(result_file).map(&:chomp)
+
+ raise "Empty test result file: #{result_file}" if lines.empty?
+
+ result_output = get_details(result_file, lines)
+ tests, failures, ignored = parse_test_summary(lines)
+ result_output[:counts][:total] = tests
+ result_output[:counts][:failed] = failures
+ result_output[:counts][:ignored] = ignored
+ result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored])
+
+ # use line[0] from the test output to get the test_file path and name
+ test_file_str = lines[0].tr('\\', '/')
+ test_file_str = test_file_str.split(':')
+ test_file = if test_file_str.length < 2
+ result_file
+ else
+ test_file_str[0] + ':' + test_file_str[1]
+ end
+ result_output[:source][:path] = File.dirname(test_file)
+ result_output[:source][:file] = File.basename(test_file)
+
+ # save result_output
+ @unit_name = File.basename(test_file, '.*')
+
+ write_suite_header(result_output[:counts], f)
+ write_failures(result_output, f)
+ write_tests(result_output, f)
+ write_ignored(result_output, f)
+ write_suite_footer(f)
+ end
+ write_suites_footer(f)
+ f.close
+ end
+
+ def usage(err_msg = nil)
+ puts "\nERROR: "
+ puts err_msg if err_msg
+ puts 'Usage: unity_to_junit.rb [options]'
+ puts ''
+ puts 'Specific options:'
+ puts ' -r, --results <dir> Look for Unity Results files here.'
+ puts ' -p, --root_path <path> Prepend this path to files in results.'
+ puts ' -o, --output <filename> XML file to generate.'
+ puts ''
+ puts 'Common options:'
+ puts ' -h, --help Show this message'
+ puts ' --version Show version'
+
+ exit 1
+ end
+
+ protected
+
+ def get_details(_result_file, lines)
+ results = results_structure
+ lines.each do |line|
+ line = line.tr('\\', '/')
+ _src_file, src_line, test_name, status, msg = line.split(/:/)
+ case status
+ when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg }
+ when 'FAIL' then results[:failures] << { test: test_name, line: src_line, message: msg }
+ when 'PASS' then results[:successes] << { test: test_name, line: src_line, message: msg }
+ end
+ end
+ results
+ end
+
+ def parse_test_summary(summary)
+ raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
+
+ [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i]
+ end
+
+ private
+
+ def results_structure
+ {
+ source: { path: '', file: '' },
+ successes: [],
+ failures: [],
+ ignores: [],
+ counts: { total: 0, passed: 0, failed: 0, ignored: 0 },
+ stdout: []
+ }
+ end
+
+ def write_xml_header(stream)
+ stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
+ end
+
+ def write_suites_header(stream)
+ stream.puts '<testsuites>'
+ end
+
+ def write_suite_header(counts, stream)
+ stream.puts "\t<testsuite errors=\"0\" skipped=\"#{counts[:ignored]}\" failures=\"#{counts[:failed]}\" tests=\"#{counts[:total]}\" name=\"unity\">"
+ end
+
+ def write_failures(results, stream)
+ result = results[:failures]
+ result.each do |item|
+ filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
+ stream.puts "\t\t\t<failure message=\"#{item[:message]}\" type=\"Assertion\"/>"
+ stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
+ stream.puts "\t\t</testcase>"
+ end
+ end
+
+ def write_tests(results, stream)
+ result = results[:successes]
+ result.each do |item|
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\" />"
+ end
+ end
+
+ def write_ignored(results, stream)
+ result = results[:ignores]
+ result.each do |item|
+ filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
+ puts "Writing ignored tests for test harness: #{filename}"
+ stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
+ stream.puts "\t\t\t<skipped message=\"#{item[:message]}\" type=\"Assertion\"/>"
+ stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
+ stream.puts "\t\t</testcase>"
+ end
+ end
+
+ def write_suite_footer(stream)
+ stream.puts "\t</testsuite>"
+ end
+
+ def write_suites_footer(stream)
+ stream.puts '</testsuites>'
+ end
+end
+
+if $0 == __FILE__
+ # parse out the command options
+ options = ArgvParser.parse(ARGV)
+
+ # create an instance to work with
+ utj = UnityToJUnit.new
+ begin
+ # look in the specified or current directory for result files
+ targets = "#{options.results_dir.tr('\\', '/')}**/*.test*"
+
+ results = Dir[targets]
+
+ raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
+
+ utj.targets = results
+
+ # set the root path
+ utj.root = options.root_path
+
+ # set the output XML file name
+ # puts "Output File from options: #{options.out_file}"
+ utj.out_file = options.out_file
+
+ # run the summarizer
+ puts utj.run
+ rescue StandardError => e
+ utj.usage e.message
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/test_file_filter.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/test_file_filter.rb
new file mode 100755
index 00000000..5c3a79fc
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/test_file_filter.rb
@@ -0,0 +1,25 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require'yaml'
+
+module RakefileHelpers
+ class TestFileFilter
+ def initialize(all_files = false)
+ @all_files = all_files
+
+ return unless @all_files
+ return unless File.exist?('test_file_filter.yml')
+
+ filters = YAML.load_file('test_file_filter.yml')
+ @all_files = filters[:all_files]
+ @only_files = filters[:only_files]
+ @exclude_files = filters[:exclude_files]
+ end
+
+ attr_accessor :all_files, :only_files, :exclude_files
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/type_sanitizer.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/type_sanitizer.rb
new file mode 100755
index 00000000..dafb8826
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/type_sanitizer.rb
@@ -0,0 +1,6 @@
+module TypeSanitizer
+ def self.sanitize_c_identifier(unsanitized)
+ # convert filename to valid C identifier by replacing invalid chars with '_'
+ unsanitized.gsub(/[-\/\\\.\,\s]/, '_')
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.py b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.py
new file mode 100755
index 00000000..00c0da8c
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.py
@@ -0,0 +1,139 @@
+#! python3
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de
+# [Released under MIT License. Please refer to license.txt for details]
+# Based on the ruby script by Mike Karlesky, Mark VanderVoord, Greg Williams
+# ==========================================
+import sys
+import os
+import re
+from glob import glob
+
+class UnityTestSummary:
+ def __init__(self):
+ self.report = ''
+ self.total_tests = 0
+ self.failures = 0
+ self.ignored = 0
+
+ def run(self):
+ # Clean up result file names
+ results = []
+ for target in self.targets:
+ results.append(target.replace('\\', '/'))
+
+ # Dig through each result file, looking for details on pass/fail:
+ failure_output = []
+ ignore_output = []
+
+ for result_file in results:
+ lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
+ if len(lines) == 0:
+ raise Exception("Empty test result file: %s" % result_file)
+
+ details = self.get_details(result_file, lines)
+ failures = details['failures']
+ ignores = details['ignores']
+ if len(failures) > 0: failure_output.append('\n'.join(failures))
+ if len(ignores) > 0: ignore_output.append('n'.join(ignores))
+ tests,failures,ignored = self.parse_test_summary('\n'.join(lines))
+ self.total_tests += tests
+ self.failures += failures
+ self.ignored += ignored
+
+ if self.ignored > 0:
+ self.report += "\n"
+ self.report += "--------------------------\n"
+ self.report += "UNITY IGNORED TEST SUMMARY\n"
+ self.report += "--------------------------\n"
+ self.report += "\n".join(ignore_output)
+
+ if self.failures > 0:
+ self.report += "\n"
+ self.report += "--------------------------\n"
+ self.report += "UNITY FAILED TEST SUMMARY\n"
+ self.report += "--------------------------\n"
+ self.report += '\n'.join(failure_output)
+
+ self.report += "\n"
+ self.report += "--------------------------\n"
+ self.report += "OVERALL UNITY TEST SUMMARY\n"
+ self.report += "--------------------------\n"
+ self.report += "{total_tests} TOTAL TESTS {failures} TOTAL FAILURES {ignored} IGNORED\n".format(total_tests = self.total_tests, failures=self.failures, ignored=self.ignored)
+ self.report += "\n"
+
+ return self.report
+
+ def set_targets(self, target_array):
+ self.targets = target_array
+
+ def set_root_path(self, path):
+ self.root = path
+
+ def usage(self, err_msg=None):
+ print("\nERROR: ")
+ if err_msg:
+ print(err_msg)
+ print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
+ print(" result_file_directory - The location of your results files.")
+ print(" Defaults to current directory if not specified.")
+ print(" Should end in / if specified.")
+ print(" root_path - Helpful for producing more verbose output if using relative paths.")
+ sys.exit(1)
+
+ def get_details(self, result_file, lines):
+ results = { 'failures': [], 'ignores': [], 'successes': [] }
+ for line in lines:
+ parts = line.split(':')
+ if len(parts) == 5:
+ src_file,src_line,test_name,status,msg = parts
+ elif len(parts) == 4:
+ src_file,src_line,test_name,status = parts
+ msg = ''
+ else:
+ continue
+ if len(self.root) > 0:
+ line_out = "%s%s" % (self.root, line)
+ else:
+ line_out = line
+ if status == 'IGNORE':
+ results['ignores'].append(line_out)
+ elif status == 'FAIL':
+ results['failures'].append(line_out)
+ elif status == 'PASS':
+ results['successes'].append(line_out)
+ return results
+
+ def parse_test_summary(self, summary):
+ m = re.search(r"([0-9]+) Tests ([0-9]+) Failures ([0-9]+) Ignored", summary)
+ if not m:
+ raise Exception("Couldn't parse test results: %s" % summary)
+
+ return int(m.group(1)), int(m.group(2)), int(m.group(3))
+
+
+if __name__ == '__main__':
+ uts = UnityTestSummary()
+ try:
+ #look in the specified or current directory for result files
+ if len(sys.argv) > 1:
+ targets_dir = sys.argv[1]
+ else:
+ targets_dir = './'
+ targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '**/*.test*', recursive=True)))
+ if len(targets) == 0:
+ raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
+ uts.set_targets(targets)
+
+ #set the root path
+ if len(sys.argv) > 2:
+ root_path = sys.argv[2]
+ else:
+ root_path = os.path.split(__file__)[0]
+ uts.set_root_path(root_path)
+
+ #run the summarizer
+ print(uts.run())
+ except Exception as e:
+ uts.usage(e)
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.rb b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.rb
new file mode 100755
index 00000000..b3fe8a69
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_test_summary.rb
@@ -0,0 +1,135 @@
+# ==========================================
+# Unity Project - A Test Framework for C
+# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+# [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+# !/usr/bin/ruby
+#
+# unity_test_summary.rb
+#
+require 'fileutils'
+require 'set'
+
+class UnityTestSummary
+ include FileUtils::Verbose
+
+ attr_reader :report, :total_tests, :failures, :ignored
+ attr_writer :targets, :root
+
+ def initialize(_opts = {})
+ @report = ''
+ @total_tests = 0
+ @failures = 0
+ @ignored = 0
+ end
+
+ def run
+ # Clean up result file names
+ results = @targets.map { |target| target.tr('\\', '/') }
+
+ # Dig through each result file, looking for details on pass/fail:
+ failure_output = []
+ ignore_output = []
+
+ results.each do |result_file|
+ lines = File.readlines(result_file).map(&:chomp)
+
+ raise "Empty test result file: #{result_file}" if lines.empty?
+
+ output = get_details(result_file, lines)
+ failure_output << output[:failures] unless output[:failures].empty?
+ ignore_output << output[:ignores] unless output[:ignores].empty?
+ tests, failures, ignored = parse_test_summary(lines)
+ @total_tests += tests
+ @failures += failures
+ @ignored += ignored
+ end
+
+ if @ignored > 0
+ @report += "\n"
+ @report += "--------------------------\n"
+ @report += "UNITY IGNORED TEST SUMMARY\n"
+ @report += "--------------------------\n"
+ @report += ignore_output.flatten.join("\n")
+ end
+
+ if @failures > 0
+ @report += "\n"
+ @report += "--------------------------\n"
+ @report += "UNITY FAILED TEST SUMMARY\n"
+ @report += "--------------------------\n"
+ @report += failure_output.flatten.join("\n")
+ end
+
+ @report += "\n"
+ @report += "--------------------------\n"
+ @report += "OVERALL UNITY TEST SUMMARY\n"
+ @report += "--------------------------\n"
+ @report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n"
+ @report += "\n"
+ end
+
+ def usage(err_msg = nil)
+ puts "\nERROR: "
+ puts err_msg if err_msg
+ puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/"
+ puts ' result_file_directory - The location of your results files.'
+ puts ' Defaults to current directory if not specified.'
+ puts ' Should end in / if specified.'
+ puts ' root_path - Helpful for producing more verbose output if using relative paths.'
+ exit 1
+ end
+
+ protected
+
+ def get_details(_result_file, lines)
+ results = { failures: [], ignores: [], successes: [] }
+ lines.each do |line|
+ _src_file, _src_line, _test_name, status, _msg = line.split(/:/)
+ line_out = (@root && (@root != 0) ? "#{@root}#{line}" : line).gsub(/\//, '\\')
+ case status
+ when 'IGNORE' then results[:ignores] << line_out
+ when 'FAIL' then results[:failures] << line_out
+ when 'PASS' then results[:successes] << line_out
+ end
+ end
+ results
+ end
+
+ def parse_test_summary(summary)
+ raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
+
+ [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i]
+ end
+end
+
+if $0 == __FILE__
+
+ # parse out the command options
+ opts, args = ARGV.partition { |v| v =~ /^--\w+/ }
+ opts.map! { |v| v[2..-1].to_sym }
+
+ # create an instance to work with
+ uts = UnityTestSummary.new(opts)
+
+ begin
+ # look in the specified or current directory for result files
+ args[0] ||= './'
+ targets = "#{ARGV[0].tr('\\', '/')}**/*.test*"
+ results = Dir[targets]
+
+ raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
+
+ uts.targets = results
+
+ # set the root path
+ args[1] ||= Dir.pwd + '/'
+ uts.root = ARGV[1]
+
+ # run the summarizer
+ puts uts.run
+ rescue StandardError => e
+ uts.usage e.message
+ end
+end
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_to_junit.py b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_to_junit.py
new file mode 100755
index 00000000..71dd5688
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/auto/unity_to_junit.py
@@ -0,0 +1,146 @@
+import sys
+import os
+from glob import glob
+
+from pyparsing import *
+from junit_xml import TestSuite, TestCase
+
+
+class UnityTestSummary:
+ def __init__(self):
+ self.report = ''
+ self.total_tests = 0
+ self.failures = 0
+ self.ignored = 0
+ self.targets = 0
+ self.root = None
+ self.test_suites = dict()
+
+ def run(self):
+ # Clean up result file names
+ results = []
+ for target in self.targets:
+ results.append(target.replace('\\', '/'))
+
+ # Dig through each result file, looking for details on pass/fail:
+ for result_file in results:
+ lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
+ if len(lines) == 0:
+ raise Exception("Empty test result file: %s" % result_file)
+
+ # define an expression for your file reference
+ entry_one = Combine(
+ oneOf(list(alphas)) + ':/' +
+ Word(alphanums + '_-./'))
+
+ entry_two = Word(printables + ' ', excludeChars=':')
+ entry = entry_one | entry_two
+
+ delimiter = Literal(':').suppress()
+ tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName(
+ 'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName(
+ 'tc_status') + Optional(
+ delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
+
+ eol = LineEnd().suppress()
+ sol = LineStart().suppress()
+ blank_line = sol + eol
+
+ tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
+ "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
+ "tc_summary")
+ tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result")
+
+ # run it and see...
+ pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line)
+ pp1.ignore(blank_line | OneOrMore("-"))
+
+ result = list()
+ for l in lines:
+ result.append((pp1.parseString(l)).asDict())
+ # delete empty results
+ result = filter(None, result)
+
+ tc_list = list()
+ for r in result:
+ if 'tc_line' in r:
+ tmp_tc_line = r['tc_line']
+
+ # get only the file name which will be used as the classname
+ file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
+ tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
+ if 'tc_status' in tmp_tc_line:
+ if str(tmp_tc_line['tc_status']) == 'IGNORE':
+ if 'tc_msg' in tmp_tc_line:
+ tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'],
+ output=r'[File]={0}, [Line]={1}'.format(
+ tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
+ else:
+ tmp_tc.add_skipped_info(message=" ")
+ elif str(tmp_tc_line['tc_status']) == 'FAIL':
+ if 'tc_msg' in tmp_tc_line:
+ tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'],
+ output=r'[File]={0}, [Line]={1}'.format(
+ tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
+ else:
+ tmp_tc.add_failure_info(message=" ")
+
+ tc_list.append((str(result_file), tmp_tc))
+
+ for k, v in tc_list:
+ try:
+ self.test_suites[k].append(v)
+ except KeyError:
+ self.test_suites[k] = [v]
+ ts = []
+ for suite_name in self.test_suites:
+ ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
+
+ with open('result.xml', 'w') as f:
+ TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
+
+ return self.report
+
+ def set_targets(self, target_array):
+ self.targets = target_array
+
+ def set_root_path(self, path):
+ self.root = path
+
+ @staticmethod
+ def usage(err_msg=None):
+ print("\nERROR: ")
+ if err_msg:
+ print(err_msg)
+ print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
+ print(" result_file_directory - The location of your results files.")
+ print(" Defaults to current directory if not specified.")
+ print(" Should end in / if specified.")
+ print(" root_path - Helpful for producing more verbose output if using relative paths.")
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ uts = UnityTestSummary()
+ try:
+ # look in the specified or current directory for result files
+ if len(sys.argv) > 1:
+ targets_dir = sys.argv[1]
+ else:
+ targets_dir = './'
+ targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
+ if len(targets) == 0:
+ raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
+ uts.set_targets(targets)
+
+ # set the root path
+ if len(sys.argv) > 2:
+ root_path = sys.argv[2]
+ else:
+ root_path = os.path.split(__file__)[0]
+ uts.set_root_path(root_path)
+
+ # run the summarizer
+ print(uts.run())
+ except Exception as e:
+ UnityTestSummary.usage(e)
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/release/build.info b/tinyusb/test/vendor/ceedling/vendor/unity/release/build.info
new file mode 100755
index 00000000..56d59128
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/release/build.info
@@ -0,0 +1,2 @@
+122
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/release/version.info b/tinyusb/test/vendor/ceedling/vendor/unity/release/version.info
new file mode 100755
index 00000000..cf12b30d
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/release/version.info
@@ -0,0 +1,2 @@
+2.4.3
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/CMakeLists.txt b/tinyusb/test/vendor/ceedling/vendor/unity/src/CMakeLists.txt
new file mode 100755
index 00000000..c747cb0a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/CMakeLists.txt
@@ -0,0 +1,22 @@
+###################################################################################
+# #
+# NAME: CMakeLists.txt #
+# #
+# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams. #
+# WRITTEN BY: Michael Brockus. #
+# #
+# License: MIT #
+# #
+###################################################################################
+cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
+
+
+add_library(unity STATIC "unity.c")
+
+install(TARGETS unity EXPORT unityConfig
+ ARCHIVE DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_INSTALL_LIBDIR}"
+ LIBRARY DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_INSTALL_LIBDIR}"
+ RUNTIME DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_INSTALL_BINDIR}"
+ INCLUDES DESTINATION "${CMAKE_INSTALL_LIBDIR}")
+
+
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/meson.build b/tinyusb/test/vendor/ceedling/vendor/unity/src/meson.build
new file mode 100755
index 00000000..f5e01465
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/meson.build
@@ -0,0 +1,16 @@
+###################################################################################
+# #
+# NAME: meson.build #
+# #
+# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams. #
+# WRITTEN BY: Michael Brockus. #
+# #
+# License: MIT #
+# #
+###################################################################################
+
+unity_dir = include_directories('.')
+
+unity_lib = static_library(meson.project_name(),
+ sources: ['unity.c'],
+ include_directories: unity_dir)
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.c b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.c
new file mode 100755
index 00000000..c7be02cc
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.c
@@ -0,0 +1,2085 @@
+/* =========================================================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+============================================================================ */
+
+#include "unity.h"
+#include <stddef.h>
+
+#ifdef AVR
+#include <avr/pgmspace.h>
+#else
+#define PROGMEM
+#endif
+
+/* If omitted from header, declare overrideable prototypes here so they're ready for use */
+#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
+void UNITY_OUTPUT_CHAR(int);
+#endif
+
+/* Helpful macros for us to use here in Assert functions */
+#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); }
+#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); }
+#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return
+
+struct UNITY_STORAGE_T Unity;
+
+#ifdef UNITY_OUTPUT_COLOR
+const char PROGMEM UnityStrOk[] = "\033[42mOK\033[00m";
+const char PROGMEM UnityStrPass[] = "\033[42mPASS\033[00m";
+const char PROGMEM UnityStrFail[] = "\033[41mFAIL\033[00m";
+const char PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[00m";
+#else
+const char PROGMEM UnityStrOk[] = "OK";
+const char PROGMEM UnityStrPass[] = "PASS";
+const char PROGMEM UnityStrFail[] = "FAIL";
+const char PROGMEM UnityStrIgnore[] = "IGNORE";
+#endif
+static const char PROGMEM UnityStrNull[] = "NULL";
+static const char PROGMEM UnityStrSpacer[] = ". ";
+static const char PROGMEM UnityStrExpected[] = " Expected ";
+static const char PROGMEM UnityStrWas[] = " Was ";
+static const char PROGMEM UnityStrGt[] = " to be greater than ";
+static const char PROGMEM UnityStrLt[] = " to be less than ";
+static const char PROGMEM UnityStrOrEqual[] = "or equal to ";
+static const char PROGMEM UnityStrElement[] = " Element ";
+static const char PROGMEM UnityStrByte[] = " Byte ";
+static const char PROGMEM UnityStrMemory[] = " Memory Mismatch.";
+static const char PROGMEM UnityStrDelta[] = " Values Not Within Delta ";
+static const char PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless.";
+static const char PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL";
+static const char PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL";
+#ifndef UNITY_EXCLUDE_FLOAT
+static const char PROGMEM UnityStrNot[] = "Not ";
+static const char PROGMEM UnityStrInf[] = "Infinity";
+static const char PROGMEM UnityStrNegInf[] = "Negative Infinity";
+static const char PROGMEM UnityStrNaN[] = "NaN";
+static const char PROGMEM UnityStrDet[] = "Determinate";
+static const char PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait";
+#endif
+const char PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled";
+const char PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled";
+const char PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled";
+const char PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled";
+static const char PROGMEM UnityStrBreaker[] = "-----------------------";
+static const char PROGMEM UnityStrResultsTests[] = " Tests ";
+static const char PROGMEM UnityStrResultsFailures[] = " Failures ";
+static const char PROGMEM UnityStrResultsIgnored[] = " Ignored ";
+static const char PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " ";
+static const char PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " ";
+
+/*-----------------------------------------------
+ * Pretty Printers & Test Result Output Handlers
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+/* Local helper function to print characters. */
+static void UnityPrintChar(const char* pch)
+{
+ /* printable characters plus CR & LF are printed */
+ if ((*pch <= 126) && (*pch >= 32))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ }
+ /* write escaped carriage returns */
+ else if (*pch == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (*pch == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)*pch, 2);
+ }
+}
+
+/*-----------------------------------------------*/
+/* Local helper function to print ANSI escape strings e.g. "\033[42m". */
+#ifdef UNITY_OUTPUT_COLOR
+static UNITY_UINT UnityPrintAnsiEscapeString(const char* string)
+{
+ const char* pch = string;
+ UNITY_UINT count = 0;
+
+ while (*pch && (*pch != 'm'))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ pch++;
+ count++;
+ }
+ UNITY_OUTPUT_CHAR('m');
+ count++;
+
+ return count;
+}
+#endif
+
+/*-----------------------------------------------*/
+void UnityPrint(const char* string)
+{
+ const char* pch = string;
+
+ if (pch != NULL)
+ {
+ while (*pch)
+ {
+#ifdef UNITY_OUTPUT_COLOR
+ /* print ANSI escape code */
+ if ((*pch == 27) && (*(pch + 1) == '['))
+ {
+ pch += UnityPrintAnsiEscapeString(pch);
+ continue;
+ }
+#endif
+ UnityPrintChar(pch);
+ pch++;
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+#ifdef UNITY_INCLUDE_PRINT_FORMATTED
+void UnityPrintFormatted(const char* format, ...)
+{
+ const char* pch = format;
+ va_list va;
+ va_start(va, format);
+
+ if (pch != NULL)
+ {
+ while (*pch)
+ {
+ /* format identification character */
+ if (*pch == '%')
+ {
+ pch++;
+
+ if (pch != NULL)
+ {
+ switch (*pch)
+ {
+ case 'd':
+ case 'i':
+ {
+ const int number = va_arg(va, int);
+ UnityPrintNumber((UNITY_INT)number);
+ break;
+ }
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ case 'f':
+ case 'g':
+ {
+ const double number = va_arg(va, double);
+ UnityPrintFloat((UNITY_DOUBLE)number);
+ break;
+ }
+#endif
+ case 'u':
+ {
+ const unsigned int number = va_arg(va, unsigned int);
+ UnityPrintNumberUnsigned((UNITY_UINT)number);
+ break;
+ }
+ case 'b':
+ {
+ const unsigned int number = va_arg(va, unsigned int);
+ const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1;
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('b');
+ UnityPrintMask(mask, (UNITY_UINT)number);
+ break;
+ }
+ case 'x':
+ case 'X':
+ case 'p':
+ {
+ const unsigned int number = va_arg(va, unsigned int);
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)number, 8);
+ break;
+ }
+ case 'c':
+ {
+ const int ch = va_arg(va, int);
+ UnityPrintChar((const char *)&ch);
+ break;
+ }
+ case 's':
+ {
+ const char * string = va_arg(va, const char *);
+ UnityPrint(string);
+ break;
+ }
+ case '%':
+ {
+ UnityPrintChar(pch);
+ break;
+ }
+ default:
+ {
+ /* print the unknown format character */
+ UNITY_OUTPUT_CHAR('%');
+ UnityPrintChar(pch);
+ break;
+ }
+ }
+ }
+ }
+#ifdef UNITY_OUTPUT_COLOR
+ /* print ANSI escape code */
+ else if ((*pch == 27) && (*(pch + 1) == '['))
+ {
+ pch += UnityPrintAnsiEscapeString(pch);
+ continue;
+ }
+#endif
+ else if (*pch == '\n')
+ {
+ UNITY_PRINT_EOL();
+ }
+ else
+ {
+ UnityPrintChar(pch);
+ }
+
+ pch++;
+ }
+ }
+
+ va_end(va);
+}
+#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */
+
+/*-----------------------------------------------*/
+void UnityPrintLen(const char* string, const UNITY_UINT32 length)
+{
+ const char* pch = string;
+
+ if (pch != NULL)
+ {
+ while (*pch && ((UNITY_UINT32)(pch - string) < length))
+ {
+ /* printable characters plus CR & LF are printed */
+ if ((*pch <= 126) && (*pch >= 32))
+ {
+ UNITY_OUTPUT_CHAR(*pch);
+ }
+ /* write escaped carriage returns */
+ else if (*pch == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (*pch == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)*pch, 2);
+ }
+ pch++;
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style)
+{
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (style == UNITY_DISPLAY_STYLE_CHAR)
+ {
+ /* printable characters plus CR & LF are printed */
+ UNITY_OUTPUT_CHAR('\'');
+ if ((number <= 126) && (number >= 32))
+ {
+ UNITY_OUTPUT_CHAR((int)number);
+ }
+ /* write escaped carriage returns */
+ else if (number == 13)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('r');
+ }
+ /* write escaped line feeds */
+ else if (number == 10)
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('n');
+ }
+ /* unprintable characters are shown as codes */
+ else
+ {
+ UNITY_OUTPUT_CHAR('\\');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)number, 2);
+ }
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrintNumber(number);
+ }
+ }
+ else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT)
+ {
+ UnityPrintNumberUnsigned((UNITY_UINT)number);
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('0');
+ UNITY_OUTPUT_CHAR('x');
+ UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2));
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumber(const UNITY_INT number_to_print)
+{
+ UNITY_UINT number = (UNITY_UINT)number_to_print;
+
+ if (number_to_print < 0)
+ {
+ /* A negative number, including MIN negative */
+ UNITY_OUTPUT_CHAR('-');
+ number = (~number) + 1;
+ }
+ UnityPrintNumberUnsigned(number);
+}
+
+/*-----------------------------------------------
+ * basically do an itoa using as little ram as possible */
+void UnityPrintNumberUnsigned(const UNITY_UINT number)
+{
+ UNITY_UINT divisor = 1;
+
+ /* figure out initial divisor */
+ while (number / divisor > 9)
+ {
+ divisor *= 10;
+ }
+
+ /* now mod and print, then divide divisor */
+ do
+ {
+ UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10)));
+ divisor /= 10;
+ } while (divisor > 0);
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print)
+{
+ int nibble;
+ char nibbles = nibbles_to_print;
+
+ if ((unsigned)nibbles > UNITY_MAX_NIBBLES)
+ {
+ nibbles = UNITY_MAX_NIBBLES;
+ }
+
+ while (nibbles > 0)
+ {
+ nibbles--;
+ nibble = (int)(number >> (nibbles * 4)) & 0x0F;
+ if (nibble <= 9)
+ {
+ UNITY_OUTPUT_CHAR((char)('0' + nibble));
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble));
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
+{
+ UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1);
+ UNITY_INT32 i;
+
+ for (i = 0; i < UNITY_INT_WIDTH; i++)
+ {
+ if (current_bit & mask)
+ {
+ if (current_bit & number)
+ {
+ UNITY_OUTPUT_CHAR('1');
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('0');
+ }
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('X');
+ }
+ current_bit = current_bit >> 1;
+ }
+}
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+/*
+ * This function prints a floating-point value in a format similar to
+ * printf("%.7g") on a single-precision machine or printf("%.9g") on a
+ * double-precision machine. The 7th digit won't always be totally correct
+ * in single-precision operation (for that level of accuracy, a more
+ * complicated algorithm would be needed).
+ */
+void UnityPrintFloat(const UNITY_DOUBLE input_number)
+{
+#ifdef UNITY_INCLUDE_DOUBLE
+ static const int sig_digits = 9;
+ static const UNITY_INT32 min_scaled = 100000000;
+ static const UNITY_INT32 max_scaled = 1000000000;
+#else
+ static const int sig_digits = 7;
+ static const UNITY_INT32 min_scaled = 1000000;
+ static const UNITY_INT32 max_scaled = 10000000;
+#endif
+
+ UNITY_DOUBLE number = input_number;
+
+ /* print minus sign (does not handle negative zero) */
+ if (number < 0.0f)
+ {
+ UNITY_OUTPUT_CHAR('-');
+ number = -number;
+ }
+
+ /* handle zero, NaN, and +/- infinity */
+ if (number == 0.0f)
+ {
+ UnityPrint("0");
+ }
+ else if (isnan(number))
+ {
+ UnityPrint("nan");
+ }
+ else if (isinf(number))
+ {
+ UnityPrint("inf");
+ }
+ else
+ {
+ UNITY_INT32 n_int = 0, n;
+ int exponent = 0;
+ int decimals, digits;
+ char buf[16] = {0};
+
+ /*
+ * Scale up or down by powers of 10. To minimize rounding error,
+ * start with a factor/divisor of 10^10, which is the largest
+ * power of 10 that can be represented exactly. Finally, compute
+ * (exactly) the remaining power of 10 and perform one more
+ * multiplication or division.
+ */
+ if (number < 1.0f)
+ {
+ UNITY_DOUBLE factor = 1.0f;
+
+ while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; }
+ while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; }
+
+ number *= factor;
+ }
+ else if (number > (UNITY_DOUBLE)max_scaled)
+ {
+ UNITY_DOUBLE divisor = 1.0f;
+
+ while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; }
+ while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; }
+
+ number /= divisor;
+ }
+ else
+ {
+ /*
+ * In this range, we can split off the integer part before
+ * doing any multiplications. This reduces rounding error by
+ * freeing up significant bits in the fractional part.
+ */
+ UNITY_DOUBLE factor = 1.0f;
+ n_int = (UNITY_INT32)number;
+ number -= (UNITY_DOUBLE)n_int;
+
+ while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; }
+
+ number *= factor;
+ }
+
+ /* round to nearest integer */
+ n = ((UNITY_INT32)(number + number) + 1) / 2;
+
+#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO
+ /* round to even if exactly between two integers */
+ if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f))
+ n--;
+#endif
+
+ n += n_int;
+
+ if (n >= max_scaled)
+ {
+ n = min_scaled;
+ exponent++;
+ }
+
+ /* determine where to place decimal point */
+ decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1);
+ exponent += decimals;
+
+ /* truncate trailing zeroes after decimal point */
+ while ((decimals > 0) && ((n % 10) == 0))
+ {
+ n /= 10;
+ decimals--;
+ }
+
+ /* build up buffer in reverse order */
+ digits = 0;
+ while ((n != 0) || (digits < (decimals + 1)))
+ {
+ buf[digits++] = (char)('0' + n % 10);
+ n /= 10;
+ }
+ while (digits > 0)
+ {
+ if (digits == decimals) { UNITY_OUTPUT_CHAR('.'); }
+ UNITY_OUTPUT_CHAR(buf[--digits]);
+ }
+
+ /* print exponent if needed */
+ if (exponent != 0)
+ {
+ UNITY_OUTPUT_CHAR('e');
+
+ if (exponent < 0)
+ {
+ UNITY_OUTPUT_CHAR('-');
+ exponent = -exponent;
+ }
+ else
+ {
+ UNITY_OUTPUT_CHAR('+');
+ }
+
+ digits = 0;
+ while ((exponent != 0) || (digits < 2))
+ {
+ buf[digits++] = (char)('0' + exponent % 10);
+ exponent /= 10;
+ }
+ while (digits > 0)
+ {
+ UNITY_OUTPUT_CHAR(buf[--digits]);
+ }
+ }
+ }
+}
+#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */
+
+/*-----------------------------------------------*/
+static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line)
+{
+#ifdef UNITY_OUTPUT_FOR_ECLIPSE
+ UNITY_OUTPUT_CHAR('(');
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrintNumber((UNITY_INT)line);
+ UNITY_OUTPUT_CHAR(')');
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(Unity.CurrentTestName);
+ UNITY_OUTPUT_CHAR(':');
+#else
+#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH
+ UnityPrint("<SRCREF line=");
+ UnityPrintNumber((UNITY_INT)line);
+ UnityPrint(" file=\"");
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR('"');
+ UNITY_OUTPUT_CHAR('>');
+ UnityPrint(Unity.CurrentTestName);
+ UnityPrint("</SRCREF> ");
+#else
+#ifdef UNITY_OUTPUT_FOR_QT_CREATOR
+ UnityPrint("file://");
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrintNumber((UNITY_INT)line);
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(Unity.CurrentTestName);
+ UNITY_OUTPUT_CHAR(':');
+#else
+ UnityPrint(file);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrintNumber((UNITY_INT)line);
+ UNITY_OUTPUT_CHAR(':');
+ UnityPrint(Unity.CurrentTestName);
+ UNITY_OUTPUT_CHAR(':');
+#endif
+#endif
+#endif
+}
+
+/*-----------------------------------------------*/
+static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line)
+{
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrFail);
+ UNITY_OUTPUT_CHAR(':');
+}
+
+/*-----------------------------------------------*/
+void UnityConcludeTest(void)
+{
+ if (Unity.CurrentTestIgnored)
+ {
+ Unity.TestIgnores++;
+ }
+ else if (!Unity.CurrentTestFailed)
+ {
+ UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber);
+ UnityPrint(UnityStrPass);
+ }
+ else
+ {
+ Unity.TestFailures++;
+ }
+
+ Unity.CurrentTestFailed = 0;
+ Unity.CurrentTestIgnored = 0;
+ UNITY_PRINT_EXEC_TIME();
+ UNITY_PRINT_EOL();
+ UNITY_FLUSH_CALL();
+}
+
+/*-----------------------------------------------*/
+static void UnityAddMsgIfSpecified(const char* msg)
+{
+ if (msg)
+ {
+ UnityPrint(UnityStrSpacer);
+#ifndef UNITY_EXCLUDE_DETAILS
+ if (Unity.CurrentDetail1)
+ {
+ UnityPrint(UnityStrDetail1Name);
+ UnityPrint(Unity.CurrentDetail1);
+ if (Unity.CurrentDetail2)
+ {
+ UnityPrint(UnityStrDetail2Name);
+ UnityPrint(Unity.CurrentDetail2);
+ }
+ UnityPrint(UnityStrSpacer);
+ }
+#endif
+ UnityPrint(msg);
+ }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual)
+{
+ UnityPrint(UnityStrExpected);
+ if (expected != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrint(expected);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+ UnityPrint(UnityStrWas);
+ if (actual != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrint(actual);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStringsLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length)
+{
+ UnityPrint(UnityStrExpected);
+ if (expected != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrintLen(expected, length);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+ UnityPrint(UnityStrWas);
+ if (actual != NULL)
+ {
+ UNITY_OUTPUT_CHAR('\'');
+ UnityPrintLen(actual, length);
+ UNITY_OUTPUT_CHAR('\'');
+ }
+ else
+ {
+ UnityPrint(UnityStrNull);
+ }
+}
+
+/*-----------------------------------------------
+ * Assertion & Control Helpers
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_LINE_TYPE lineNumber,
+ const char* msg)
+{
+ /* Both are NULL or same pointer */
+ if (expected == actual) { return 0; }
+
+ /* print and return true if just expected is NULL */
+ if (expected == NULL)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrNullPointerForExpected);
+ UnityAddMsgIfSpecified(msg);
+ return 1;
+ }
+
+ /* print and return true if just actual is NULL */
+ if (actual == NULL)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrNullPointerForActual);
+ UnityAddMsgIfSpecified(msg);
+ return 1;
+ }
+
+ return 0; /* return false if neither is NULL */
+}
+
+/*-----------------------------------------------
+ * Assertion Functions
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+void UnityAssertBits(const UNITY_INT mask,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((mask & expected) != (mask & actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected);
+ UnityPrint(UnityStrWas);
+ UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualNumber(const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (expected != actual)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expected, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
+ const UNITY_INT actual,
+ const UNITY_COMPARISON_T compare,
+ const char *msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ int failed = 0;
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; }
+ if ((threshold == actual)) { failed = 1; }
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; }
+ if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; }
+ }
+ else /* UINT or HEX */
+ {
+ if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; }
+ if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; }
+ }
+
+ if (failed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(actual, style);
+ if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); }
+ if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); }
+ if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); }
+ UnityPrintNumberByStyle(threshold, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#define UnityPrintPointlessAndBail() \
+{ \
+ UnityTestResultsFailBegin(lineNumber); \
+ UnityPrint(UnityStrPointless); \
+ UnityAddMsgIfSpecified(msg); \
+ UNITY_FAIL_AND_BAIL; }
+
+/*-----------------------------------------------*/
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ unsigned int length = style & 0xF;
+ unsigned int increment = 0;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (num_elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while ((elements > 0) && (elements--))
+ {
+ UNITY_INT expect_val;
+ UNITY_INT actual_val;
+
+ switch (length)
+ {
+ case 1:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual;
+ increment = sizeof(UNITY_INT8);
+ break;
+
+ case 2:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual;
+ increment = sizeof(UNITY_INT16);
+ break;
+
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual;
+ increment = sizeof(UNITY_INT64);
+ break;
+#endif
+
+ default: /* default is length 4 bytes */
+ case 4:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual;
+ increment = sizeof(UNITY_INT32);
+ length = 4;
+ break;
+ }
+
+ if (expect_val != actual_val)
+ {
+ if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8)))
+ { /* For UINT, remove sign extension (padding 1's) from signed type casts above */
+ UNITY_INT mask = 1;
+ mask = (mask << 8 * length) - 1;
+ expect_val &= mask;
+ actual_val &= mask;
+ }
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expect_val, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual_val, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ /* Walk through array by incrementing the pointers */
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment);
+ }
+ actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment);
+ }
+}
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_FLOAT
+/* Wrap this define in a function with variable types as float or double */
+#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \
+ if (isinf(expected) && isinf(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \
+ if (UNITY_NAN_CHECK) return 1; \
+ (diff) = (actual) - (expected); \
+ if ((diff) < 0) (diff) = -(diff); \
+ if ((delta) < 0) (delta) = -(delta); \
+ return !(isnan(diff) || isinf(diff) || ((diff) > (delta)))
+ /* This first part of this condition will catch any NaN or Infinite values */
+#ifndef UNITY_NAN_NOT_EQUAL_NAN
+ #define UNITY_NAN_CHECK isnan(expected) && isnan(actual)
+#else
+ #define UNITY_NAN_CHECK 0
+#endif
+
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
+ { \
+ UnityPrint(UnityStrExpected); \
+ UnityPrintFloat(expected); \
+ UnityPrint(UnityStrWas); \
+ UnityPrintFloat(actual); }
+#else
+ #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
+ UnityPrint(UnityStrDelta)
+#endif /* UNITY_EXCLUDE_FLOAT_PRINT */
+
+/*-----------------------------------------------*/
+static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual)
+{
+ UNITY_FLOAT diff;
+ UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected;
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while (elements--)
+ {
+ if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ ptr_expected++;
+ }
+ ptr_actual++;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+
+ if (!UnityFloatsWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style)
+{
+ const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
+ UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
+ UNITY_INT is_trait = !should_be_trait;
+ UNITY_INT trait_index = (UNITY_INT)(style >> 1);
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ switch (style)
+ {
+ case UNITY_FLOAT_IS_INF:
+ case UNITY_FLOAT_IS_NOT_INF:
+ is_trait = isinf(actual) && (actual > 0);
+ break;
+ case UNITY_FLOAT_IS_NEG_INF:
+ case UNITY_FLOAT_IS_NOT_NEG_INF:
+ is_trait = isinf(actual) && (actual < 0);
+ break;
+
+ case UNITY_FLOAT_IS_NAN:
+ case UNITY_FLOAT_IS_NOT_NAN:
+ is_trait = isnan(actual) ? 1 : 0;
+ break;
+
+ case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
+ case UNITY_FLOAT_IS_NOT_DET:
+ is_trait = !isinf(actual) && !isnan(actual);
+ break;
+
+ default:
+ trait_index = 0;
+ trait_names[0] = UnityStrInvalidFloatTrait;
+ break;
+ }
+
+ if (is_trait != should_be_trait)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ if (!should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+ UnityPrint(UnityStrWas);
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ UnityPrintFloat((UNITY_DOUBLE)actual);
+#else
+ if (should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+#endif
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#endif /* not UNITY_EXCLUDE_FLOAT */
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_DOUBLE
+static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual)
+{
+ UNITY_DOUBLE diff;
+ UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected;
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while (elements--)
+ {
+ if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ ptr_expected++;
+ }
+ ptr_actual++;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (!UnityDoublesWithin(delta, expected, actual))
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style)
+{
+ const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
+ UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
+ UNITY_INT is_trait = !should_be_trait;
+ UNITY_INT trait_index = (UNITY_INT)(style >> 1);
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ switch (style)
+ {
+ case UNITY_FLOAT_IS_INF:
+ case UNITY_FLOAT_IS_NOT_INF:
+ is_trait = isinf(actual) && (actual > 0);
+ break;
+ case UNITY_FLOAT_IS_NEG_INF:
+ case UNITY_FLOAT_IS_NOT_NEG_INF:
+ is_trait = isinf(actual) && (actual < 0);
+ break;
+
+ case UNITY_FLOAT_IS_NAN:
+ case UNITY_FLOAT_IS_NOT_NAN:
+ is_trait = isnan(actual) ? 1 : 0;
+ break;
+
+ case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
+ case UNITY_FLOAT_IS_NOT_DET:
+ is_trait = !isinf(actual) && !isnan(actual);
+ break;
+
+ default:
+ trait_index = 0;
+ trait_names[0] = UnityStrInvalidFloatTrait;
+ break;
+ }
+
+ if (is_trait != should_be_trait)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrExpected);
+ if (!should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+ UnityPrint(UnityStrWas);
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+ UnityPrintFloat(actual);
+#else
+ if (should_be_trait)
+ {
+ UnityPrint(UnityStrNot);
+ }
+ UnityPrint(trait_names[trait_index]);
+#endif
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+#endif /* not UNITY_EXCLUDE_DOUBLE */
+
+/*-----------------------------------------------*/
+void UnityAssertNumbersWithin(const UNITY_UINT delta,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (actual > expected)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta);
+ }
+ }
+ else
+ {
+ if ((UNITY_UINT)actual > (UNITY_UINT)expected)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta);
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrDelta);
+ UnityPrintNumberByStyle((UNITY_INT)delta, style);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expected, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertNumbersArrayWithin(const UNITY_UINT delta,
+ UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 elements = num_elements;
+ unsigned int length = style & 0xF;
+ unsigned int increment = 0;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if (num_elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while ((elements > 0) && (elements--))
+ {
+ UNITY_INT expect_val;
+ UNITY_INT actual_val;
+
+ switch (length)
+ {
+ case 1:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual;
+ increment = sizeof(UNITY_INT8);
+ break;
+
+ case 2:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual;
+ increment = sizeof(UNITY_INT16);
+ break;
+
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual;
+ increment = sizeof(UNITY_INT64);
+ break;
+#endif
+
+ default: /* default is length 4 bytes */
+ case 4:
+ expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected;
+ actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual;
+ increment = sizeof(UNITY_INT32);
+ length = 4;
+ break;
+ }
+
+ if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+ {
+ if (actual_val > expect_val)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta);
+ }
+ }
+ else
+ {
+ if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val)
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta);
+ }
+ else
+ {
+ Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta);
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8)))
+ { /* For UINT, remove sign extension (padding 1's) from signed type casts above */
+ UNITY_INT mask = 1;
+ mask = (mask << 8 * length) - 1;
+ expect_val &= mask;
+ actual_val &= mask;
+ }
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrDelta);
+ UnityPrintNumberByStyle((UNITY_INT)delta, style);
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(expect_val, style);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(actual_val, style);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ /* Walk through array by incrementing the pointers */
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment);
+ }
+ actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment);
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualString(const char* expected,
+ const char* actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ UNITY_UINT32 i;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if both pointers not null compare the strings */
+ if (expected && actual)
+ {
+ for (i = 0; expected[i] || actual[i]; i++)
+ {
+ if (expected[i] != actual[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expected != actual)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrintExpectedAndActualStrings(expected, actual);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber)
+{
+ UNITY_UINT32 i;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if both pointers not null compare the strings */
+ if (expected && actual)
+ {
+ for (i = 0; (i < length) && (expected[i] || actual[i]); i++)
+ {
+ if (expected[i] != actual[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expected != actual)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrintExpectedAndActualStringsLen(expected, actual, length);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
+ const char** actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_UINT32 i = 0;
+ UNITY_UINT32 j = 0;
+ const char* expd = NULL;
+ const char* act = NULL;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ /* if no elements, it's an error */
+ if (num_elements == 0)
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if ((const void*)expected == (const void*)actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ if (flags != UNITY_ARRAY_TO_ARRAY)
+ {
+ expd = (const char*)expected;
+ }
+
+ do
+ {
+ act = actual[j];
+ if (flags == UNITY_ARRAY_TO_ARRAY)
+ {
+ expd = ((const char* const*)expected)[j];
+ }
+
+ /* if both pointers not null compare the strings */
+ if (expd && act)
+ {
+ for (i = 0; expd[i] || act[i]; i++)
+ {
+ if (expd[i] != act[i])
+ {
+ Unity.CurrentTestFailed = 1;
+ break;
+ }
+ }
+ }
+ else
+ { /* handle case of one pointers being null (if both null, test should pass) */
+ if (expd != act)
+ {
+ Unity.CurrentTestFailed = 1;
+ }
+ }
+
+ if (Unity.CurrentTestFailed)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ if (num_elements > 1)
+ {
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(j);
+ }
+ UnityPrintExpectedAndActualStrings(expd, act);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ } while (++j < num_elements);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 length,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags)
+{
+ UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
+ UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual;
+ UNITY_UINT32 elements = num_elements;
+ UNITY_UINT32 bytes;
+
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ if ((elements == 0) || (length == 0))
+ {
+ UnityPrintPointlessAndBail();
+ }
+
+ if (expected == actual)
+ {
+ return; /* Both are NULL or same pointer */
+ }
+
+ if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
+ {
+ UNITY_FAIL_AND_BAIL;
+ }
+
+ while (elements--)
+ {
+ bytes = length;
+ while (bytes--)
+ {
+ if (*ptr_exp != *ptr_act)
+ {
+ UnityTestResultsFailBegin(lineNumber);
+ UnityPrint(UnityStrMemory);
+ if (num_elements > 1)
+ {
+ UnityPrint(UnityStrElement);
+ UnityPrintNumberUnsigned(num_elements - elements - 1);
+ }
+ UnityPrint(UnityStrByte);
+ UnityPrintNumberUnsigned(length - bytes - 1);
+ UnityPrint(UnityStrExpected);
+ UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8);
+ UnityPrint(UnityStrWas);
+ UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8);
+ UnityAddMsgIfSpecified(msg);
+ UNITY_FAIL_AND_BAIL;
+ }
+ ptr_exp++;
+ ptr_act++;
+ }
+ if (flags == UNITY_ARRAY_TO_VAL)
+ {
+ ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
+ }
+ }
+}
+
+/*-----------------------------------------------*/
+
+static union
+{
+ UNITY_INT8 i8;
+ UNITY_INT16 i16;
+ UNITY_INT32 i32;
+#ifdef UNITY_SUPPORT_64
+ UNITY_INT64 i64;
+#endif
+#ifndef UNITY_EXCLUDE_FLOAT
+ float f;
+#endif
+#ifndef UNITY_EXCLUDE_DOUBLE
+ double d;
+#endif
+} UnityQuickCompare;
+
+UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size)
+{
+ switch(size)
+ {
+ case 1:
+ UnityQuickCompare.i8 = (UNITY_INT8)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8);
+
+ case 2:
+ UnityQuickCompare.i16 = (UNITY_INT16)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16);
+
+#ifdef UNITY_SUPPORT_64
+ case 8:
+ UnityQuickCompare.i64 = (UNITY_INT64)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64);
+#endif
+
+ default: /* 4 bytes */
+ UnityQuickCompare.i32 = (UNITY_INT32)num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32);
+ }
+}
+
+#ifndef UNITY_EXCLUDE_FLOAT
+/*-----------------------------------------------*/
+UNITY_INTERNAL_PTR UnityFloatToPtr(const float num)
+{
+ UnityQuickCompare.f = num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f);
+}
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+/*-----------------------------------------------*/
+UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
+{
+ UnityQuickCompare.d = num;
+ return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d);
+}
+#endif
+
+/*-----------------------------------------------
+ * Control Functions
+ *-----------------------------------------------*/
+
+/*-----------------------------------------------*/
+void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrFail);
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+
+#ifndef UNITY_EXCLUDE_DETAILS
+ if (Unity.CurrentDetail1)
+ {
+ UnityPrint(UnityStrDetail1Name);
+ UnityPrint(Unity.CurrentDetail1);
+ if (Unity.CurrentDetail2)
+ {
+ UnityPrint(UnityStrDetail2Name);
+ UnityPrint(Unity.CurrentDetail2);
+ }
+ UnityPrint(UnityStrSpacer);
+ }
+#endif
+ if (msg[0] != ' ')
+ {
+ UNITY_OUTPUT_CHAR(' ');
+ }
+ UnityPrint(msg);
+ }
+
+ UNITY_FAIL_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
+{
+ RETURN_IF_FAIL_OR_IGNORE;
+
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint(UnityStrIgnore);
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(msg);
+ }
+ UNITY_IGNORE_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+void UnityMessage(const char* msg, const UNITY_LINE_TYPE line)
+{
+ UnityTestResultsBegin(Unity.TestFile, line);
+ UnityPrint("INFO");
+ if (msg != NULL)
+ {
+ UNITY_OUTPUT_CHAR(':');
+ UNITY_OUTPUT_CHAR(' ');
+ UnityPrint(msg);
+ }
+ UNITY_PRINT_EOL();
+}
+
+/*-----------------------------------------------*/
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum)
+{
+ Unity.CurrentTestName = FuncName;
+ Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum;
+ Unity.NumberOfTests++;
+ UNITY_CLR_DETAILS();
+ UNITY_EXEC_TIME_START();
+ if (TEST_PROTECT())
+ {
+ setUp();
+ Func();
+ }
+ if (TEST_PROTECT())
+ {
+ tearDown();
+ }
+ UNITY_EXEC_TIME_STOP();
+ UnityConcludeTest();
+}
+
+/*-----------------------------------------------*/
+void UnitySetTestFile(const char* filename)
+{
+ Unity.TestFile = filename;
+}
+
+/*-----------------------------------------------*/
+void UnityBegin(const char* filename)
+{
+ Unity.TestFile = filename;
+ Unity.CurrentTestName = NULL;
+ Unity.CurrentTestLineNumber = 0;
+ Unity.NumberOfTests = 0;
+ Unity.TestFailures = 0;
+ Unity.TestIgnores = 0;
+ Unity.CurrentTestFailed = 0;
+ Unity.CurrentTestIgnored = 0;
+
+ UNITY_CLR_DETAILS();
+ UNITY_OUTPUT_START();
+}
+
+/*-----------------------------------------------*/
+int UnityEnd(void)
+{
+ UNITY_PRINT_EOL();
+ UnityPrint(UnityStrBreaker);
+ UNITY_PRINT_EOL();
+ UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests));
+ UnityPrint(UnityStrResultsTests);
+ UnityPrintNumber((UNITY_INT)(Unity.TestFailures));
+ UnityPrint(UnityStrResultsFailures);
+ UnityPrintNumber((UNITY_INT)(Unity.TestIgnores));
+ UnityPrint(UnityStrResultsIgnored);
+ UNITY_PRINT_EOL();
+ if (Unity.TestFailures == 0U)
+ {
+ UnityPrint(UnityStrOk);
+ }
+ else
+ {
+ UnityPrint(UnityStrFail);
+#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL
+ UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D');
+#endif
+ }
+ UNITY_PRINT_EOL();
+ UNITY_FLUSH_CALL();
+ UNITY_OUTPUT_COMPLETE();
+ return (int)(Unity.TestFailures);
+}
+
+/*-----------------------------------------------
+ * Command Line Argument Support
+ *-----------------------------------------------*/
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+
+char* UnityOptionIncludeNamed = NULL;
+char* UnityOptionExcludeNamed = NULL;
+int UnityVerbosity = 1;
+
+/*-----------------------------------------------*/
+int UnityParseOptions(int argc, char** argv)
+{
+ int i;
+ UnityOptionIncludeNamed = NULL;
+ UnityOptionExcludeNamed = NULL;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'l': /* list tests */
+ return -1;
+ case 'n': /* include tests with name including this string */
+ case 'f': /* an alias for -n */
+ if (argv[i][2] == '=')
+ {
+ UnityOptionIncludeNamed = &argv[i][3];
+ }
+ else if (++i < argc)
+ {
+ UnityOptionIncludeNamed = argv[i];
+ }
+ else
+ {
+ UnityPrint("ERROR: No Test String to Include Matches For");
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ break;
+ case 'q': /* quiet */
+ UnityVerbosity = 0;
+ break;
+ case 'v': /* verbose */
+ UnityVerbosity = 2;
+ break;
+ case 'x': /* exclude tests with name including this string */
+ if (argv[i][2] == '=')
+ {
+ UnityOptionExcludeNamed = &argv[i][3];
+ }
+ else if (++i < argc)
+ {
+ UnityOptionExcludeNamed = argv[i];
+ }
+ else
+ {
+ UnityPrint("ERROR: No Test String to Exclude Matches For");
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ break;
+ default:
+ UnityPrint("ERROR: Unknown Option ");
+ UNITY_OUTPUT_CHAR(argv[i][1]);
+ UNITY_PRINT_EOL();
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------*/
+int IsStringInBiggerString(const char* longstring, const char* shortstring)
+{
+ const char* lptr = longstring;
+ const char* sptr = shortstring;
+ const char* lnext = lptr;
+
+ if (*sptr == '*')
+ {
+ return 1;
+ }
+
+ while (*lptr)
+ {
+ lnext = lptr + 1;
+
+ /* If they current bytes match, go on to the next bytes */
+ while (*lptr && *sptr && (*lptr == *sptr))
+ {
+ lptr++;
+ sptr++;
+
+ /* We're done if we match the entire string or up to a wildcard */
+ if (*sptr == '*')
+ return 1;
+ if (*sptr == ',')
+ return 1;
+ if (*sptr == '"')
+ return 1;
+ if (*sptr == '\'')
+ return 1;
+ if (*sptr == ':')
+ return 2;
+ if (*sptr == 0)
+ return 1;
+ }
+
+ /* Otherwise we start in the long pointer 1 character further and try again */
+ lptr = lnext;
+ sptr = shortstring;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------*/
+int UnityStringArgumentMatches(const char* str)
+{
+ int retval;
+ const char* ptr1;
+ const char* ptr2;
+ const char* ptrf;
+
+ /* Go through the options and get the substrings for matching one at a time */
+ ptr1 = str;
+ while (ptr1[0] != 0)
+ {
+ if ((ptr1[0] == '"') || (ptr1[0] == '\''))
+ {
+ ptr1++;
+ }
+
+ /* look for the start of the next partial */
+ ptr2 = ptr1;
+ ptrf = 0;
+ do
+ {
+ ptr2++;
+ if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','))
+ {
+ ptrf = &ptr2[1];
+ }
+ } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','));
+
+ while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ',')))
+ {
+ ptr2++;
+ }
+
+ /* done if complete filename match */
+ retval = IsStringInBiggerString(Unity.TestFile, ptr1);
+ if (retval == 1)
+ {
+ return retval;
+ }
+
+ /* done if testname match after filename partial match */
+ if ((retval == 2) && (ptrf != 0))
+ {
+ if (IsStringInBiggerString(Unity.CurrentTestName, ptrf))
+ {
+ return 1;
+ }
+ }
+
+ /* done if complete testname match */
+ if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1)
+ {
+ return 1;
+ }
+
+ ptr1 = ptr2;
+ }
+
+ /* we couldn't find a match for any substrings */
+ return 0;
+}
+
+/*-----------------------------------------------*/
+int UnityTestMatches(void)
+{
+ /* Check if this test name matches the included test pattern */
+ int retval;
+ if (UnityOptionIncludeNamed)
+ {
+ retval = UnityStringArgumentMatches(UnityOptionIncludeNamed);
+ }
+ else
+ {
+ retval = 1;
+ }
+
+ /* Check if this test name matches the excluded test pattern */
+ if (UnityOptionExcludeNamed)
+ {
+ if (UnityStringArgumentMatches(UnityOptionExcludeNamed))
+ {
+ retval = 0;
+ }
+ }
+
+ return retval;
+}
+
+#endif /* UNITY_USE_COMMAND_LINE_ARGS */
+/*-----------------------------------------------*/
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.h b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.h
new file mode 100755
index 00000000..34d7f93a
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity.h
@@ -0,0 +1,617 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_FRAMEWORK_H
+#define UNITY_FRAMEWORK_H
+#define UNITY
+
+#define UNITY_VERSION_MAJOR 2
+#define UNITY_VERSION_MINOR 5
+#define UNITY_VERSION_BUILD 0
+#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD)
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "unity_internals.h"
+
+/*-------------------------------------------------------
+ * Test Setup / Teardown
+ *-------------------------------------------------------*/
+
+/* These functions are intended to be called before and after each test.
+ * If using unity directly, these will need to be provided for each test
+ * executable built. If you are using the test runner generator and/or
+ * Ceedling, these are optional. */
+void setUp(void);
+void tearDown(void);
+
+/* These functions are intended to be called at the beginning and end of an
+ * entire test suite. suiteTearDown() is passed the number of tests that
+ * failed, and its return value becomes the exit code of main(). If using
+ * Unity directly, you're in charge of calling these if they are desired.
+ * If using Ceedling or the test runner generator, these will be called
+ * automatically if they exist. */
+void suiteSetUp(void);
+int suiteTearDown(int num_failures);
+
+/*-------------------------------------------------------
+ * Test Reset and Verify
+ *-------------------------------------------------------*/
+
+/* These functions are intended to be called before during tests in order
+ * to support complex test loops, etc. Both are NOT built into Unity. Instead
+ * the test runner generator will create them. resetTest will run teardown and
+ * setup again, verifying any end-of-test needs between. verifyTest will only
+ * run the verification. */
+void resetTest(void);
+void verifyTest(void);
+
+/*-------------------------------------------------------
+ * Configuration Options
+ *-------------------------------------------------------
+ * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
+
+ * Integers/longs/pointers
+ * - Unity attempts to automatically discover your integer sizes
+ * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
+ * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
+ * - If you cannot use the automatic methods above, you can force Unity by using these options:
+ * - define UNITY_SUPPORT_64
+ * - set UNITY_INT_WIDTH
+ * - set UNITY_LONG_WIDTH
+ * - set UNITY_POINTER_WIDTH
+
+ * Floats
+ * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
+ * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
+ * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
+ * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
+ * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
+ * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
+ * - define UNITY_DOUBLE_TYPE to specify something other than double
+ * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors
+
+ * Output
+ * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
+ * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
+
+ * Optimization
+ * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
+ * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
+
+ * Test Cases
+ * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
+
+ * Parameterized Tests
+ * - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing
+
+ * Tests with Arguments
+ * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity
+
+ *-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message))
+#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
+#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message))
+#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
+#define TEST_MESSAGE(message) UnityMessage((message), __LINE__)
+#define TEST_ONLY()
+
+/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
+ * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
+#define TEST_PASS() TEST_ABORT()
+#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while(0)
+
+/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out
+ * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */
+#define TEST_FILE(a)
+
+/*-------------------------------------------------------
+ * Test Asserts (simple)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
+#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
+#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
+#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
+#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
+#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
+
+/* Integer Greater Than/ Less Than (of all sizes) */
+#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
+
+#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
+#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL)
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+
+/* Integer Array Ranges (of all sizes) */
+#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL)
+
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+
+/* Arrays Compared To Single Value */
+#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL)
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/* Shorthand */
+#ifdef UNITY_SHORTHAND_AS_OLD
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
+#endif
+#ifdef UNITY_SHORTHAND_AS_INT
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_MEM
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_RAW
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal")
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
+#endif
+#ifdef UNITY_SHORTHAND_AS_NONE
+#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+
+/*-------------------------------------------------------
+ * Test Asserts (with additional messages)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
+#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
+#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
+#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
+#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message))
+#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message))
+
+/* Integer Greater Than/ Less Than (of all sizes) */
+#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
+
+#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
+#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message))
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message))
+
+/* Integer Array Ranges (of all sizes) */
+#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message))
+
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+
+/* Arrays Compared To Single Value*/
+#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message))
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* Shorthand */
+#ifdef UNITY_SHORTHAND_AS_OLD
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message))
+#endif
+#ifdef UNITY_SHORTHAND_AS_INT
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_MEM
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+#ifdef UNITY_SHORTHAND_AS_RAW
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message)
+#endif
+#ifdef UNITY_SHORTHAND_AS_NONE
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand)
+#endif
+
+/* end of UNITY_FRAMEWORK_H */
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tinyusb/test/vendor/ceedling/vendor/unity/src/unity_internals.h b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity_internals.h
new file mode 100755
index 00000000..a9a7ea23
--- /dev/null
+++ b/tinyusb/test/vendor/ceedling/vendor/unity/src/unity_internals.h
@@ -0,0 +1,1002 @@
+/* ==========================================
+ Unity Project - A Test Framework for C
+ Copyright (c) 2007-19 Mike Karlesky, Mark VanderVoord, Greg Williams
+ [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_INTERNALS_H
+#define UNITY_INTERNALS_H
+
+#ifdef UNITY_INCLUDE_CONFIG_H
+#include "unity_config.h"
+#endif
+
+#ifndef UNITY_EXCLUDE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_MATH_H
+#include <math.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef UNITY_INCLUDE_PRINT_FORMATTED
+#include <stdarg.h>
+#endif
+
+/* Unity Attempts to Auto-Detect Integer Types
+ * Attempt 1: UINT_MAX, ULONG_MAX in <limits.h>, or default to 32 bits
+ * Attempt 2: UINTPTR_MAX in <stdint.h>, or default to same size as long
+ * The user may override any of these derived constants:
+ * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */
+#ifndef UNITY_EXCLUDE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_LIMITS_H
+#include <limits.h>
+#endif
+
+/*-------------------------------------------------------
+ * Guess Widths If Not Specified
+ *-------------------------------------------------------*/
+
+/* Determine the size of an int, if not already specified.
+ * We cannot use sizeof(int), because it is not yet defined
+ * at this stage in the translation of the C program.
+ * Also sizeof(int) does return the size in addressable units on all platforms,
+ * which may not necessarily be the size in bytes.
+ * Therefore, infer it from UINT_MAX if possible. */
+#ifndef UNITY_INT_WIDTH
+ #ifdef UINT_MAX
+ #if (UINT_MAX == 0xFFFF)
+ #define UNITY_INT_WIDTH (16)
+ #elif (UINT_MAX == 0xFFFFFFFF)
+ #define UNITY_INT_WIDTH (32)
+ #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_INT_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_INT_WIDTH (32)
+ #endif /* UINT_MAX */
+#endif
+
+/* Determine the size of a long, if not already specified. */
+#ifndef UNITY_LONG_WIDTH
+ #ifdef ULONG_MAX
+ #if (ULONG_MAX == 0xFFFF)
+ #define UNITY_LONG_WIDTH (16)
+ #elif (ULONG_MAX == 0xFFFFFFFF)
+ #define UNITY_LONG_WIDTH (32)
+ #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_LONG_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_LONG_WIDTH (32)
+ #endif /* ULONG_MAX */
+#endif
+
+/* Determine the size of a pointer, if not already specified. */
+#ifndef UNITY_POINTER_WIDTH
+ #ifdef UINTPTR_MAX
+ #if (UINTPTR_MAX <= 0xFFFF)
+ #define UNITY_POINTER_WIDTH (16)
+ #elif (UINTPTR_MAX <= 0xFFFFFFFF)
+ #define UNITY_POINTER_WIDTH (32)
+ #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF)
+ #define UNITY_POINTER_WIDTH (64)
+ #endif
+ #else /* Set to default */
+ #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH
+ #endif /* UINTPTR_MAX */
+#endif
+
+/*-------------------------------------------------------
+ * Int Support (Define types based on detected sizes)
+ *-------------------------------------------------------*/
+
+#if (UNITY_INT_WIDTH == 32)
+ typedef unsigned char UNITY_UINT8;
+ typedef unsigned short UNITY_UINT16;
+ typedef unsigned int UNITY_UINT32;
+ typedef signed char UNITY_INT8;
+ typedef signed short UNITY_INT16;
+ typedef signed int UNITY_INT32;
+#elif (UNITY_INT_WIDTH == 16)
+ typedef unsigned char UNITY_UINT8;
+ typedef unsigned int UNITY_UINT16;
+ typedef unsigned long UNITY_UINT32;
+ typedef signed char UNITY_INT8;
+ typedef signed int UNITY_INT16;
+ typedef signed long UNITY_INT32;
+#else
+ #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported)
+#endif
+
+/*-------------------------------------------------------
+ * 64-bit Support
+ *-------------------------------------------------------*/
+
+/* Auto-detect 64 Bit Support */
+#ifndef UNITY_SUPPORT_64
+ #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64
+ #define UNITY_SUPPORT_64
+ #endif
+#endif
+
+/* 64-Bit Support Dependent Configuration */
+#ifndef UNITY_SUPPORT_64
+ /* No 64-bit Support */
+ typedef UNITY_UINT32 UNITY_UINT;
+ typedef UNITY_INT32 UNITY_INT;
+ #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */
+#else
+ /* 64-bit Support */
+ #if (UNITY_LONG_WIDTH == 32)
+ typedef unsigned long long UNITY_UINT64;
+ typedef signed long long UNITY_INT64;
+ #elif (UNITY_LONG_WIDTH == 64)
+ typedef unsigned long UNITY_UINT64;
+ typedef signed long UNITY_INT64;
+ #else
+ #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported)
+ #endif
+ typedef UNITY_UINT64 UNITY_UINT;
+ typedef UNITY_INT64 UNITY_INT;
+ #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */
+#endif
+
+/*-------------------------------------------------------
+ * Pointer Support
+ *-------------------------------------------------------*/
+
+#if (UNITY_POINTER_WIDTH == 32)
+ #define UNITY_PTR_TO_INT UNITY_INT32
+ #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32
+#elif (UNITY_POINTER_WIDTH == 64)
+ #define UNITY_PTR_TO_INT UNITY_INT64
+ #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64
+#elif (UNITY_POINTER_WIDTH == 16)
+ #define UNITY_PTR_TO_INT UNITY_INT16
+ #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16
+#else
+ #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported)
+#endif
+
+#ifndef UNITY_PTR_ATTRIBUTE
+ #define UNITY_PTR_ATTRIBUTE
+#endif
+
+#ifndef UNITY_INTERNAL_PTR
+ #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void*
+#endif
+
+/*-------------------------------------------------------
+ * Float Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_FLOAT
+
+/* No Floating Point Support */
+#ifndef UNITY_EXCLUDE_DOUBLE
+#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */
+#endif
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+#define UNITY_EXCLUDE_FLOAT_PRINT
+#endif
+
+#else
+
+/* Floating Point Support */
+#ifndef UNITY_FLOAT_PRECISION
+#define UNITY_FLOAT_PRECISION (0.00001f)
+#endif
+#ifndef UNITY_FLOAT_TYPE
+#define UNITY_FLOAT_TYPE float
+#endif
+typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
+
+/* isinf & isnan macros should be provided by math.h */
+#ifndef isinf
+/* The value of Inf - Inf is NaN */
+#define isinf(n) (isnan((n) - (n)) && !isnan(n))
+#endif
+
+#ifndef isnan
+/* NaN is the only floating point value that does NOT equal itself.
+ * Therefore if n != n, then it is NaN. */
+#define isnan(n) ((n != n) ? 1 : 0)
+#endif
+
+#endif
+
+/*-------------------------------------------------------
+ * Double Float Support
+ *-------------------------------------------------------*/
+
+/* unlike float, we DON'T include by default */
+#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE)
+
+ /* No Floating Point Support */
+ #ifndef UNITY_EXCLUDE_DOUBLE
+ #define UNITY_EXCLUDE_DOUBLE
+ #else
+ #undef UNITY_INCLUDE_DOUBLE
+ #endif
+
+ #ifndef UNITY_EXCLUDE_FLOAT
+ #ifndef UNITY_DOUBLE_TYPE
+ #define UNITY_DOUBLE_TYPE double
+ #endif
+ typedef UNITY_FLOAT UNITY_DOUBLE;
+ /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */
+ #endif
+
+#else
+
+ /* Double Floating Point Support */
+ #ifndef UNITY_DOUBLE_PRECISION
+ #define UNITY_DOUBLE_PRECISION (1e-12)
+ #endif
+
+ #ifndef UNITY_DOUBLE_TYPE
+ #define UNITY_DOUBLE_TYPE double
+ #endif
+ typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE;
+
+#endif
+
+/*-------------------------------------------------------
+ * Output Method: stdout (DEFAULT)
+ *-------------------------------------------------------*/
+#ifndef UNITY_OUTPUT_CHAR
+ /* Default to using putchar, which is defined in stdio.h */
+ #include <stdio.h>
+ #define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
+#else
+ /* If defined as something else, make sure we declare it here so it's ready for use */
+ #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION
+ extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION;
+ #endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+ #ifdef UNITY_USE_FLUSH_STDOUT
+ /* We want to use the stdout flush utility */
+ #include <stdio.h>
+ #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout)
+ #else
+ /* We've specified nothing, therefore flush should just be ignored */
+ #define UNITY_OUTPUT_FLUSH()
+ #endif
+#else
+ /* If defined as something else, make sure we declare it here so it's ready for use */
+ #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION
+ extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION;
+ #endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+#define UNITY_FLUSH_CALL()
+#else
+#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH()
+#endif
+
+#ifndef UNITY_PRINT_EOL
+#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n')
+#endif
+
+#ifndef UNITY_OUTPUT_START
+#define UNITY_OUTPUT_START()
+#endif
+
+#ifndef UNITY_OUTPUT_COMPLETE
+#define UNITY_OUTPUT_COMPLETE()
+#endif
+
+#ifdef UNITY_INCLUDE_EXEC_TIME
+ #if !defined(UNITY_EXEC_TIME_START) && \
+ !defined(UNITY_EXEC_TIME_STOP) && \
+ !defined(UNITY_PRINT_EXEC_TIME) && \
+ !defined(UNITY_TIME_TYPE)
+ /* If none any of these macros are defined then try to provide a default implementation */
+
+ #if defined(UNITY_CLOCK_MS)
+ /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */
+ #define UNITY_TIME_TYPE UNITY_UINT
+ #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS()
+ #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS()
+ #define UNITY_PRINT_EXEC_TIME() { \
+ UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \
+ UnityPrint(" ("); \
+ UnityPrintNumberUnsigned(execTimeMs); \
+ UnityPrint(" ms)"); \
+ }
+ #elif defined(_WIN32)
+ #include <time.h>
+ #define UNITY_TIME_TYPE clock_t
+ #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC)
+ #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime)
+ #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime)
+ #define UNITY_PRINT_EXEC_TIME() { \
+ UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \
+ UnityPrint(" ("); \
+ UnityPrintNumberUnsigned(execTimeMs); \
+ UnityPrint(" ms)"); \
+ }
+ #elif defined(__unix__)
+ #include <time.h>
+ #define UNITY_TIME_TYPE struct timespec
+ #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t)
+ #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime)
+ #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime)
+ #define UNITY_PRINT_EXEC_TIME() { \
+ UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \
+ execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \
+ UnityPrint(" ("); \
+ UnityPrintNumberUnsigned(execTimeMs); \
+ UnityPrint(" ms)"); \
+ }
+ #endif
+ #endif
+#endif
+
+#ifndef UNITY_EXEC_TIME_START
+#define UNITY_EXEC_TIME_START() do{}while(0)
+#endif
+
+#ifndef UNITY_EXEC_TIME_STOP
+#define UNITY_EXEC_TIME_STOP() do{}while(0)
+#endif
+
+#ifndef UNITY_TIME_TYPE
+#define UNITY_TIME_TYPE UNITY_UINT
+#endif
+
+#ifndef UNITY_PRINT_EXEC_TIME
+#define UNITY_PRINT_EXEC_TIME() do{}while(0)
+#endif
+
+/*-------------------------------------------------------
+ * Footprint
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_LINE_TYPE
+#define UNITY_LINE_TYPE UNITY_UINT
+#endif
+
+#ifndef UNITY_COUNTER_TYPE
+#define UNITY_COUNTER_TYPE UNITY_UINT
+#endif
+
+/*-------------------------------------------------------
+ * Internal Structs Needed
+ *-------------------------------------------------------*/
+
+typedef void (*UnityTestFunction)(void);
+
+#define UNITY_DISPLAY_RANGE_INT (0x10)
+#define UNITY_DISPLAY_RANGE_UINT (0x20)
+#define UNITY_DISPLAY_RANGE_HEX (0x40)
+#define UNITY_DISPLAY_RANGE_CHAR (0x80)
+
+typedef enum
+{
+ UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT,
+ UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT,
+#endif
+
+ UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT,
+ UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT,
+#endif
+
+ UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX,
+ UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX,
+ UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX,
+#ifdef UNITY_SUPPORT_64
+ UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX,
+#endif
+
+ UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT,
+
+ UNITY_DISPLAY_STYLE_UNKNOWN
+} UNITY_DISPLAY_STYLE_T;
+
+typedef enum
+{
+ UNITY_WITHIN = 0x0,
+ UNITY_EQUAL_TO = 0x1,
+ UNITY_GREATER_THAN = 0x2,
+ UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO,
+ UNITY_SMALLER_THAN = 0x4,
+ UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO,
+ UNITY_UNKNOWN
+} UNITY_COMPARISON_T;
+
+#ifndef UNITY_EXCLUDE_FLOAT
+typedef enum UNITY_FLOAT_TRAIT
+{
+ UNITY_FLOAT_IS_NOT_INF = 0,
+ UNITY_FLOAT_IS_INF,
+ UNITY_FLOAT_IS_NOT_NEG_INF,
+ UNITY_FLOAT_IS_NEG_INF,
+ UNITY_FLOAT_IS_NOT_NAN,
+ UNITY_FLOAT_IS_NAN,
+ UNITY_FLOAT_IS_NOT_DET,
+ UNITY_FLOAT_IS_DET,
+ UNITY_FLOAT_INVALID_TRAIT
+} UNITY_FLOAT_TRAIT_T;
+#endif
+
+typedef enum
+{
+ UNITY_ARRAY_TO_VAL = 0,
+ UNITY_ARRAY_TO_ARRAY,
+ UNITY_ARRAY_UNKNOWN
+} UNITY_FLAGS_T;
+
+struct UNITY_STORAGE_T
+{
+ const char* TestFile;
+ const char* CurrentTestName;
+#ifndef UNITY_EXCLUDE_DETAILS
+ const char* CurrentDetail1;
+ const char* CurrentDetail2;
+#endif
+ UNITY_LINE_TYPE CurrentTestLineNumber;
+ UNITY_COUNTER_TYPE NumberOfTests;
+ UNITY_COUNTER_TYPE TestFailures;
+ UNITY_COUNTER_TYPE TestIgnores;
+ UNITY_COUNTER_TYPE CurrentTestFailed;
+ UNITY_COUNTER_TYPE CurrentTestIgnored;
+#ifdef UNITY_INCLUDE_EXEC_TIME
+ UNITY_TIME_TYPE CurrentTestStartTime;
+ UNITY_TIME_TYPE CurrentTestStopTime;
+#endif
+#ifndef UNITY_EXCLUDE_SETJMP_H
+ jmp_buf AbortFrame;
+#endif
+};
+
+extern struct UNITY_STORAGE_T Unity;
+
+/*-------------------------------------------------------
+ * Test Suite Management
+ *-------------------------------------------------------*/
+
+void UnityBegin(const char* filename);
+int UnityEnd(void);
+void UnitySetTestFile(const char* filename);
+void UnityConcludeTest(void);
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum);
+
+/*-------------------------------------------------------
+ * Details Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_DETAILS
+#define UNITY_CLR_DETAILS()
+#define UNITY_SET_DETAIL(d1)
+#define UNITY_SET_DETAILS(d1,d2)
+#else
+#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; }
+#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; }
+#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); }
+
+#ifndef UNITY_DETAIL1_NAME
+#define UNITY_DETAIL1_NAME "Function"
+#endif
+
+#ifndef UNITY_DETAIL2_NAME
+#define UNITY_DETAIL2_NAME "Argument"
+#endif
+#endif
+
+/*-------------------------------------------------------
+ * Test Output
+ *-------------------------------------------------------*/
+
+void UnityPrint(const char* string);
+
+#ifdef UNITY_INCLUDE_PRINT_FORMATTED
+void UnityPrintFormatted(const char* format, ...);
+#endif
+
+void UnityPrintLen(const char* string, const UNITY_UINT32 length);
+void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number);
+void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style);
+void UnityPrintNumber(const UNITY_INT number_to_print);
+void UnityPrintNumberUnsigned(const UNITY_UINT number);
+void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print);
+
+#ifndef UNITY_EXCLUDE_FLOAT_PRINT
+void UnityPrintFloat(const UNITY_DOUBLE input_number);
+#endif
+
+/*-------------------------------------------------------
+ * Test Assertion Functions
+ *-------------------------------------------------------
+ * Use the macros below this section instead of calling
+ * these directly. The macros have a consistent naming
+ * convention and will pull in file and line information
+ * for you. */
+
+void UnityAssertEqualNumber(const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
+ const UNITY_INT actual,
+ const UNITY_COMPARISON_T compare,
+ const char *msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertBits(const UNITY_INT mask,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualString(const char* expected,
+ const char* actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringLen(const char* expected,
+ const char* actual,
+ const UNITY_UINT32 length,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected,
+ const char** actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 length,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertNumbersWithin(const UNITY_UINT delta,
+ const UNITY_INT expected,
+ const UNITY_INT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertNumbersArrayWithin(const UNITY_UINT delta,
+ UNITY_INTERNAL_PTR expected,
+ UNITY_INTERNAL_PTR actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_DISPLAY_STYLE_T style,
+ const UNITY_FLAGS_T flags);
+
+void UnityFail(const char* message, const UNITY_LINE_TYPE line);
+void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
+void UnityMessage(const char* message, const UNITY_LINE_TYPE line);
+
+#ifndef UNITY_EXCLUDE_FLOAT
+void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
+ const UNITY_FLOAT expected,
+ const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
+ const UNITY_DOUBLE expected,
+ const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
+ UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
+ const UNITY_UINT32 num_elements,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLAGS_T flags);
+
+void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
+ const char* msg,
+ const UNITY_LINE_TYPE lineNumber,
+ const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+/*-------------------------------------------------------
+ * Helpers
+ *-------------------------------------------------------*/
+
+UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size);
+#ifndef UNITY_EXCLUDE_FLOAT
+UNITY_INTERNAL_PTR UnityFloatToPtr(const float num);
+#endif
+#ifndef UNITY_EXCLUDE_DOUBLE
+UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num);
+#endif
+
+/*-------------------------------------------------------
+ * Error Strings We Might Need
+ *-------------------------------------------------------*/
+
+extern const char UnityStrOk[];
+extern const char UnityStrPass[];
+extern const char UnityStrFail[];
+extern const char UnityStrIgnore[];
+
+extern const char UnityStrErrFloat[];
+extern const char UnityStrErrDouble[];
+extern const char UnityStrErr64[];
+extern const char UnityStrErrShorthand[];
+
+/*-------------------------------------------------------
+ * Test Running Macros
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_EXCLUDE_SETJMP_H
+#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
+#define TEST_ABORT() longjmp(Unity.AbortFrame, 1)
+#else
+#define TEST_PROTECT() 1
+#define TEST_ABORT() return
+#endif
+
+/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */
+#ifndef RUN_TEST
+#ifdef __STDC_VERSION__
+#if __STDC_VERSION__ >= 199901L
+#define UNITY_SUPPORT_VARIADIC_MACROS
+#endif
+#endif
+#ifdef UNITY_SUPPORT_VARIADIC_MACROS
+#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__))
+#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway)
+#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first
+#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway)
+#define RUN_TEST_SECOND_HELPER(first, second, ...) (second)
+#endif
+#endif
+
+/* If we can't do the tricky version, we'll just have to require them to always include the line number */
+#ifndef RUN_TEST
+#ifdef CMOCK
+#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num)
+#else
+#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__)
+#endif
+#endif
+
+#define TEST_LINE_NUM (Unity.CurrentTestLineNumber)
+#define TEST_IS_IGNORED (Unity.CurrentTestIgnored)
+#define UNITY_NEW_TEST(a) \
+ Unity.CurrentTestName = (a); \
+ Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \
+ Unity.NumberOfTests++;
+
+#ifndef UNITY_BEGIN
+#define UNITY_BEGIN() UnityBegin(__FILE__)
+#endif
+
+#ifndef UNITY_END
+#define UNITY_END() UnityEnd()
+#endif
+
+#ifndef UNITY_SHORTHAND_AS_INT
+#ifndef UNITY_SHORTHAND_AS_MEM
+#ifndef UNITY_SHORTHAND_AS_NONE
+#ifndef UNITY_SHORTHAND_AS_RAW
+#define UNITY_SHORTHAND_AS_OLD
+#endif
+#endif
+#endif
+#endif
+
+/*-----------------------------------------------
+ * Command Line Argument Support
+ *-----------------------------------------------*/
+
+#ifdef UNITY_USE_COMMAND_LINE_ARGS
+int UnityParseOptions(int argc, char** argv);
+int UnityTestMatches(void);
+#endif
+
+/*-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line))
+
+/*-------------------------------------------------------
+ * Test Asserts
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));}
+#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message))
+
+#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line))
+
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR)
+
+#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY)
+
+
+#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
+#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+
+#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY)
+
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL)
+
+#ifdef UNITY_SUPPORT_64
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY)
+#else
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#endif
+
+#ifdef UNITY_EXCLUDE_FLOAT
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#else
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+#ifdef UNITY_EXCLUDE_DOUBLE
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#else
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
+#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+/* End of UNITY_INTERNALS_H */
+#endif