cJSON

mirror of Dave's cJSON
git clone git://git.thc420.xyz/cJSON
Log | Files | Refs | README | LICENSE

commit 49b9336558521209c6c4adf3ea3dc880a9ac206d
parent e65ea3a45bb467b929b5641044eaab77f415e12e
Author: Max Bruckner <max@maxbruckner.de>
Date:   Tue,  7 Feb 2017 21:50:07 +0100

Merge pull request #92 from DaveGamble/tests

Introduce the cunity testing framework
Diffstat:
A.travis.yml | 28++++++++++++++++++++++++++++
MCMakeLists.txt | 19+++++++++++++++++++
MREADME.md | 2++
Mtest.c | 140-------------------------------------------------------------------------------
Atests/CMakeLists.txt | 41+++++++++++++++++++++++++++++++++++++++++
Rtests/test1 -> tests/inputs/test1 | 0
Atests/inputs/test1.expected | 23+++++++++++++++++++++++
Atests/inputs/test10 | 1+
Atests/inputs/test10.expected | 2++
Atests/inputs/test11 | 8++++++++
Atests/inputs/test11.expected | 11+++++++++++
Rtests/test2 -> tests/inputs/test2 | 0
Atests/inputs/test2.expected | 19+++++++++++++++++++
Rtests/test3 -> tests/inputs/test3 | 0
Atests/inputs/test3.expected | 29+++++++++++++++++++++++++++++
Rtests/test4 -> tests/inputs/test4 | 0
Atests/inputs/test4.expected | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rtests/test5 -> tests/inputs/test5 | 0
Atests/inputs/test5.expected | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rtests/test6 -> tests/inputs/test6 | 0
Atests/inputs/test7 | 22++++++++++++++++++++++
Atests/inputs/test7.expected | 20++++++++++++++++++++
Atests/inputs/test8 | 13+++++++++++++
Atests/inputs/test8.expected | 14++++++++++++++
Atests/inputs/test9 | 5+++++
Atests/inputs/test9.expected | 2++
Atests/parse_array.c | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/parse_examples.c | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/parse_hex4.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/parse_number.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/parse_object.c | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/parse_string.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/parse_value.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/.gitattributes | 30++++++++++++++++++++++++++++++
Atests/unity/.gitignore | 9+++++++++
Atests/unity/.travis.yml | 25+++++++++++++++++++++++++
Atests/unity/README.md | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/colour_prompt.rb | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/colour_reporter.rb | 40++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/generate_config.yml | 36++++++++++++++++++++++++++++++++++++
Atests/unity/auto/generate_module.rb | 311+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/generate_test_runner.rb | 435+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/parseOutput.rb | 191+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/stylize_as_junit.rb | 264+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/test_file_filter.rb | 23+++++++++++++++++++++++
Atests/unity/auto/type_sanitizer.rb | 8++++++++
Atests/unity/auto/unity_test_summary.py | 139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/unity_test_summary.rb | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/auto/unity_to_junit.py | 146+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf | 0
Atests/unity/docs/UnityAssertionsReference.pdf | 0
Atests/unity/docs/UnityConfigurationGuide.pdf | 0
Atests/unity/docs/UnityGettingStartedGuide.pdf | 0
Atests/unity/docs/UnityHelperScriptsGuide.pdf | 0
Atests/unity/docs/license.txt | 21+++++++++++++++++++++
Atests/unity/examples/example_1/makefile | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_1/readme.txt | 6++++++
Atests/unity/examples/example_1/src/ProductionCode.c | 24++++++++++++++++++++++++
Atests/unity/examples/example_1/src/ProductionCode.h | 3+++
Atests/unity/examples/example_1/src/ProductionCode2.c | 11+++++++++++
Atests/unity/examples/example_1/src/ProductionCode2.h | 2++
Atests/unity/examples/example_1/test/TestProductionCode.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_1/test/TestProductionCode2.c | 31+++++++++++++++++++++++++++++++
Atests/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_2/makefile | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_2/readme.txt | 6++++++
Atests/unity/examples/example_2/src/ProductionCode.c | 24++++++++++++++++++++++++
Atests/unity/examples/example_2/src/ProductionCode.h | 3+++
Atests/unity/examples/example_2/src/ProductionCode2.c | 11+++++++++++
Atests/unity/examples/example_2/src/ProductionCode2.h | 2++
Atests/unity/examples/example_2/test/TestProductionCode.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_2/test/TestProductionCode2.c | 33+++++++++++++++++++++++++++++++++
Atests/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c | 10++++++++++
Atests/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c | 12++++++++++++
Atests/unity/examples/example_2/test/test_runners/all_tests.c | 12++++++++++++
Atests/unity/examples/example_3/helper/UnityHelper.c | 10++++++++++
Atests/unity/examples/example_3/helper/UnityHelper.h | 12++++++++++++
Atests/unity/examples/example_3/rakefile.rb | 43+++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_3/rakefile_helper.rb | 258+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_3/readme.txt | 13+++++++++++++
Atests/unity/examples/example_3/src/ProductionCode.c | 24++++++++++++++++++++++++
Atests/unity/examples/example_3/src/ProductionCode.h | 3+++
Atests/unity/examples/example_3/src/ProductionCode2.c | 11+++++++++++
Atests/unity/examples/example_3/src/ProductionCode2.h | 2++
Atests/unity/examples/example_3/target_gcc_32.yml | 46++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_3/test/TestProductionCode.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/examples/example_3/test/TestProductionCode2.c | 31+++++++++++++++++++++++++++++++
Atests/unity/examples/unity_config.h | 237+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/eclipse/error_parsers.txt | 26++++++++++++++++++++++++++
Atests/unity/extras/fixture/rakefile.rb | 48++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/rakefile_helper.rb | 179+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/readme.txt | 10++++++++++
Atests/unity/extras/fixture/src/unity_fixture.c | 432+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/src/unity_fixture.h | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/src/unity_fixture_internals.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h | 46++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/test/Makefile | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/test/main/AllTests.c | 22++++++++++++++++++++++
Atests/unity/extras/fixture/test/template_fixture_tests.c | 39+++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/test/unity_fixture_Test.c | 543+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/test/unity_fixture_TestRunner.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/test/unity_output_Spy.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/extras/fixture/test/unity_output_Spy.h | 17+++++++++++++++++
Atests/unity/release/build.info | 2++
Atests/unity/release/version.info | 2++
Atests/unity/src/unity.c | 1421+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/src/unity.h | 291++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/src/unity_internals.h | 732+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/Makefile | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_cmd.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_def.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_head1.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_head1.h | 15+++++++++++++++
Atests/unity/test/expectdata/testsample_mock_cmd.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_def.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_head1.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_head1.h | 13+++++++++++++
Atests/unity/test/expectdata/testsample_mock_new1.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_new2.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_param.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_run1.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_run2.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_mock_yaml.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_new1.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_new2.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_param.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_run1.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_run2.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/expectdata/testsample_yaml.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/rakefile | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/rakefile_helper.rb | 257+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/spec/generate_module_existing_file_spec.rb | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/clang_file.yml | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/clang_strict.yml | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/gcc_32.yml | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/gcc_64.yml | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/gcc_auto_limits.yml | 47+++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/gcc_auto_stdint.yml | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/gcc_manual_math.yml | 47+++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/hitech_picc18.yml | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/iar_arm_v4.yml | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/iar_arm_v5.yml | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/iar_arm_v5_3.yml | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/iar_cortexm3_v5.yml | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/iar_msp430.yml | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/targets/iar_sh2a_v6.yml | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/testdata/CException.h | 11+++++++++++
Atests/unity/test/testdata/Defs.h | 8++++++++
Atests/unity/test/testdata/cmock.h | 14++++++++++++++
Atests/unity/test/testdata/mockMock.h | 13+++++++++++++
Atests/unity/test/testdata/testRunnerGenerator.c | 183+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/testdata/testRunnerGeneratorSmall.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/testdata/testRunnerGeneratorWithMocks.c | 192+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/tests/test_generate_test_runner.rb | 1252+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/tests/testparameterized.c | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unity/test/tests/testunity.c | 4058+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
158 files changed, 17951 insertions(+), 140 deletions(-)

diff --git a/.travis.yml b/.travis.yml @@ -0,0 +1,28 @@ +dist: trusty +sudo: false +language: c +env: + matrix: + - VALGRIND=On SANITIZERS=Off + - VALGRIND=Off SANITIZERS=Off + - VALGRIND=Off SANITIZERS=On +compiler: + - gcc + - clang +addons: + apt: + packages: + - valgrind + - libasan0 + - lib32asan0 + # currently not supported on travis: + # - libasan1 + # - libasan2 + # - libubsan0 + - llvm +script: + - mkdir build + - cd build + - cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_VALGRIND="${VALGRIND}" -DENABLE_SANITIZERS="${SANITIZERS}" + - make + - make test CTEST_OUTPUT_ON_FAILURE=On diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -1,6 +1,8 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0) cmake_minimum_required(VERSION 2.8) +subdirs(tests) + include(GNUInstallDirs) project(cJSON C) @@ -41,6 +43,21 @@ if (ENABLE_CUSTOM_COMPILER_FLAGS) ) endif() +option(ENABLE_SANITIZERS "Enables AddressSanitizer and UndefinedBehaviorSanitizer." OFF) +if (ENABLE_SANITIZERS) + list(APPEND custom_compiler_flags + -fno-omit-frame-pointer + -fsanitize=address + -fsanitize=undefined + -fsanitize=float-divide-by-zero + -fsanitize=float-cast-overflow + -fsanitize-address-use-after-scope + -fsanitize=integer + -01 + -fno-sanitize-recover + ) +endif() + # apply custom compiler flags foreach(compiler_flag ${custom_compiler_flags}) #remove problematic characters @@ -131,6 +148,8 @@ install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake option(ENABLE_CJSON_TEST "Enable building cJSON test" ON) if(ENABLE_CJSON_TEST) + enable_testing() + set(TEST_CJSON cJSON_test) add_executable("${TEST_CJSON}" test.c) target_link_libraries("${TEST_CJSON}" "${CJSON_LIB}") diff --git a/README.md b/README.md @@ -83,6 +83,8 @@ You can change the build process with a list of different options that you can p * `-DENABLE_CJSON_UTILS=On`: Enable building cJSON_Utils. (off by default) * `-DENABLE_TARGET_EXPORT=On`: Enable the export of CMake targets. Turn off if it makes problems. (on by default) * `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang and GCC). Turn off if it makes problems. (on by default) +* `-DENABLE_VALGRIND=On`: Run tests with [valgrind](http://valgrind.org). (off by default) +* `-DENABLE_SANITIZERS=On`: Compile cJSON with [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) enabled (if possible). (off by default) * `-DBUILD_SHARED_LIBS=On`: Build the shared libraries. (on by default) * `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation. diff --git a/test.c b/test.c @@ -25,57 +25,6 @@ #include <string.h> #include "cJSON.h" -/* Parse text to JSON, then render back to text, and print! */ -static void doit(char *text) -{ - char *out = NULL; - cJSON *json = NULL; - - json = cJSON_Parse(text); - if (!json) - { - printf("Error before: [%s]\n", cJSON_GetErrorPtr()); - } - else - { - out = cJSON_Print(json); - cJSON_Delete(json); - printf("%s\n", out); - free(out); - } -} - -#if 0 -/* Read a file, parse, render back, etc. */ -static void dofile(char *filename) -{ - FILE *f = NULL; - long len = 0; - char *data = NULL; - - /* open in read binary mode */ - f = fopen(filename,"rb"); - /* get the length */ - fseek(f, 0, SEEK_END); - len = ftell(f); - fseek(f, 0, SEEK_SET); - - data = (char*)malloc(len + 1); - if (data == NULL) - { - printf("Failed to allocate memory.\n"); - exit(1); - } - - fread(data, 1, len, f); - data[len] = '\0'; - fclose(f); - - doit(data); - free(data); -} -#endif - /* Used by some code below as an example datatype. */ struct record { @@ -309,98 +258,9 @@ static void create_objects(void) int main(void) { - /* a bunch of json: */ - char text1[] = - "{\n" - "\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n" - "\"format\": {\"type\": \"rect\", \n" - "\"width\": 1920, \n" - "\"height\": 1080, \n" - "\"interlace\": false,\"frame rate\": 24\n" - "}\n" - "}"; - char text2[] = "[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]"; - char text3[] = - "[\n" - " [0, -1, 0],\n" - " [1, 0, 0],\n" - " [0, 0, 1]\n" - "\t]\n"; - char text4[] = - "{\n" - "\t\t\"Image\": {\n" - "\t\t\t\"Width\": 800,\n" - "\t\t\t\"Height\": 600,\n" - "\t\t\t\"Title\": \"View from 15th Floor\",\n" - "\t\t\t\"Thumbnail\": {\n" - "\t\t\t\t\"Url\": \"http:/*www.example.com/image/481989943\",\n" - "\t\t\t\t\"Height\": 125,\n" - "\t\t\t\t\"Width\": \"100\"\n" - "\t\t\t},\n" - "\t\t\t\"IDs\": [116, 943, 234, 38793]\n" - "\t\t}\n" - "\t}"; - char text5[] = - "[\n" - "\t {\n" - "\t \"precision\": \"zip\",\n" - "\t \"Latitude\": 37.7668,\n" - "\t \"Longitude\": -122.3959,\n" - "\t \"Address\": \"\",\n" - "\t \"City\": \"SAN FRANCISCO\",\n" - "\t \"State\": \"CA\",\n" - "\t \"Zip\": \"94107\",\n" - "\t \"Country\": \"US\"\n" - "\t },\n" - "\t {\n" - "\t \"precision\": \"zip\",\n" - "\t \"Latitude\": 37.371991,\n" - "\t \"Longitude\": -122.026020,\n" - "\t \"Address\": \"\",\n" - "\t \"City\": \"SUNNYVALE\",\n" - "\t \"State\": \"CA\",\n" - "\t \"Zip\": \"94085\",\n" - "\t \"Country\": \"US\"\n" - "\t }\n" - "\t ]"; - - char text6[] = - "<!DOCTYPE html>" - "<html>\n" - "<head>\n" - " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n" - " <style type=\"text/css\">\n" - " html, body, iframe { margin: 0; padding: 0; height: 100%; }\n" - " iframe { display: block; width: 100%; border: none; }\n" - " </style>\n" - "<title>Application Error</title>\n" - "</head>\n" - "<body>\n" - " <iframe src=\"//s3.amazonaws.com/heroku_pages/error.html\">\n" - " <p>Application Error</p>\n" - " </iframe>\n" - "</body>\n" - "</html>\n"; - /* print the version */ printf("Version: %s\n", cJSON_Version()); - /* Process each json textblock by parsing, then rebuilding: */ - doit(text1); - doit(text2); - doit(text3); - doit(text4); - doit(text5); - doit(text6); - - /* Parse standard testfiles: */ - /* dofile("../../tests/test1"); */ - /* dofile("../../tests/test2"); */ - /* dofile("../../tests/test3"); */ - /* dofile("../../tests/test4"); */ - /* dofile("../../tests/test5"); */ - /* dofile("../../tests/test6"); */ - /* Now some samplecode for building objects concisely: */ create_objects(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt @@ -0,0 +1,41 @@ +add_library(unity unity/src/unity.c) + +if(ENABLE_CJSON_TEST) + #copy test files + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/inputs") + file(GLOB test_files "inputs/*") + file(COPY ${test_files} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/inputs/") + + set(unity_tests + parse_examples + parse_number + parse_hex4 + parse_string + parse_array + parse_object + parse_value + ) + + option(ENABLE_VALGRIND OFF "Enable the valgrind memory checker for the tests.") + if (ENABLE_VALGRIND) + find_program(MEMORYCHECK_COMMAND valgrind) + if ("${MEMORYCHECK_COMMAND}" MATCHES "MEMORYCHECK_COMMAND-NOTFOUND") + message(WARNING "Valgrind couldn't be found.") + unset(MEMORYCHECK_COMMAND) + else() + set(MEMORYCHECK_COMMAND_OPTIONS --trace-children=yes --leak-check=full --error-exitcode=1) + endif() + endif() + + foreach(unity_test ${unity_tests}) + add_executable("${unity_test}" "${unity_test}.c") + target_link_libraries("${unity_test}" "${CJSON_LIB}" unity) + if(MEMORYCHECK_COMMAND) + add_test(NAME "${unity_test}" + COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "./${unity_test}") + else() + add_test(NAME "${unity_test}" + COMMAND "./${unity_test}") + endif() + endforeach() +endif() diff --git a/tests/test1 b/tests/inputs/test1 diff --git a/tests/inputs/test1.expected b/tests/inputs/test1.expected @@ -0,0 +1,22 @@ +{ + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { + "para": "A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso": ["GML", "XML"] + }, + "GlossSee": "markup" + } + } + } + } +}+ \ No newline at end of file diff --git a/tests/inputs/test10 b/tests/inputs/test10 @@ -0,0 +1 @@ +["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] diff --git a/tests/inputs/test10.expected b/tests/inputs/test10.expected @@ -0,0 +1 @@ +["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]+ \ No newline at end of file diff --git a/tests/inputs/test11 b/tests/inputs/test11 @@ -0,0 +1,8 @@ +{ +"name": "Jack (\"Bee\") Nimble", +"format": {"type": "rect", +"width": 1920, +"height": 1080, +"interlace": false,"frame rate": 24 +} +} diff --git a/tests/inputs/test11.expected b/tests/inputs/test11.expected @@ -0,0 +1,10 @@ +{ + "name": "Jack (\"Bee\") Nimble", + "format": { + "type": "rect", + "width": 1920, + "height": 1080, + "interlace": false, + "frame rate": 24 + } +}+ \ No newline at end of file diff --git a/tests/test2 b/tests/inputs/test2 diff --git a/tests/inputs/test2.expected b/tests/inputs/test2.expected @@ -0,0 +1,18 @@ +{ + "menu": { + "id": "file", + "value": "File", + "popup": { + "menuitem": [{ + "value": "New", + "onclick": "CreateNewDoc()" + }, { + "value": "Open", + "onclick": "OpenDoc()" + }, { + "value": "Close", + "onclick": "CloseDoc()" + }] + } + } +}+ \ No newline at end of file diff --git a/tests/test3 b/tests/inputs/test3 diff --git a/tests/inputs/test3.expected b/tests/inputs/test3.expected @@ -0,0 +1,28 @@ +{ + "widget": { + "debug": "on", + "window": { + "title": "Sample Konfabulator Widget", + "name": "main_window", + "width": 500, + "height": 500 + }, + "image": { + "src": "Images/Sun.png", + "name": "sun1", + "hOffset": 250, + "vOffset": 250, + "alignment": "center" + }, + "text": { + "data": "Click Here", + "size": 36, + "style": "bold", + "name": "text1", + "hOffset": 250, + "vOffset": 100, + "alignment": "center", + "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" + } + } +}+ \ No newline at end of file diff --git a/tests/test4 b/tests/inputs/test4 diff --git a/tests/inputs/test4.expected b/tests/inputs/test4.expected @@ -0,0 +1,94 @@ +{ + "web-app": { + "servlet": [{ + "servlet-name": "cofaxCDS", + "servlet-class": "org.cofax.cds.CDSServlet", + "init-param": { + "configGlossary:installationAt": "Philadelphia, PA", + "configGlossary:adminEmail": "ksm@pobox.com", + "configGlossary:poweredBy": "Cofax", + "configGlossary:poweredByIcon": "/images/cofax.gif", + "configGlossary:staticPath": "/content/static", + "templateProcessorClass": "org.cofax.WysiwygTemplate", + "templateLoaderClass": "org.cofax.FilesTemplateLoader", + "templatePath": "templates", + "templateOverridePath": "", + "defaultListTemplate": "listTemplate.htm", + "defaultFileTemplate": "articleTemplate.htm", + "useJSP": false, + "jspListTemplate": "listTemplate.jsp", + "jspFileTemplate": "articleTemplate.jsp", + "cachePackageTagsTrack": 200, + "cachePackageTagsStore": 200, + "cachePackageTagsRefresh": 60, + "cacheTemplatesTrack": 100, + "cacheTemplatesStore": 50, + "cacheTemplatesRefresh": 15, + "cachePagesTrack": 200, + "cachePagesStore": 100, + "cachePagesRefresh": 10, + "cachePagesDirtyRead": 10, + "searchEngineListTemplate": "forSearchEnginesList.htm", + "searchEngineFileTemplate": "forSearchEngines.htm", + "searchEngineRobotsDb": "WEB-INF/robots.db", + "useDataStore": true, + "dataStoreClass": "org.cofax.SqlDataStore", + "redirectionClass": "org.cofax.SqlRedirection", + "dataStoreName": "cofax", + "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", + "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", + "dataStoreUser": "sa", + "dataStorePassword": "dataStoreTestQuery", + "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", + "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", + "dataStoreInitConns": 10, + "dataStoreMaxConns": 100, + "dataStoreConnUsageLimit": 100, + "dataStoreLogLevel": "debug", + "maxUrlLength": 500 + } + }, { + "servlet-name": "cofaxEmail", + "servlet-class": "org.cofax.cds.EmailServlet", + "init-param": { + "mailHost": "mail1", + "mailHostOverride": "mail2" + } + }, { + "servlet-name": "cofaxAdmin", + "servlet-class": "org.cofax.cds.AdminServlet" + }, { + "servlet-name": "fileServlet", + "servlet-class": "org.cofax.cds.FileServlet" + }, { + "servlet-name": "cofaxTools", + "servlet-class": "org.cofax.cms.CofaxToolsServlet", + "init-param": { + "templatePath": "toolstemplates/", + "log": 1, + "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", + "logMaxSize": "", + "dataLog": 1, + "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", + "dataLogMaxSize": "", + "removePageCache": "/content/admin/remove?cache=pages&id=", + "removeTemplateCache": "/content/admin/remove?cache=templates&id=", + "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", + "lookInContext": 1, + "adminGroupID": 4, + "betaServer": true + } + }], + "servlet-mapping": { + "cofaxCDS": "/", + "cofaxEmail": "/cofaxutil/aemail/*", + "cofaxAdmin": "/admin/*", + "fileServlet": "/static/*", + "cofaxTools": "/tools/*" + }, + "taglib": { + "taglib-uri": "cofax.tld", + "taglib-location": "/WEB-INF/tlds/cofax.tld" + } + } +}+ \ No newline at end of file diff --git a/tests/test5 b/tests/inputs/test5 diff --git a/tests/inputs/test5.expected b/tests/inputs/test5.expected @@ -0,0 +1,54 @@ +{ + "menu": { + "header": "SVG Viewer", + "items": [{ + "id": "Open" + }, { + "id": "OpenNew", + "label": "Open New" + }, null, { + "id": "ZoomIn", + "label": "Zoom In" + }, { + "id": "ZoomOut", + "label": "Zoom Out" + }, { + "id": "OriginalView", + "label": "Original View" + }, null, { + "id": "Quality" + }, { + "id": "Pause" + }, { + "id": "Mute" + }, null, { + "id": "Find", + "label": "Find..." + }, { + "id": "FindAgain", + "label": "Find Again" + }, { + "id": "Copy" + }, { + "id": "CopyAgain", + "label": "Copy Again" + }, { + "id": "CopySVG", + "label": "Copy SVG" + }, { + "id": "ViewSVG", + "label": "View SVG" + }, { + "id": "ViewSource", + "label": "View Source" + }, { + "id": "SaveAs", + "label": "Save As" + }, null, { + "id": "Help" + }, { + "id": "About", + "label": "About Adobe CVG Viewer..." + }] + } +}+ \ No newline at end of file diff --git a/tests/test6 b/tests/inputs/test6 diff --git a/tests/inputs/test7 b/tests/inputs/test7 @@ -0,0 +1,22 @@ +[ + { + "precision": "zip", + "Latitude": 37.7668, + "Longitude": -122.3959, + "Address": "", + "City": "SAN FRANCISCO", + "State": "CA", + "Zip": "94107", + "Country": "US" + }, + { + "precision": "zip", + "Latitude": 37.371991, + "Longitude": -122.026020, + "Address": "", + "City": "SUNNYVALE", + "State": "CA", + "Zip": "94085", + "Country": "US" + } + ] diff --git a/tests/inputs/test7.expected b/tests/inputs/test7.expected @@ -0,0 +1,19 @@ +[{ + "precision": "zip", + "Latitude": 37.766800, + "Longitude": -122.395900, + "Address": "", + "City": "SAN FRANCISCO", + "State": "CA", + "Zip": "94107", + "Country": "US" + }, { + "precision": "zip", + "Latitude": 37.371991, + "Longitude": -122.026020, + "Address": "", + "City": "SUNNYVALE", + "State": "CA", + "Zip": "94085", + "Country": "US" + }]+ \ No newline at end of file diff --git a/tests/inputs/test8 b/tests/inputs/test8 @@ -0,0 +1,13 @@ +{ + "Image": { + "Width": 800, + "Height": 600, + "Title": "View from 15th Floor", + "Thumbnail": { + "Url": "http:/*www.example.com/image/481989943", + "Height": 125, + "Width": "100" + }, + "IDs": [116, 943, 234, 38793] + } + } diff --git a/tests/inputs/test8.expected b/tests/inputs/test8.expected @@ -0,0 +1,13 @@ +{ + "Image": { + "Width": 800, + "Height": 600, + "Title": "View from 15th Floor", + "Thumbnail": { + "Url": "http:/*www.example.com/image/481989943", + "Height": 125, + "Width": "100" + }, + "IDs": [116, 943, 234, 38793] + } +}+ \ No newline at end of file diff --git a/tests/inputs/test9 b/tests/inputs/test9 @@ -0,0 +1,5 @@ +[ + [0, -1, 0], + [1, 0, 0], + [0, 0, 1] + ] diff --git a/tests/inputs/test9.expected b/tests/inputs/test9.expected @@ -0,0 +1 @@ +[[0, -1, 0], [1, 0, 0], [0, 0, 1]]+ \ No newline at end of file diff --git a/tests/parse_array.c b/tests/parse_array.c @@ -0,0 +1,166 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "unity/examples/unity_config.h" +#include "unity/src/unity.h" +#include "../cJSON.c" + +static cJSON item[1]; + +static const unsigned char *error_pointer = NULL; + +static void assert_is_array(cJSON *string_item) +{ + TEST_ASSERT_NOT_NULL_MESSAGE(string_item, "Item is NULL."); + + TEST_ASSERT_NULL_MESSAGE(string_item->next, "Linked list next pointer is not NULL."); + TEST_ASSERT_NULL_MESSAGE(string_item->prev, "Linked list previous pointer is not NULL"); + TEST_ASSERT_BITS_MESSAGE(0xFF, cJSON_Array, string_item->type, "Item type is not array."); + TEST_ASSERT_BITS_MESSAGE(cJSON_IsReference, 0, string_item->type, "Item should not have a string as reference."); + TEST_ASSERT_BITS_MESSAGE(cJSON_StringIsConst, 0, string_item->type, "Item should not have a const string."); + TEST_ASSERT_NULL_MESSAGE(string_item->valuestring, "Valuestring is not NULL."); + TEST_ASSERT_NULL_MESSAGE(string_item->string, "String is not NULL."); +} + +static void assert_not_array(const char *json) +{ + TEST_ASSERT_NULL(parse_array(item, (const unsigned char*)json, &error_pointer)); +} + +static void assert_parse_array(const char *json) +{ + TEST_ASSERT_NOT_NULL(parse_array(item, (const unsigned char*)json, &error_pointer)); + assert_is_array(item); +} + +static void reset(void) +{ + if (item->child != NULL) + { + cJSON_Delete(item->child); + } + memset(item, 0, sizeof(cJSON)); +} + +static void parse_array_should_parse_empty_arrays(void) +{ + assert_parse_array("[]"); + TEST_ASSERT_NULL(item->child); + assert_parse_array("[\n\t]"); + TEST_ASSERT_NULL(item->child); +} + + +static void parse_array_should_parse_arrays_with_one_element(void) +{ + + assert_parse_array("[1]"); + TEST_ASSERT_NOT_NULL(item->child); + TEST_ASSERT_BITS(0xFF, cJSON_Number, item->child->type); + reset(); + + assert_parse_array("[\"hello!\"]"); + TEST_ASSERT_NOT_NULL(item->child); + TEST_ASSERT_BITS(0xFF, cJSON_String, item->child->type); + TEST_ASSERT_EQUAL_STRING("hello!", item->child->valuestring); + reset(); + + assert_parse_array("[[]]"); + TEST_ASSERT_NOT_NULL(item->child); + assert_is_array(item->child); + TEST_ASSERT_NULL(item->child->child); + reset(); + + assert_parse_array("[null]"); + TEST_ASSERT_NOT_NULL(item->child); + TEST_ASSERT_BITS(0xFF, cJSON_NULL, item->child->type); + reset(); +} + +static void parse_array_should_parse_arrays_with_multiple_elements(void) +{ + assert_parse_array("[1\t,\n2, 3]"); + TEST_ASSERT_NOT_NULL(item->child); + TEST_ASSERT_NOT_NULL(item->child->next); + TEST_ASSERT_NOT_NULL(item->child->next->next); + TEST_ASSERT_NULL(item->child->next->next->next); + TEST_ASSERT_BITS(0xFF, cJSON_Number, item->child->type); + TEST_ASSERT_BITS(0xFF, cJSON_Number, item->child->next->type); + TEST_ASSERT_BITS(0xFF, cJSON_Number, item->child->next->next->type); + reset(); + + { + size_t i = 0; + cJSON *node = NULL; + int expected_types[7] = + { + cJSON_Number, + cJSON_NULL, + cJSON_True, + cJSON_False, + cJSON_Array, + cJSON_String, + cJSON_Object + }; + assert_parse_array("[1, null, true, false, [], \"hello\", {}]"); + + node = item->child; + for ( + i = 0; + (i < (sizeof(expected_types)/sizeof(int))) + && (node != NULL); + i++, node = node->next) + { + TEST_ASSERT_BITS(0xFF, expected_types[i], node->type); + } + TEST_ASSERT_EQUAL_INT(i, 7); + reset(); + } +} + +static void parse_array_should_not_parse_non_arrays(void) +{ + assert_not_array(""); + assert_not_array("["); + assert_not_array("]"); + assert_not_array("{\"hello\":[]}"); + assert_not_array("42"); + assert_not_array("3.14"); + assert_not_array("\"[]hello world!\n\""); +} + +int main(void) +{ + /* initialize cJSON item */ + memset(item, 0, sizeof(cJSON)); + + UNITY_BEGIN(); + RUN_TEST(parse_array_should_parse_empty_arrays); + RUN_TEST(parse_array_should_parse_arrays_with_one_element); + RUN_TEST(parse_array_should_parse_arrays_with_multiple_elements); + RUN_TEST(parse_array_should_not_parse_non_arrays); + return UNITY_END(); +} diff --git a/tests/parse_examples.c b/tests/parse_examples.c @@ -0,0 +1,253 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "unity/examples/unity_config.h" +#include "unity/src/unity.h" +#include "../cJSON.h" + +static char *read_file(const char *filename) +{ + FILE *file = NULL; + long length = 0; + char *content = NULL; + size_t read_chars = 0; + + /* open in read binary mode */ + file = fopen(filename, "rb"); + if (file == NULL) + { + goto cleanup; + } + + /* get the length */ + if (fseek(file, 0, SEEK_END) != 0) + { + goto cleanup; + } + length = ftell(file); + if (length < 0) + { + goto cleanup; + } + if (fseek(file, 0, SEEK_SET) != 0) + { + goto cleanup; + } + + /* allocate content buffer */ + content = (char*)malloc((size_t)length + sizeof('\0')); + if (content == NULL) + { + goto cleanup; + } + + /* read the file into memory */ + read_chars = fread(content, sizeof(char), (size_t)length, file); + if ((long)read_chars != length) + { + free(content); + content = NULL; + goto cleanup; + } + content[read_chars] = '\0'; + + +cleanup: + if (file != NULL) + { + fclose(file); + } + + return content; +} + +static cJSON *parse_file(const char *filename) +{ + cJSON *parsed = NULL; + char *content = read_file(filename); + + parsed = cJSON_Parse(content); + + if (content != NULL) + { + free(content); + } + + return parsed; +} + +static void do_test(const char *test_name) +{ + char *expected = NULL; + char *actual = NULL; + cJSON *tree = NULL; + + size_t test_name_length = 0; + /* path of the test input */ + char *test_path = NULL; + /* path of the expected output */ + char *expected_path = NULL; + + test_name_length = strlen(test_name); + + /* allocate file paths */ +#define TEST_DIR_PATH "inputs/" + test_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length); + TEST_ASSERT_NOT_NULL_MESSAGE(test_path, "Failed to allocate test_path buffer."); + expected_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length + sizeof(".expected")); + TEST_ASSERT_NOT_NULL_MESSAGE(expected_path, "Failed to allocate expected_path buffer."); + + /* create file paths */ + sprintf(test_path, TEST_DIR_PATH"%s", test_name); + sprintf(expected_path, TEST_DIR_PATH"%s.expected", test_name); + + /* read expected output */ + expected = read_file(expected_path); + TEST_ASSERT_NOT_NULL_MESSAGE(expected, "Failed to read expected output."); + + /* read and parse test */ + tree = parse_file(test_path); + TEST_ASSERT_NOT_NULL_MESSAGE(tree, "Failed to read of parse test."); + + /* print the parsed tree */ + actual = cJSON_Print(tree); + TEST_ASSERT_NOT_NULL_MESSAGE(actual, "Failed to print tree back to JSON."); + + + TEST_ASSERT_EQUAL_STRING(expected, actual); + + /* cleanup resources */ + if (expected != NULL) + { + free(expected); + } + if (tree != NULL) + { + cJSON_Delete(tree); + } + if (actual != NULL) + { + free(actual); + } + if (test_path != NULL) + { + free(test_path); + } + if (expected_path != NULL) + { + free(expected_path); + } +} + +static void file_test1_should_be_parsed_and_printed(void) +{ + do_test("test1"); +} + +static void file_test2_should_be_parsed_and_printed(void) +{ + do_test("test2"); +} + +static void file_test3_should_be_parsed_and_printed(void) +{ + do_test("test3"); +} + +static void file_test4_should_be_parsed_and_printed(void) +{ + do_test("test4"); +} + +static void file_test5_should_be_parsed_and_printed(void) +{ + do_test("test5"); +} + +static void file_test6_should_not_be_parsed(void) +{ + char *test6 = NULL; + cJSON *tree = NULL; + + test6 = read_file("inputs/test6"); + TEST_ASSERT_NOT_NULL_MESSAGE(test6, "Failed to read test6 data."); + + tree = cJSON_Parse(test6); + TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse what is not JSON."); + + TEST_ASSERT_EQUAL_STRING_MESSAGE(test6, cJSON_GetErrorPtr(), "Error pointer is incorrect."); + + if (test6 != NULL) + { + free(test6); + } + if (tree != NULL) + { + cJSON_Delete(tree); + } +} + +static void file_test7_should_be_parsed_and_printed(void) +{ + do_test("test7"); +} + +static void file_test8_should_be_parsed_and_printed(void) +{ + do_test("test8"); +} + +static void file_test9_should_be_parsed_and_printed(void) +{ + do_test("test9"); +} + +static void file_test10_should_be_parsed_and_printed(void) +{ + do_test("test10"); +} + +static void file_test11_should_be_parsed_and_printed(void) +{ + do_test("test11"); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(file_test1_should_be_parsed_and_printed); + RUN_TEST(file_test2_should_be_parsed_and_printed); + RUN_TEST(file_test3_should_be_parsed_and_printed); + RUN_TEST(file_test4_should_be_parsed_and_printed); + RUN_TEST(file_test5_should_be_parsed_and_printed); + RUN_TEST(file_test6_should_not_be_parsed); + RUN_TEST(file_test7_should_be_parsed_and_printed); + RUN_TEST(file_test8_should_be_parsed_and_printed); + RUN_TEST(file_test9_should_be_parsed_and_printed); + RUN_TEST(file_test10_should_be_parsed_and_printed); + RUN_TEST(file_test11_should_be_parsed_and_printed); + return UNITY_END(); +} diff --git a/tests/parse_hex4.c b/tests/parse_hex4.c @@ -0,0 +1,73 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "unity/examples/unity_config.h" +#include "unity/src/unity.h" +#include "../cJSON.c" + +static void parse_hex4_should_parse_all_combinations(void) +{ + unsigned int number = 0; + unsigned char digits_lower[5]; + unsigned char digits_upper[5]; + /* test all combinations */ + for (number = 0; number <= 0xFFFF; number++) + { + TEST_ASSERT_EQUAL_INT_MESSAGE(4, sprintf((char*)digits_lower, "%.4x", number), "sprintf failed."); + TEST_ASSERT_EQUAL_INT_MESSAGE(4, sprintf((char*)digits_upper, "%.4X", number), "sprintf failed."); + + TEST_ASSERT_EQUAL_INT_MESSAGE(number, parse_hex4(digits_lower), "Failed to parse lowercase digits."); + TEST_ASSERT_EQUAL_INT_MESSAGE(number, parse_hex4(digits_upper), "Failed to parse uppercase digits."); + } +} + +static void parse_hex4_should_parse_mixed_case(void) +{ + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beef")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beeF")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beEf")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"beEF")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEef")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEeF")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEEf")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"bEEF")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"Beef")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BeeF")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BeEf")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BeEF")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEef")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEeF")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEEf")); + TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEEF")); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(parse_hex4_should_parse_all_combinations); + RUN_TEST(parse_hex4_should_parse_mixed_case); + return UNITY_END(); +} diff --git a/tests/parse_number.c b/tests/parse_number.c @@ -0,0 +1,107 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "unity/examples/unity_config.h" +#include "unity/src/unity.h" +#include "../cJSON.c" + +static cJSON item[1]; + +static void assert_is_number(cJSON *number_item) +{ + TEST_ASSERT_NOT_NULL_MESSAGE(number_item, "Item is NULL."); + + TEST_ASSERT_NULL_MESSAGE(number_item->next, "Linked list next pointer is not NULL."); + TEST_ASSERT_NULL_MESSAGE(number_item->prev, "Linked list previous pointer is not NULL"); + TEST_ASSERT_NULL_MESSAGE(number_item->child, "Child pointer is not NULL."); + TEST_ASSERT_BITS_MESSAGE(0xFF, cJSON_Number, number_item->type, "Message type is not number."); + TEST_ASSERT_BITS_MESSAGE(cJSON_IsReference, 0, number_item->type, "Item should not have a string as reference."); + TEST_ASSERT_BITS_MESSAGE(cJSON_StringIsConst, 0, number_item->type, "Item should not have a const string."); + TEST_ASSERT_NULL_MESSAGE(number_item->valuestring, "Valuestring is not NULL."); + TEST_ASSERT_NULL_MESSAGE(number_item->string, "String is not NULL."); +} + +static void assert_parse_number(const char *string, int integer, double real) +{ + TEST_ASSERT_NOT_NULL(parse_number(item, (const unsigned char*)string)); + assert_is_number(item); + TEST_ASSERT_EQUAL_INT(integer, item->valueint); + TEST_ASSERT_EQUAL_DOUBLE(real, item->valuedouble); +} + +static void parse_number_should_parse_zero(void) +{ + assert_parse_number("0", 0, 0); + assert_parse_number("0.0", 0, 0.0); + assert_parse_number("-0", 0, -0.0); +} + +static void parse_number_should_parse_negative_integers(void) +{ + assert_parse_number("-1", -1, -1); + assert_parse_number("-32768", -32768, -32768.0); + assert_parse_number("-2147483648", (int)-2147483648.0, -2147483648.0); +} + +static void parse_number_should_parse_positive_integers(void) +{ + assert_parse_number("1", 1, 1); + assert_parse_number("32767", 32767, 32767.0); + assert_parse_number("2147483647", (int)2147483647.0, 2147483647.0); +} + +static void parse_number_should_parse_positive_reals(void) +{ + assert_parse_number("0.001", 0, 0.001); + assert_parse_number("10e-10", 0, 10e-10); + assert_parse_number("10E-10", 0, 10e-10); + assert_parse_number("10e10", INT_MAX, 10e10); + assert_parse_number("123e+127", INT_MAX, 123e127); + assert_parse_number("123e-128", 0, 123e-128); +} + +static void parse_number_should_parse_negative_reals(void) +{ + assert_parse_number("-0.001", 0, -0.001); + assert_parse_number("-10e-10", 0, -10e-10); + assert_parse_number("-10E-10", 0, -10e-10); + assert_parse_number("-10e20", INT_MIN, -10e20); + assert_parse_number("-123e+127", INT_MIN, -123e127); + assert_parse_number("-123e-128", 0, -123e-128); +} + +int main(void) +{ + /* initialize cJSON item */ + memset(item, 0, sizeof(cJSON)); + UNITY_BEGIN(); + RUN_TEST(parse_number_should_parse_zero); + RUN_TEST(parse_number_should_parse_negative_integers); + RUN_TEST(parse_number_should_parse_positive_integers); + RUN_TEST(parse_number_should_parse_positive_reals); + RUN_TEST(parse_number_should_parse_negative_reals); + return UNITY_END(); +} diff --git a/tests/parse_object.c b/tests/parse_object.c @@ -0,0 +1,173 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "unity/examples/unity_config.h" +#include "unity/src/unity.h" +#include "../cJSON.c" + +static cJSON item[1]; + +static const unsigned char *error_pointer = NULL; + +static void assert_is_object(cJSON *object_item) +{ + TEST_ASSERT_NOT_NULL_MESSAGE(object_item, "Item is NULL."); + + TEST_ASSERT_NULL_MESSAGE(object_item->next, "Linked list next pointer is not NULL."); + TEST_ASSERT_NULL_MESSAGE(object_item->prev, "Linked list previous pointer is not NULL"); + TEST_ASSERT_BITS_MESSAGE(0xFF, cJSON_Object, object_item->type, "Item type is not object."); + TEST_ASSERT_BITS_MESSAGE(cJSON_IsReference, 0, object_item->type, "Item should not have a string as reference."); + TEST_ASSERT_BITS_MESSAGE(cJSON_StringIsConst, 0, object_item->type, "Item should not have a const string."); + TEST_ASSERT_NULL_MESSAGE(object_item->valuestring, "Valuestring is not NULL."); + TEST_ASSERT_NULL_MESSAGE(object_item->string, "String is not NULL."); +} + +static void assert_is_child(cJSON *child_item, const char *name, int type) +{ + TEST_ASSERT_NOT_NULL_MESSAGE(child_item, "Child item is NULL."); + TEST_ASSERT_NOT_NULL_MESSAGE(child_item->string, "Child item doesn't have a name."); + TEST_ASSERT_EQUAL_STRING_MESSAGE(name, child_item->string, "Child item has the wrong name."); + TEST_ASSERT_BITS(0xFF, type, child_item->type); +} + +static void assert_not_object(const char *json) +{ + TEST_ASSERT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer)); +} + +static void assert_parse_object(const char *json) +{ + TEST_ASSERT_NOT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer)); + assert_is_object(item); +} + +static void reset(void) +{ + if (item->child != NULL) + { + cJSON_Delete(item->child); + } + memset(item, 0, sizeof(cJSON)); +} + +static void parse_object_should_parse_empty_objects(void) +{ + assert_parse_object("{}"); + TEST_ASSERT_NULL(item->child); + assert_parse_object("{\n\t}"); + TEST_ASSERT_NULL(item->child); +} + +static void parse_array_should_parse_arrays_with_one_element(void) +{ + + assert_parse_object("{\"one\":1}"); + assert_is_child(item->child, "one", cJSON_Number); + reset(); + + assert_parse_object("{\"hello\":\"world!\"}"); + assert_is_child(item->child, "hello", cJSON_String); + reset(); + + assert_parse_object("{\"array\":[]}"); + assert_is_child(item->child, "array", cJSON_Array); + reset(); + + assert_parse_object("{\"null\":null}"); + assert_is_child(item->child, "null", cJSON_NULL); + reset(); +} + +static void parse_object_should_parse_objects_with_multiple_elements(void) +{ + assert_parse_object("{\"one\":1\t,\t\"two\"\n:2, \"three\":3}"); + assert_is_child(item->child, "one", cJSON_Number); + assert_is_child(item->child->next, "two", cJSON_Number); + assert_is_child(item->child->next->next, "three", cJSON_Number); + reset(); + + { + size_t i = 0; + cJSON *node = NULL; + int expected_types[7] = + { + cJSON_Number, + cJSON_NULL, + cJSON_True, + cJSON_False, + cJSON_Array, + cJSON_String, + cJSON_Object + }; + const char *expected_names[7] = + { + "one", + "NULL", + "TRUE", + "FALSE", + "array", + "world", + "object" + }; + assert_parse_object("{\"one\":1, \"NULL\":null, \"TRUE\":true, \"FALSE\":false, \"array\":[], \"world\":\"hello\", \"object\":{}}"); + + node = item->child; + for ( + i = 0; + (i < (sizeof(expected_types)/sizeof(int))) + && (node != NULL); + i++, node = node->next) + { + assert_is_child(node, expected_names[i], expected_types[i]); + } + TEST_ASSERT_EQUAL_INT(i, 7); + reset(); + } +} + +static void parse_object_should_not_parse_non_objects(void) +{ + assert_not_object(""); + assert_not_object("{"); + assert_not_object("}"); + assert_not_object("[\"hello\",{}]"); + assert_not_object("42"); + assert_not_object("3.14"); + assert_not_object("\"{}hello world!\n\""); +} + +int main(void) +{ + /* initialize cJSON item */ + memset(item, 0, sizeof(cJSON)); + + UNITY_BEGIN(); + RUN_TEST(parse_object_should_parse_empty_objects); + RUN_TEST(parse_object_should_not_parse_non_objects); + RUN_TEST(parse_object_should_parse_objects_with_multiple_elements); + RUN_TEST(parse_array_should_parse_arrays_with_one_element); + return UNITY_END(); +} diff --git a/tests/parse_string.c b/tests/parse_string.c @@ -0,0 +1,111 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "unity/examples/unity_config.h" +#include "unity/src/unity.h" +#include "../cJSON.c" + +static cJSON item[1]; + +static const unsigned char *error_pointer = NULL; + +static void assert_is_string(cJSON *string_item) +{ + TEST_ASSERT_NOT_NULL_MESSAGE(string_item, "Item is NULL."); + + TEST_ASSERT_NULL_MESSAGE(string_item->next, "Linked list next pointer is not NULL."); + TEST_ASSERT_NULL_MESSAGE(string_item->prev, "Linked list previous pointer is not NULL"); + TEST_ASSERT_NULL_MESSAGE(string_item->child, "Child pointer is not NULL."); + TEST_ASSERT_BITS_MESSAGE(0xFF, cJSON_String, string_item->type, "Item type is not string."); + TEST_ASSERT_BITS_MESSAGE(cJSON_IsReference, 1, string_item->type, "Item should have a string as reference."); + TEST_ASSERT_BITS_MESSAGE(cJSON_StringIsConst, 0, string_item->type, "Item should not have a const string."); + TEST_ASSERT_NOT_NULL_MESSAGE(string_item->valuestring, "Valuestring is NULL."); + TEST_ASSERT_NULL_MESSAGE(string_item->string, "String is not NULL."); +} + +static void assert_parse_string(const char *string, const char *expected) +{ + TEST_ASSERT_NOT_NULL_MESSAGE(parse_string(item, (const unsigned char*)string, &error_pointer), "Couldn't parse string."); + assert_is_string(item); + TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, item->valuestring, "The parsed result isn't as expected."); + cJSON_free(item->valuestring); + item->valuestring = NULL; +} + +static void parse_string_should_parse_strings(void) +{ + assert_parse_string("\"\"", ""); + assert_parse_string( + "\" !\\\"#$%&'()*+,-./\\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_'abcdefghijklmnopqrstuvwxyz{|}~\"", + " !\"#$%&'()*+,-.//0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~"); + assert_parse_string( + "\"\\\"\\\\\\/\\b\\f\\n\\r\\t\\u20AC\\u732b\"", + "\"\\/\b\f\n\r\t€猫"); + assert_parse_string("\"\b\f\n\r\t\"", "\b\f\n\r\t"); +} + +static void parse_string_should_parse_utf16_surrogate_pairs(void) +{ + assert_parse_string("\"\\uD83D\\udc31\"", "🐱"); +} + +static void parse_string_should_not_parse_non_strings(void) +{ + TEST_ASSERT_NULL(parse_string(item, (const unsigned char*)"this\" is not a string\"", &error_pointer)); + TEST_ASSERT_NULL(parse_string(item, (const unsigned char*) "", &error_pointer)); +} + +static void parse_string_should_not_parse_invalid_backslash(void) +{ + TEST_ASSERT_NULL_MESSAGE(parse_string(item, (const unsigned char*)"Abcdef\\123", &error_pointer), "Invalid backshlash should not be accepted."); + TEST_ASSERT_NULL_MESSAGE(parse_string(item, (const unsigned char*)"Abcdef\\e23", &error_pointer), "Invalid backshlash should not be accepted."); +} + +static void parse_string_should_not_overflow_with_closing_backslash(void) +{ + TEST_ASSERT_NULL_MESSAGE(parse_string(item, (const unsigned char*)"\"000000000000000000\\", &error_pointer), "Malformed string should not be accepted."); +} + +static void parse_string_should_parse_bug_94(void) +{ + const char string[] = "\"~!@\\\\#$%^&*()\\\\\\\\-\\\\+{}[]:\\\\;\\\\\\\"\\\\<\\\\>?/.,DC=ad,DC=com\""; + assert_parse_string(string, "~!@\\#$%^&*()\\\\-\\+{}[]:\\;\\\"\\<\\>?/.,DC=ad,DC=com"); +} + +int main(void) +{ + /* initialize cJSON item and error pointer */ + memset(item, 0, sizeof(cJSON)); + + UNITY_BEGIN(); + RUN_TEST(parse_string_should_parse_strings); + RUN_TEST(parse_string_should_parse_utf16_surrogate_pairs); + RUN_TEST(parse_string_should_not_parse_non_strings); + RUN_TEST(parse_string_should_not_parse_invalid_backslash); + RUN_TEST(parse_string_should_parse_bug_94); + RUN_TEST(parse_string_should_not_overflow_with_closing_backslash); + return UNITY_END(); +} diff --git a/tests/parse_value.c b/tests/parse_value.c @@ -0,0 +1,122 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "unity/examples/unity_config.h" +#include "unity/src/unity.h" +#include "../cJSON.c" + +static cJSON item[1]; +const unsigned char *error_pointer = NULL; + +static void assert_is_value(cJSON *value_item, int type) +{ + TEST_ASSERT_NOT_NULL_MESSAGE(value_item, "Item is NULL."); + + TEST_ASSERT_NULL_MESSAGE(value_item->next, "Linked list next pointer is not NULL."); + TEST_ASSERT_NULL_MESSAGE(value_item->prev, "Linked list previous pointer is not NULL"); + TEST_ASSERT_BITS_MESSAGE(0xFF, type, value_item->type, "Message type is not number."); + TEST_ASSERT_BITS_MESSAGE(cJSON_IsReference, 0, value_item->type, "Item should not have a string as reference."); + TEST_ASSERT_BITS_MESSAGE(cJSON_StringIsConst, 0, value_item->type, "Item should not have a const string."); + TEST_ASSERT_NULL_MESSAGE(value_item->string, "String is not NULL."); +} + +static void assert_parse_value(const char *string, int type) +{ + TEST_ASSERT_NOT_NULL(parse_value(item, (const unsigned char*)string, &error_pointer)); + assert_is_value(item, type); +} + +static void reset(void) +{ + if (item->child != NULL) + { + cJSON_Delete(item->child); + } + if (item->valuestring != NULL) + { + cJSON_free(item->valuestring); + } + memset(item, 0, sizeof(cJSON)); +} + +static void parse_value_should_parse_null(void) +{ + assert_parse_value("null", cJSON_NULL); + reset(); +} + +static void parse_value_should_parse_true(void) +{ + assert_parse_value("true", cJSON_True); + reset(); +} + +static void parse_value_should_parse_false(void) +{ + assert_parse_value("false", cJSON_False); + reset(); +} + +static void parse_value_should_parse_number(void) +{ + assert_parse_value("1.5", cJSON_Number); + reset(); +} + +static void parse_value_should_parse_string(void) +{ + assert_parse_value("\"\"", cJSON_String); + reset(); + assert_parse_value("\"hello\"", cJSON_String); + reset(); +} + +static void parse_value_should_parse_array(void) +{ + assert_parse_value("[]", cJSON_Array); + reset(); +} + +static void parse_value_should_parse_object(void) +{ + assert_parse_value("{}", cJSON_Object); + reset(); +} + +int main(void) +{ + /* initialize cJSON item */ + memset(item, 0, sizeof(cJSON)); + UNITY_BEGIN(); + RUN_TEST(parse_value_should_parse_null); + RUN_TEST(parse_value_should_parse_true); + RUN_TEST(parse_value_should_parse_false); + RUN_TEST(parse_value_should_parse_number); + RUN_TEST(parse_value_should_parse_string); + RUN_TEST(parse_value_should_parse_array); + RUN_TEST(parse_value_should_parse_object); + return UNITY_END(); +} diff --git a/tests/unity/.gitattributes b/tests/unity/.gitattributes @@ -0,0 +1,30 @@ +* text=auto + +# These files are text and should be normalized (convert crlf to lf) +*.rb text +*.test text +*.c text +*.cpp text +*.h text +*.txt text +*.yml text +*.s79 text +*.bat text +*.xcl text +*.inc text +*.info text +*.md text +makefile text +rakefile text + + +#These files are binary and should not be normalized +*.doc binary +*.odt binary +*.pdf binary +*.ewd binary +*.eww binary +*.dni binary +*.wsdt binary +*.dbgdt binary +*.mac binary diff --git a/tests/unity/.gitignore b/tests/unity/.gitignore @@ -0,0 +1,9 @@ +build/ +test/sandbox +.DS_Store +examples/example_1/test1.exe +examples/example_1/test2.exe +examples/example_2/all_tests.exe +examples/example_1/test1.out +examples/example_1/test2.out +examples/example_2/all_tests.out diff --git a/tests/unity/.travis.yml b/tests/unity/.travis.yml @@ -0,0 +1,25 @@ +language: c + +matrix: + include: + - os: osx + compiler: clang + osx_image: xcode7.3 + - os: linux + dist: trusty + compiler: gcc + +before_install: + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then rvm install 2.1 && rvm use 2.1 && ruby -v; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install --assume-yes --quiet gcc-multilib; fi +install: gem install rspec +script: + - cd test && rake ci + - make -s + - make -s DEBUG=-m32 + - cd ../extras/fixture/test && rake ci + - make -s default noStdlibMalloc + - make -s C89 + - cd ../../../examples/example_1 && make -s ci + - cd ../example_2 && make -s ci + - cd ../example_3 && rake diff --git a/tests/unity/README.md b/tests/unity/README.md @@ -0,0 +1,211 @@ +Unity Test API +============== + +[![Unity Build Status](https://api.travis-ci.org/ThrowTheSwitch/Unity.png?branch=master)](https://travis-ci.org/ThrowTheSwitch/Unity) +__Copyright (c) 2007 - 2014 Unity Project by Mike Karlesky, Mark VanderVoord, and Greg Williams__ + +Running Tests +------------- + + RUN_TEST(func, linenum) + +Each Test is run within the macro `RUN_TEST`. This macro performs necessary setup before the test is called and handles cleanup and result tabulation afterwards. + +Ignoring Tests +-------------- + +There are times when a test is incomplete or not valid for some reason. At these times, TEST_IGNORE can be called. Control will immediately be returned to the caller of the test, and no failures will be returned. + + TEST_IGNORE() + +Ignore this test and return immediately + + TEST_IGNORE_MESSAGE (message) + +Ignore this test and return immediately. Output a message stating why the test was ignored. + +Aborting Tests +-------------- + +There are times when a test will contain an infinite loop on error conditions, or there may be reason to escape from the test early without executing the rest of the test. A pair of macros support this functionality in Unity. The first `TEST_PROTECT` sets up the feature, and handles emergency abort cases. `TEST_ABORT` can then be used at any time within the tests to return to the last `TEST_PROTECT` call. + + TEST_PROTECT() + +Setup and Catch macro + + TEST_ABORT() + +Abort Test macro + +Example: + + main() + { + if (TEST_PROTECT() == 0) + { + MyTest(); + } + } + +If MyTest calls `TEST_ABORT`, program control will immediately return to `TEST_PROTECT` with a non-zero return value. + + +Unity Assertion Summary +======================= + +Basic Validity Tests +-------------------- + + TEST_ASSERT_TRUE(condition) + +Evaluates whatever code is in condition and fails if it evaluates to false + + TEST_ASSERT_FALSE(condition) + +Evaluates whatever code is in condition and fails if it evaluates to true + + TEST_ASSERT(condition) + +Another way of calling `TEST_ASSERT_TRUE` + + TEST_ASSERT_UNLESS(condition) + +Another way of calling `TEST_ASSERT_FALSE` + + TEST_FAIL() + TEST_FAIL_MESSAGE(message) + +This test is automatically marked as a failure. The message is output stating why. + +Numerical Assertions: Integers +------------------------------ + + 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) + +Compare two integers for equality and display errors as signed integers. A cast will be performed +to your natural integer size so often this can just be used. When you need to specify the exact size, +like when comparing arrays, you can use a specific version: + + 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) + +Compare two integers for equality and display errors as unsigned integers. Like INT, there are +variants for different sizes also. + + 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) + +Compares two integers for equality and display errors as hexadecimal. Like the other integer comparisons, +you can specify the size... here the size will also effect how many nibbles are shown (for example, `HEX16` +will show 4 nibbles). + + _ARRAY + +You can append `_ARRAY` to any of these macros to make an array comparison of that type. Here you will +need to care a bit more about the actual size of the value being checked. You will also specify an +additional argument which is the number of elements to compare. For example: + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements) + + TEST_ASSERT_EQUAL(expected, actual) + +Another way of calling TEST_ASSERT_EQUAL_INT + + TEST_ASSERT_INT_WITHIN(delta, expected, actual) + +Asserts that the actual value is within plus or minus delta of the expected value. This also comes in +size specific variants. + + +Numerical Assertions: Bitwise +----------------------------- + + TEST_ASSERT_BITS(mask, expected, actual) + +Use an integer mask to specify which bits should be compared between two other integers. High bits in the mask are compared, low bits ignored. + + TEST_ASSERT_BITS_HIGH(mask, actual) + +Use an integer mask to specify which bits should be inspected to determine if they are all set high. High bits in the mask are compared, low bits ignored. + + TEST_ASSERT_BITS_LOW(mask, actual) + +Use an integer mask to specify which bits should be inspected to determine if they are all set low. High bits in the mask are compared, low bits ignored. + + TEST_ASSERT_BIT_HIGH(bit, actual) + +Test a single bit and verify that it is high. The bit is specified 0-31 for a 32-bit integer. + + TEST_ASSERT_BIT_LOW(bit, actual) + +Test a single bit and verify that it is low. The bit is specified 0-31 for a 32-bit integer. + +Numerical Assertions: Floats +---------------------------- + + TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) + +Asserts that the actual value is within plus or minus delta of the expected value. + + TEST_ASSERT_EQUAL_FLOAT(expected, actual) + TEST_ASSERT_EQUAL_DOUBLE(expected, actual) + +Asserts that two floating point values are "equal" within a small % delta of the expected value. + +String Assertions +----------------- + + TEST_ASSERT_EQUAL_STRING(expected, actual) + +Compare two null-terminate strings. Fail if any character is different or if the lengths are different. + + TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) + +Compare two strings. Fail if any character is different, stop comparing after len characters. + + TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) + +Compare two null-terminate strings. Fail if any character is different or if the lengths are different. Output a custom message on failure. + + TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) + +Compare two strings. Fail if any character is different, stop comparing after len characters. Output a custom message on failure. + +Pointer Assertions +------------------ + +Most pointer operations can be performed by simply using the integer comparisons above. However, a couple of special cases are added for clarity. + + TEST_ASSERT_NULL(pointer) + +Fails if the pointer is not equal to NULL + + TEST_ASSERT_NOT_NULL(pointer) + +Fails if the pointer is equal to NULL + +Memory Assertions +----------------- + + TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) + +Compare two blocks of memory. This is a good generic assertion for types that can't be coerced into acting like +standard types... but since it's a memory compare, you have to be careful that your data types are packed. + +_MESSAGE +-------- + +you can append _MESSAGE to any of the macros to make them take an additional argument. This argument +is a string that will be printed at the end of the failure strings. This is useful for specifying more +information about the problem. + diff --git a/tests/unity/auto/colour_prompt.rb b/tests/unity/auto/colour_prompt.rb @@ -0,0 +1,115 @@ +# ========================================== +# 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 + if RUBY_PLATFORM =~/(win|w)32$/ + get_std_handle = Win32API.new("kernel32", "GetStdHandle", ['L'], 'L') + @set_console_txt_attrb = + Win32API.new("kernel32","SetConsoleTextAttribute",['L','N'], 'I') + @hout = get_std_handle.call(-11) + end + end + + def change_to(new_colour) + if RUBY_PLATFORM =~/(win|w)32$/ + @set_console_txt_attrb.call(@hout,self.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 # ColourCommandLine + +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/tests/unity/auto/colour_reporter.rb b/tests/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 "#{File.expand_path(File.dirname(__FILE__))}/colour_prompt" + +$colour_output = true + +def report(message) + if not $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 + ($1.to_i == 0) ? :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+ \ No newline at end of file diff --git a/tests/unity/auto/generate_config.yml b/tests/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/tests/unity/auto/generate_module.rb b/tests/unity/auto/generate_module.rb @@ -0,0 +1,311 @@ +# ========================================== +# 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 ||= %q[#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"); +} +] + +#TEMPLATE_SRC +TEMPLATE_SRC ||= %q[%2$s#include "%1$s.h" +] + +#TEMPLATE_INC +TEMPLATE_INC ||= %q[#ifndef _%3$s_H +#define _%3$s_H +%2$s + +#endif // _%3$s_H +] + +class UnityModuleGenerator + + ############################ + def initialize(options=nil) + + here = File.expand_path(File.dirname(__FILE__)) + '/' + + @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] = here + "../src/" if @options[:path_src].nil? + @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil? + @options[:path_tst] = here + "../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 = self.default_options + unless (config_file.nil? or 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 + return(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 + if (pattern == 'test') + triad.reject!{|v| v[:inc] != :tst } + end + + # 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| f % [module_name]} + when :inc then (@options[:includes][:inc] || []) + when :tst then (@options[:includes][:tst] || []) | pattern_traits[:inc].map{|f| "#{@options[:mock_prefix]}#{f}" % [module_name]} + end + } + end + end + + return 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.downcase + 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.downcase + "_" + part2.downcase + 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| + if not File.exist?(file[:path]) + all_files_exist = false + end + 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{|f| "#include \"#{f}\"\n"}.join, + file[:name].upcase ] + ) + end + if (@options[:update_svn]) + `svn add \"#{file[:path]}\"` + if $?.exitstatus == 0 + 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] = $1 + when /^-s\"?(.+)\"?/ then options[:path_src] = $1 + when /^-i\"?(.+)\"?/ then options[:path_inc] = $1 + when /^-t\"?(.+)\"?/ then options[:path_tst] = $1 + when /^-n\"?(.+)\"?/ then options[:naming] = $1 + when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config($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 = [] + else + raise "ERROR: Unknown option specified '#{arg}'" + end + end + + if (!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. (DEFAULT)", + " 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/tests/unity/auto/generate_test_runner.rb b/tests/unity/auto/generate_test_runner.rb @@ -0,0 +1,435 @@ +# ========================================== +# 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] +# ========================================== + +$QUICK_RUBY_VERSION = RUBY_VERSION.split('.').inject(0){|vv,v| vv * 100 + v.to_i } +File.expand_path(File.join(File.dirname(__FILE__),'colour_prompt')) + +class UnityTestRunnerGenerator + + def initialize(options = nil) + @options = UnityTestRunnerGenerator.default_options + case(options) + when NilClass then @options + when String then @options.merge!(UnityTestRunnerGenerator.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 + require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer" + end + + def self.default_options + { + :includes => [], + :defines => [], + :plugins => [], + :framework => :unity, + :test_prefix => "test|spec|should", + :setup_name => "setUp", + :teardown_name => "tearDown", + :main_name => "main", #set to :auto to automatically generate each time + :main_export_decl => "", + :cmdline_args => false, + :use_param_tests => false, + } + end + + def self.grab_config(config_file) + options = self.default_options + unless (config_file.nil? or 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 + return(options) + end + + def run(input_file, output_file, options=nil) + tests = [] + testfile_includes = [] + used_mocks = [] + + @options.merge!(options) unless options.nil? + module_name = File.basename(input_file) + + #pull required data from source file + source = File.read(input_file) + source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil) if ($QUICK_RUBY_VERSION > 10900) + 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)/} + + #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? + return 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_suite_setup_and_teardown(output) + create_reset(output, used_mocks) + create_main(output, input_file, tests, used_mocks) + end + + if (@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 + end + + def find_tests(source) + tests_and_line_numbers = [] + + source_scrubbed = source.clone + source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings + source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments + source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments + lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line + | (;|\{|\}) /x) # Match ;, {, and } as end of lines + + lines.each_with_index do |line, index| + #find tests + if line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/ + arguments = $1 + name = $2 + call = $3 + params = $4 + args = nil + if (@options[:use_param_tests] and !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 + 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| + 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 + + return 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}>" } + } + return 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 =~ /^mock/i) + end + return mock_headers + end + + def create_header(output, mocks, testfile_includes=[]) + output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') + create_runtest(output, mocks) + output.puts("\n/*=======Automagically Detected Files To Include=====*/") + output.puts("#include \"#{@options[:framework].to_s}.h\"") + output.puts('#include "cmock.h"') unless (mocks.empty?) + output.puts('#include <setjmp.h>') + output.puts('#include <stdio.h>') + output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) + if (@options[:defines] && !@options[:defines].empty?) + @options[:defines].each {|d| output.puts("#define #{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 + if @options[:enforce_strict_ordering] + output.puts('') + output.puts('int GlobalExpectCount;') + output.puts('int GlobalVerifyOrder;') + output.puts('char* GlobalOrderError;') + end + 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);") + tests.each do |test| + output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});") + end + output.puts('') + end + + def create_mock_management(output, mock_headers) + unless (mock_headers.empty?) + 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 + end + + def create_suite_setup_and_teardown(output) + unless (@options[:suite_setup].nil?) + output.puts("\n/*=======Suite Setup=====*/") + output.puts("static void suite_setup(void)") + output.puts("{") + output.puts(@options[:suite_setup]) + output.puts("}") + end + unless (@options[:suite_teardown].nil?) + output.puts("\n/*=======Suite Teardown=====*/") + output.puts("static int suite_teardown(int num_failures)") + output.puts("{") + output.puts(@options[:suite_teardown]) + output.puts("}") + end + end + + def create_runtest(output, used_mocks) + cexception = @options[:plugins].include? :cexception + va_args1 = @options[:use_param_tests] ? ', ...' : '' + va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : '' + output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/") + output.puts("#define RUN_TEST_NO_ARGS") if @options[:use_param_tests] + output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\") + output.puts("{ \\") + output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\") + output.puts(" Unity.CurrentTestLineNumber = TestLineNum; \\") + output.puts(" if (UnityTestMatches()) { \\") if (@options[:cmdline_args]) + output.puts(" Unity.NumberOfTests++; \\") + output.puts(" CMock_Init(); \\") unless (used_mocks.empty?) + output.puts(" UNITY_CLR_DETAILS(); \\") unless (used_mocks.empty?) + output.puts(" if (TEST_PROTECT()) \\") + output.puts(" { \\") + output.puts(" CEXCEPTION_T e; \\") if cexception + output.puts(" Try { \\") if cexception + output.puts(" #{@options[:setup_name]}(); \\") + output.puts(" TestFunc(#{va_args2}); \\") + output.puts(" } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\"); } \\") if cexception + output.puts(" } \\") + output.puts(" if (TEST_PROTECT()) \\") + output.puts(" { \\") + output.puts(" #{@options[:teardown_name]}(); \\") + output.puts(" CMock_Verify(); \\") unless (used_mocks.empty?) + output.puts(" } \\") + output.puts(" CMock_Destroy(); \\") unless (used_mocks.empty?) + output.puts(" UnityConcludeTest(); \\") + output.puts(" } \\") if (@options[:cmdline_args]) + output.puts("}\n") + end + + def create_reset(output, used_mocks) + output.puts("\n/*=======Test Reset Option=====*/") + output.puts("void resetTest(void);") + output.puts("void resetTest(void)") + output.puts("{") + output.puts(" CMock_Verify();") unless (used_mocks.empty?) + output.puts(" CMock_Destroy();") unless (used_mocks.empty?) + output.puts(" #{@options[:teardown_name]}();") + output.puts(" CMock_Init();") unless (used_mocks.empty?) + output.puts(" #{@options[:setup_name]}();") + output.puts("}") + 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]}" + 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();") + if (@options[:use_param_tests]) + tests.each do |test| + if ((test[:args].nil?) or (test[:args].empty?)) + output.puts(" UnityPrint(\" #{test[:test]}(RUN_TEST_NO_ARGS)\");") + 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 + else + tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();")} + end + output.puts(" return 0;") + output.puts(" }") + output.puts(" return parse_status;") + output.puts(" }") + else + if (main_name != "main") + output.puts("#{@options[:main_export_decl]} int #{main_name}(void);") + end + output.puts("int #{main_name}(void)") + output.puts("{") + end + output.puts(" suite_setup();") unless @options[:suite_setup].nil? + output.puts(" UnityBegin(\"#{filename.gsub(/\\/,'\\\\\\')}\");") + if (@options[:use_param_tests]) + tests.each do |test| + if ((test[:args].nil?) or (test[:args].empty?)) + output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);") + else + test[:args].each {|args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});")} + end + end + else + tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") } + end + output.puts() + output.puts(" CMock_Guts_MemFreeFinal();") unless used_mocks.empty? + output.puts(" return #{@options[:suite_teardown].nil? ? "" : "suite_teardown"}(UnityEnd());") + 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].to_s}.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?) or (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 => [] } + yaml_file = nil + + #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[$1.to_sym] = $2; true + when /\.*\.h/ + options[:includes] << arg; true + else false + end + end + + #make sure there is at least one parameter left (the input file) + if !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", + " --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", + " --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)", + " --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") if (!ARGV[1]) + + UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1]) +end diff --git a/tests/unity/auto/parseOutput.rb b/tests/unity/auto/parseOutput.rb @@ -0,0 +1,191 @@ +#============================================================ +# 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 GCC/Linux builds use the following: +# make | tee Output.txt +# +# 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 +#============================================================ + + +class ParseOutput +# The following flag is set to true when a test is found or false otherwise. + @testFlag + @xmlOut + @arrayList + @totalTests + @classIndex + +# Set the flag to indicate if there will be an XML output file or not + def setXmlOutput() + @xmlOut = true + end + +# if write our output to XML + def writeXmlOuput() + output = File.open("report.xml", "w") + output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + @arrayList.each do |item| + output << item << "\n" + end + output << "</testsuite>\n" + 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 testSuiteVerify(testSuiteName) + if @testFlag == false + @testFlag = true; + # Split the path name + testName = testSuiteName.split("/") + # Remove the extension + baseName = testName[testName.size - 1].split(".") + @testSuite = "test." + baseName[0] + printf "New Test: %s\n", @testSuite + end + end + + +# Test was flagged as having passed so format the output + def testPassed(array) + lastItem = array.length - 1 + testName = array[lastItem - 1] + testSuiteVerify(array[@className]) + printf "%-40s PASS\n", testName + if @xmlOut == true + @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>" + end + end + +# Test was flagged as being ingored so format the output + def testIgnored(array) + lastItem = array.length - 1 + testName = array[lastItem - 2] + reason = array[lastItem].chomp + testSuiteVerify(array[@className]) + printf "%-40s IGNORED\n", testName + if @xmlOut == true + @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" + @arrayList.push " <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>" + @arrayList.push " </testcase>" + end + end + +# Test was flagged as having failed so format the line + def testFailed(array) + lastItem = array.length - 1 + testName = array[lastItem - 2] + reason = array[lastItem].chomp + " at line: " + array[lastItem - 3] + testSuiteVerify(array[@className]) + printf "%-40s FAILED\n", testName + if @xmlOut == true + @arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">" + @arrayList.push " <failure type=\"ASSERT FAILED\"> " + reason + " </failure>" + @arrayList.push " </testcase>" + end + end + + +# Figure out what OS we are running on. For now we are assuming if it's not Windows it must +# be Unix based. + def detectOS() + myOS = RUBY_PLATFORM.split("-") + if myOS.size == 2 + if myOS[1] == "mingw32" + @className = 1 + else + @className = 0 + end + else + @className = 0 + end + + end + +# Main function used to parse the file that was captured. + def process(name) + @testFlag = false + @arrayList = Array.new + + detectOS() + + puts "Parsing file: " + name + + + testPass = 0 + testFail = 0 + testIgnore = 0 + puts "" + puts "=================== RESULTS =====================" + puts "" + File.open(name).each do |line| + # Typical test lines look like this: + # <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 + # + # where path is different on Unix vs Windows devices (Windows leads with a drive letter) + lineArray = line.split(":") + lineSize = lineArray.size + # 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. + if lineSize >= 4 + # Determine if this test passed + if line.include? ":PASS" + testPassed(lineArray) + testPass += 1 + elsif line.include? ":FAIL:" + testFailed(lineArray) + testFail += 1 + elsif line.include? ":IGNORE:" + testIgnored(lineArray) + testIgnore += 1 + # If none of the keywords are found there are no more tests for this suite so clear + # the test flag + else + @testFlag = false + end + else + @testFlag = false + end + end + puts "" + puts "=================== SUMMARY =====================" + puts "" + puts "Tests Passed : " + testPass.to_s + puts "Tests Failed : " + testFail.to_s + puts "Tests Ignored : " + testIgnore.to_s + @totalTests = testPass + testFail + testIgnore + if @xmlOut == true + heading = "<testsuite tests=\"" + @totalTests.to_s + "\" failures=\"" + testFail.to_s + "\"" + " skips=\"" + testIgnore.to_s + "\">" + @arrayList.insert(0, heading) + writeXmlOuput() + end + + # return result + end + + end + +# If the command line has no values in, used a default value of Output.txt +parseMyFile = ParseOutput.new + +if ARGV.size >= 1 + ARGV.each do |a| + if a == "-xml" + parseMyFile.setXmlOutput(); + else + parseMyFile.process(a) + break + end + end +end diff --git a/tests/unity/auto/stylize_as_junit.rb b/tests/unity/auto/stylize_as_junit.rb @@ -0,0 +1,264 @@ +#!/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 |opts| + opts.banner = "Usage: unity_to_junit.rb [options]" + + opts.separator "" + opts.separator "Specific options:" + + opts.on("-r", "--results <dir>", "Look for Unity Results files here.") do |results| + #puts "results #{results}" + options.results_dir = results + end + + opts.on("-p", "--root_path <path>", "Prepend this path to files in results.") do |root_path| + options.root_path = root_path + end + + opts.on("-o", "--output <filename>", "XML file to generate.") do |out_file| + #puts "out_file: #{out_file}" + options.out_file = out_file + end + + opts.separator "" + opts.separator "Common options:" + + # No argument, shows at tail. This will print an options summary. + opts.on_tail("-h", "--help", "Show this message") do + puts opts + exit + end + + # Another typical switch to print the version. + opts.on_tail("--version", "Show version") do + puts "unity_to_junit.rb version #{VERSION}" + exit + end + end + + opts.parse!(args) + options + end # parse() + +end # class OptparseExample + +class UnityToJUnit + include FileUtils::Verbose + attr_reader :report, :total_tests, :failures, :ignored + + def initialize + @report = '' + @unit_name = '' + end + + def run + # Clean up result file names + results = @targets.map {|target| target.gsub(/\\/,"/")} + #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 { |line| line.chomp } + if lines.length == 0 + raise "Empty test result file: #{result_file}" + else + 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]) + end + #use line[0] from the test output to get the test_file path and name + test_file_str = lines[0].gsub("\\","/") + 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 set_targets(target_array) + @targets = target_array + end + + def set_root_path(path) + @root = path + end + def set_out_file(filename) + @out_file = filename + 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 = get_results_structure + lines.each do |line| + line = line.gsub("\\","/") + src_file,src_line,test_name,status,msg = line.split(/:/) + line_out = ((@root and (@root != 0)) ? "#{@root}#{line}" : line ).gsub(/\//, "\\") + 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 + return results + end + + def parse_test_summary(summary) + if summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + [$1.to_i,$2.to_i,$3.to_i] + else + raise "Couldn't parse test results: #{summary}" + end + end + def here; File.expand_path(File.dirname(__FILE__)); end + + private + + def get_results_structure + return { + :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| + filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) + 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 #UnityToJUnit + +if __FILE__ == $0 + #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.gsub(/\\/, '/')}**/*.test*" + + results = Dir[targets] + raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? + utj.set_targets(results) + + #set the root path + utj.set_root_path(options.root_path) + + #set the output XML file name + #puts "Output File from options: #{options.out_file}" + utj.set_out_file(options.out_file) + + #run the summarizer + puts utj.run + rescue Exception => e + utj.usage e.message + end +end diff --git a/tests/unity/auto/test_file_filter.rb b/tests/unity/auto/test_file_filter.rb @@ -0,0 +1,23 @@ +# ========================================== +# 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 + if not @all_files == true + if File.exist?('test_file_filter.yml') + filters = YAML.load_file( 'test_file_filter.yml' ) + @all_files, @only_files, @exclude_files = + filters[:all_files], filters[:only_files], filters[:exclude_files] + end + end + end + attr_accessor :all_files, :only_files, :exclude_files + end +end diff --git a/tests/unity/auto/type_sanitizer.rb b/tests/unity/auto/type_sanitizer.rb @@ -0,0 +1,8 @@ +module TypeSanitizer + + def self.sanitize_c_identifier(unsanitized) + # convert filename to valid C identifier by replacing invalid chars with '_' + return unsanitized.gsub(/[-\/\\\.\,\s]/, "_") + end + +end diff --git a/tests/unity/auto/unity_test_summary.py b/tests/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*'))) + 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/tests/unity/auto/unity_test_summary.rb b/tests/unity/auto/unity_test_summary.rb @@ -0,0 +1,148 @@ +# ========================================== +# 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 + + def initialize(opts = {}) + @report = '' + @total_tests = 0 + @failures = 0 + @ignored = 0 + + + end + + def run + # Clean up result file names + results = @targets.map {|target| target.gsub(/\\/,'/')} + + # 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 { |line| line.chomp } + if lines.length == 0 + raise "Empty test result file: #{result_file}" + else + 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 + 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 set_targets(target_array) + @targets = target_array + end + + def set_root_path(path) + @root = path + 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 + return results + end + + def parse_test_summary(summary) + if summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + [$1.to_i,$2.to_i,$3.to_i] + else + raise "Couldn't parse test results: #{summary}" + end + end + + def here; File.expand_path(File.dirname(__FILE__)); 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].gsub(/\\/, '/')}**/*.test*" + results = Dir[targets] + raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? + uts.set_targets(results) + + #set the root path + args[1] ||= Dir.pwd + '/' + uts.set_root_path(ARGV[1]) + + #run the summarizer + puts uts.run + rescue Exception => e + uts.usage e.message + end +end diff --git a/tests/unity/auto/unity_to_junit.py b/tests/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/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf b/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf Binary files differ. diff --git a/tests/unity/docs/UnityAssertionsReference.pdf b/tests/unity/docs/UnityAssertionsReference.pdf Binary files differ. diff --git a/tests/unity/docs/UnityConfigurationGuide.pdf b/tests/unity/docs/UnityConfigurationGuide.pdf Binary files differ. diff --git a/tests/unity/docs/UnityGettingStartedGuide.pdf b/tests/unity/docs/UnityGettingStartedGuide.pdf Binary files differ. diff --git a/tests/unity/docs/UnityHelperScriptsGuide.pdf b/tests/unity/docs/UnityHelperScriptsGuide.pdf Binary files differ. diff --git a/tests/unity/docs/license.txt b/tests/unity/docs/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) <year> 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams + +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/tests/unity/examples/example_1/makefile b/tests/unity/examples/example_1/makefile @@ -0,0 +1,71 @@ +# ========================================== +# 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] +# ========================================== + +#We try to detect the OS we are running on, and adjust commands as needed +ifeq ($(OS),Windows_NT) + ifeq ($(shell uname -s),) # not in a bash-like shell + CLEANUP = del /F /Q + MKDIR = mkdir + else # in a bash-like shell, like msys + CLEANUP = rm -f + MKDIR = mkdir -p + endif + TARGET_EXTENSION=.exe +else + CLEANUP = rm -f + MKDIR = mkdir -p + TARGET_EXTENSION=.out +endif + +C_COMPILER=gcc +ifeq ($(shell uname -s), Darwin) +C_COMPILER=clang +endif + +UNITY_ROOT=../.. + +CFLAGS=-std=c89 +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -Wpointer-arith +CFLAGS += -Wcast-align +CFLAGS += -Wwrite-strings +CFLAGS += -Wswitch-default +CFLAGS += -Wunreachable-code +CFLAGS += -Winit-self +CFLAGS += -Wmissing-field-initializers +CFLAGS += -Wno-unknown-pragmas +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wundef +CFLAGS += -Wold-style-definition + +TARGET_BASE1=test1 +TARGET_BASE2=test2 +TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION) +TARGET2 = $(TARGET_BASE2)$(TARGET_EXTENSION) +SRC_FILES1=$(UNITY_ROOT)/src/unity.c src/ProductionCode.c test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c +SRC_FILES2=$(UNITY_ROOT)/src/unity.c src/ProductionCode2.c test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c +INC_DIRS=-Isrc -I$(UNITY_ROOT)/src +SYMBOLS= + +all: clean default + +default: $(SRC_FILES1) $(SRC_FILES2) + $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1) + $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES2) -o $(TARGET2) + - ./$(TARGET1) + ./$(TARGET2) + +test/test_runners/TestProductionCode_Runner.c: test/TestProductionCode.c + ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c +test/test_runners/TestProductionCode2_Runner.c: test/TestProductionCode2.c + ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c + +clean: + $(CLEANUP) $(TARGET1) $(TARGET2) + +ci: CFLAGS += -Werror +ci: default diff --git a/tests/unity/examples/example_1/readme.txt b/tests/unity/examples/example_1/readme.txt @@ -0,0 +1,5 @@ +Example 1 +========= + +Close to the simplest possible example of Unity, using only basic features. +Run make to build & run the example tests.+ \ No newline at end of file diff --git a/tests/unity/examples/example_1/src/ProductionCode.c b/tests/unity/examples/example_1/src/ProductionCode.c @@ -0,0 +1,24 @@ + +#include "ProductionCode.h" + +int Counter = 0; +int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */ + +/* This function is supposed to search through NumbersToFind and find a particular number. + * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since + * NumbersToFind is indexed from 1. Unfortunately it's broken + * (and should therefore be caught by our tests) */ +int FindFunction_WhichIsBroken(int NumberToFind) +{ + int i = 0; + while (i <= 8) /* Notice I should have been in braces */ + i++; + if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */ + return i; + return 0; +} + +int FunctionWhichReturnsLocalVariable(void) +{ + return Counter; +} diff --git a/tests/unity/examples/example_1/src/ProductionCode.h b/tests/unity/examples/example_1/src/ProductionCode.h @@ -0,0 +1,3 @@ + +int FindFunction_WhichIsBroken(int NumberToFind); +int FunctionWhichReturnsLocalVariable(void); diff --git a/tests/unity/examples/example_1/src/ProductionCode2.c b/tests/unity/examples/example_1/src/ProductionCode2.c @@ -0,0 +1,11 @@ + +#include "ProductionCode2.h" + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) +{ + (void)Poor; + (void)LittleFunction; + /* Since There Are No Tests Yet, This Function Could Be Empty For All We Know. + * Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget */ + return (char*)0; +} diff --git a/tests/unity/examples/example_1/src/ProductionCode2.h b/tests/unity/examples/example_1/src/ProductionCode2.h @@ -0,0 +1,2 @@ + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/tests/unity/examples/example_1/test/TestProductionCode.c b/tests/unity/examples/example_1/test/TestProductionCode.c @@ -0,0 +1,62 @@ + +#include "ProductionCode.h" +#include "unity.h" + +/* sometimes you may want to get at local data in a module. + * for example: If you plan to pass by reference, this could be useful + * however, it should often be avoided */ +extern int Counter; + +void setUp(void) +{ + /* This is run before EACH TEST */ + Counter = 0x5a5a; +} + +void tearDown(void) +{ +} + +void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void) +{ + /* All of these should pass */ + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); +} + +void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) +{ + /* You should see this line fail in your test summary */ + TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); + + /* Notice the rest of these didn't get a chance to run because the line above failed. + * Unit tests abort each test function on the first sign of trouble. + * Then NEXT test function runs as normal. */ + TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void) +{ + /* This should be true because setUp set this up for us before this test */ + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); + + /* This should be true because we can still change our answer */ + Counter = 0x1234; + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void) +{ + /* This should be true again because setup was rerun before this test (and after we changed it to 0x1234) */ + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void) +{ + /* Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell + * you what actually happened...which in this case was a failure to setup the initial condition. */ + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} diff --git a/tests/unity/examples/example_1/test/TestProductionCode2.c b/tests/unity/examples/example_1/test/TestProductionCode2.c @@ -0,0 +1,31 @@ + +#include "ProductionCode2.h" +#include "unity.h" + +/* These should be ignored because they are commented out in various ways: +#include "whatever.h" +#include "somethingelse.h" +*/ + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_IgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); +} + +void test_AnotherIgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); +} + +void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void) +{ + TEST_IGNORE(); /* Like This */ +} diff --git a/tests/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c b/tests/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c @@ -0,0 +1,53 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT()) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "ProductionCode2.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_IgnoredTest(void); +extern void test_AnotherIgnoredTest(void); +extern void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("test/TestProductionCode2.c"); + RUN_TEST(test_IgnoredTest, 18); + RUN_TEST(test_AnotherIgnoredTest, 23); + RUN_TEST(test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented, 28); + + return (UnityEnd()); +} diff --git a/tests/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c b/tests/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c @@ -0,0 +1,57 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT()) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "ProductionCode.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void); +extern void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("test/TestProductionCode.c"); + RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode, 20); + RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken, 30); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue, 41); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain, 51); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed, 57); + + return (UnityEnd()); +} diff --git a/tests/unity/examples/example_2/makefile b/tests/unity/examples/example_2/makefile @@ -0,0 +1,70 @@ +# ========================================== +# 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] +# ========================================== + +#We try to detect the OS we are running on, and adjust commands as needed +ifeq ($(OS),Windows_NT) + ifeq ($(shell uname -s),) # not in a bash-like shell + CLEANUP = del /F /Q + MKDIR = mkdir + else # in a bash-like shell, like msys + CLEANUP = rm -f + MKDIR = mkdir -p + endif + TARGET_EXTENSION=.exe +else + CLEANUP = rm -f + MKDIR = mkdir -p + TARGET_EXTENSION=.out +endif + +C_COMPILER=gcc +ifeq ($(shell uname -s), Darwin) +C_COMPILER=clang +endif + +UNITY_ROOT=../.. + +CFLAGS=-std=c99 +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -Wpointer-arith +CFLAGS += -Wcast-align +CFLAGS += -Wwrite-strings +CFLAGS += -Wswitch-default +CFLAGS += -Wunreachable-code +CFLAGS += -Winit-self +CFLAGS += -Wmissing-field-initializers +CFLAGS += -Wno-unknown-pragmas +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wundef +CFLAGS += -Wold-style-definition + +TARGET_BASE1=all_tests +TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION) +SRC_FILES1=\ + $(UNITY_ROOT)/src/unity.c \ + $(UNITY_ROOT)/extras/fixture/src/unity_fixture.c \ + src/ProductionCode.c \ + src/ProductionCode2.c \ + test/TestProductionCode.c \ + test/TestProductionCode2.c \ + test/test_runners/TestProductionCode_Runner.c \ + test/test_runners/TestProductionCode2_Runner.c \ + test/test_runners/all_tests.c +INC_DIRS=-Isrc -I$(UNITY_ROOT)/src -I$(UNITY_ROOT)/extras/fixture/src +SYMBOLS= + +all: clean default + +default: + $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1) + - ./$(TARGET1) -v + +clean: + $(CLEANUP) $(TARGET1) + +ci: CFLAGS += -Werror +ci: default diff --git a/tests/unity/examples/example_2/readme.txt b/tests/unity/examples/example_2/readme.txt @@ -0,0 +1,5 @@ +Example 2 +========= + +Same as the first example, but now using Unity's test fixture to group tests +together. Using the test fixture also makes writing test runners much easier.+ \ No newline at end of file diff --git a/tests/unity/examples/example_2/src/ProductionCode.c b/tests/unity/examples/example_2/src/ProductionCode.c @@ -0,0 +1,24 @@ + +#include "ProductionCode.h" + +int Counter = 0; +int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0. + +// This function is supposed to search through NumbersToFind and find a particular number. +// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since +// NumbersToFind is indexed from 1. Unfortunately it's broken +// (and should therefore be caught by our tests) +int FindFunction_WhichIsBroken(int NumberToFind) +{ + int i = 0; + while (i <= 8) //Notice I should have been in braces + i++; + if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it! + return i; + return 0; +} + +int FunctionWhichReturnsLocalVariable(void) +{ + return Counter; +} diff --git a/tests/unity/examples/example_2/src/ProductionCode.h b/tests/unity/examples/example_2/src/ProductionCode.h @@ -0,0 +1,3 @@ + +int FindFunction_WhichIsBroken(int NumberToFind); +int FunctionWhichReturnsLocalVariable(void); diff --git a/tests/unity/examples/example_2/src/ProductionCode2.c b/tests/unity/examples/example_2/src/ProductionCode2.c @@ -0,0 +1,11 @@ + +#include "ProductionCode2.h" + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) +{ + (void)Poor; + (void)LittleFunction; + //Since There Are No Tests Yet, This Function Could Be Empty For All We Know. + // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget + return (char*)0; +} diff --git a/tests/unity/examples/example_2/src/ProductionCode2.h b/tests/unity/examples/example_2/src/ProductionCode2.h @@ -0,0 +1,2 @@ + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/tests/unity/examples/example_2/test/TestProductionCode.c b/tests/unity/examples/example_2/test/TestProductionCode.c @@ -0,0 +1,64 @@ +#include "ProductionCode.h" +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP(ProductionCode); + +//sometimes you may want to get at local data in a module. +//for example: If you plan to pass by reference, this could be useful +//however, it should often be avoided +extern int Counter; + +TEST_SETUP(ProductionCode) +{ + //This is run before EACH TEST + Counter = 0x5a5a; +} + +TEST_TEAR_DOWN(ProductionCode) +{ +} + +TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode) +{ + //All of these should pass + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); +} + +TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken) +{ + // You should see this line fail in your test summary + TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); + + // Notice the rest of these didn't get a chance to run because the line above failed. + // Unit tests abort each test function on the first sign of trouble. + // Then NEXT test function runs as normal. + TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); +} + +TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue) +{ + //This should be true because setUp set this up for us before this test + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); + + //This should be true because we can still change our answer + Counter = 0x1234; + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} + +TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain) +{ + //This should be true again because setup was rerun before this test (and after we changed it to 0x1234) + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); +} + +TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed) +{ + //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell + // you what actually happened...which in this case was a failure to setup the initial condition. + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} diff --git a/tests/unity/examples/example_2/test/TestProductionCode2.c b/tests/unity/examples/example_2/test/TestProductionCode2.c @@ -0,0 +1,33 @@ +#include "ProductionCode2.h" +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP(ProductionCode2); + +/* These should be ignored because they are commented out in various ways: +#include "whatever.h" +*/ +//#include "somethingelse.h" + +TEST_SETUP(ProductionCode2) +{ +} + +TEST_TEAR_DOWN(ProductionCode2) +{ +} + +TEST(ProductionCode2, IgnoredTest) +{ + TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); +} + +TEST(ProductionCode2, AnotherIgnoredTest) +{ + TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); +} + +TEST(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented) +{ + TEST_IGNORE(); //Like This +} diff --git a/tests/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c b/tests/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c @@ -0,0 +1,9 @@ +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP_RUNNER(ProductionCode2) +{ + RUN_TEST_CASE(ProductionCode2, IgnoredTest); + RUN_TEST_CASE(ProductionCode2, AnotherIgnoredTest); + RUN_TEST_CASE(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented); +}+ \ No newline at end of file diff --git a/tests/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c b/tests/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c @@ -0,0 +1,11 @@ +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP_RUNNER(ProductionCode) +{ + RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode); + RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken); + RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue); + RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain); + RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed); +}+ \ No newline at end of file diff --git a/tests/unity/examples/example_2/test/test_runners/all_tests.c b/tests/unity/examples/example_2/test/test_runners/all_tests.c @@ -0,0 +1,12 @@ +#include "unity_fixture.h" + +static void RunAllTests(void) +{ + RUN_TEST_GROUP(ProductionCode); + RUN_TEST_GROUP(ProductionCode2); +} + +int main(int argc, const char * argv[]) +{ + return UnityMain(argc, argv, RunAllTests); +} diff --git a/tests/unity/examples/example_3/helper/UnityHelper.c b/tests/unity/examples/example_3/helper/UnityHelper.c @@ -0,0 +1,10 @@ +#include "unity.h" +#include "UnityHelper.h" +#include <stdio.h> +#include <string.h> + +void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line) +{ + UNITY_TEST_ASSERT_EQUAL_INT(expected.x, actual.x, line, "Example Struct Failed For Field x"); + UNITY_TEST_ASSERT_EQUAL_INT(expected.y, actual.y, line, "Example Struct Failed For Field y"); +} diff --git a/tests/unity/examples/example_3/helper/UnityHelper.h b/tests/unity/examples/example_3/helper/UnityHelper.h @@ -0,0 +1,12 @@ +#ifndef _TESTHELPER_H +#define _TESTHELPER_H + +#include "Types.h" + +void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line); + +#define UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, line, message) AssertEqualExampleStruct(expected, actual, line); + +#define TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual) UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, __LINE__, NULL); + +#endif // _TESTHELPER_H diff --git a/tests/unity/examples/example_3/rakefile.rb b/tests/unity/examples/example_3/rakefile.rb @@ -0,0 +1,43 @@ +HERE = File.expand_path(File.dirname(__FILE__)) + '/' +UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..' + +require 'rake' +require 'rake/clean' +require HERE+'rakefile_helper' + +TEMP_DIRS = [ + File.join(HERE, 'build') +] + +TEMP_DIRS.each do |dir| + directory(dir) + CLOBBER.include(dir) +end + +task :prepare_for_tests => TEMP_DIRS + +include RakefileHelpers + +# Load default configuration, for now +DEFAULT_CONFIG_FILE = 'target_gcc_32.yml' +configure_toolchain(DEFAULT_CONFIG_FILE) + +task :unit => [:prepare_for_tests] do + run_tests get_unit_test_files +end + +desc "Generate test summary" +task :summary do + report_summary +end + +desc "Build and test Unity" +task :all => [:clean, :unit, :summary] +task :default => [:clobber, :all] +task :ci => [:default] +task :cruise => [:default] + +desc "Load configuration" +task :config, :config_file do |t, args| + configure_toolchain(args[:config_file]) +end diff --git a/tests/unity/examples/example_3/rakefile_helper.rb b/tests/unity/examples/example_3/rakefile_helper.rb @@ -0,0 +1,258 @@ +require 'yaml' +require 'fileutils' +require UNITY_ROOT+'/auto/unity_test_summary' +require UNITY_ROOT+'/auto/generate_test_runner' +require UNITY_ROOT+'/auto/colour_reporter' + +module RakefileHelpers + + C_EXTENSION = '.c' + + def load_configuration(config_file) + $cfg_file = config_file + $cfg = YAML.load(File.read($cfg_file)) + end + + def configure_clean + CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? + end + + def configure_toolchain(config_file=DEFAULT_CONFIG_FILE) + config_file += '.yml' unless config_file =~ /\.yml$/ + load_configuration(config_file) + configure_clean + end + + def get_unit_test_files + path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION + path.gsub!(/\\/, '/') + FileList.new(path) + end + + def get_local_include_dirs + include_dirs = $cfg['compiler']['includes']['items'].dup + include_dirs.delete_if {|dir| dir.is_a?(Array)} + return include_dirs + end + + def extract_headers(filename) + includes = [] + lines = File.readlines(filename) + lines.each do |line| + m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) + if not m.nil? + includes << m[1] + end + end + return includes + end + + def find_source_file(header, paths) + paths.each do |dir| + src_file = dir + header.ext(C_EXTENSION) + if (File.exists?(src_file)) + return src_file + end + end + return nil + end + + def tackit(strings) + if strings.is_a?(Array) + result = "\"#{strings.join}\"" + else + result = strings + end + return result + end + + def squash(prefix, items) + result = '' + items.each { |item| result += " #{prefix}#{tackit(item)}" } + return result + end + + def build_compiler_fields + command = tackit($cfg['compiler']['path']) + if $cfg['compiler']['defines']['items'].nil? + defines = '' + else + defines = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items']) + end + options = squash('', $cfg['compiler']['options']) + includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) + includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + return {:command => command, :defines => defines, :options => options, :includes => includes} + end + + def compile(file, defines=[]) + compiler = build_compiler_fields + cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " + + "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" + obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" + execute(cmd_str + obj_file) + return obj_file + end + + def build_linker_fields + command = tackit($cfg['linker']['path']) + if $cfg['linker']['options'].nil? + options = '' + else + options = squash('', $cfg['linker']['options']) + end + if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?) + includes = '' + else + includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) + end + includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + return {:command => command, :options => options, :includes => includes} + end + + def link_it(exe_name, obj_list) + linker = build_linker_fields + cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + + (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join + + $cfg['linker']['bin_files']['prefix'] + ' ' + + $cfg['linker']['bin_files']['destination'] + + exe_name + $cfg['linker']['bin_files']['extension'] + execute(cmd_str) + end + + def build_simulator_fields + return nil if $cfg['simulator'].nil? + if $cfg['simulator']['path'].nil? + command = '' + else + command = (tackit($cfg['simulator']['path']) + ' ') + end + if $cfg['simulator']['pre_support'].nil? + pre_support = '' + else + pre_support = squash('', $cfg['simulator']['pre_support']) + end + if $cfg['simulator']['post_support'].nil? + post_support = '' + else + post_support = squash('', $cfg['simulator']['post_support']) + end + return {:command => command, :pre_support => pre_support, :post_support => post_support} + end + + def execute(command_string, verbose=true, raise_on_fail=true) + report command_string + output = `#{command_string}`.chomp + report(output) if (verbose && !output.nil? && (output.length > 0)) + if (($?.exitstatus != 0) and (raise_on_fail)) + raise "Command failed. (Returned #{$?.exitstatus})" + end + return output + end + + def report_summary + summary = UnityTestSummary.new + summary.set_root_path(HERE) + results_glob = "#{$cfg['compiler']['build_path']}*.test*" + results_glob.gsub!(/\\/, '/') + results = Dir[results_glob] + summary.set_targets(results) + summary.run + fail_out "FAIL: There were failures" if (summary.failures > 0) + end + + def run_tests(test_files) + + report 'Running system tests...' + + # Tack on TEST define for compiling unit tests + load_configuration($cfg_file) + test_defines = ['TEST'] + $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? + $cfg['compiler']['defines']['items'] << 'TEST' + + include_dirs = get_local_include_dirs + + # Build and execute each unit test + test_files.each do |test| + obj_list = [] + + # Detect dependencies and build required required modules + extract_headers(test).each do |header| + # Compile corresponding source file if it exists + src_file = find_source_file(header, include_dirs) + if !src_file.nil? + obj_list << compile(src_file, test_defines) + end + end + + # Build the test runner (generate if configured to do so) + test_base = File.basename(test, C_EXTENSION) + runner_name = test_base + '_Runner.c' + if $cfg['compiler']['runner_path'].nil? + runner_path = $cfg['compiler']['build_path'] + runner_name + test_gen = UnityTestRunnerGenerator.new($cfg_file) + test_gen.run(test, runner_path) + else + runner_path = $cfg['compiler']['runner_path'] + runner_name + end + + obj_list << compile(runner_path, test_defines) + + # Build the test module + obj_list << compile(test, test_defines) + + # Link the test executable + link_it(test_base, obj_list) + + # Execute unit test and generate results file + simulator = build_simulator_fields + executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + if simulator.nil? + cmd_str = executable + else + cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" + end + output = execute(cmd_str, true, false) + test_results = $cfg['compiler']['build_path'] + test_base + if output.match(/OK$/m).nil? + test_results += '.testfail' + else + test_results += '.testpass' + end + File.open(test_results, 'w') { |f| f.print output } + end + end + + def build_application(main) + + report "Building application..." + + obj_list = [] + load_configuration($cfg_file) + main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION + + # Detect dependencies and build required required modules + include_dirs = get_local_include_dirs + extract_headers(main_path).each do |header| + src_file = find_source_file(header, include_dirs) + if !src_file.nil? + obj_list << compile(src_file) + end + end + + # Build the main source file + main_base = File.basename(main_path, C_EXTENSION) + obj_list << compile(main_path) + + # Create the executable + link_it(main_base, obj_list) + end + + def fail_out(msg) + puts msg + puts "Not returning exit code so continuous integration can pass" +# exit(-1) # Only removed to pass example_3, which has failing tests on purpose. +# Still fail if the build fails for any other reason. + end +end diff --git a/tests/unity/examples/example_3/readme.txt b/tests/unity/examples/example_3/readme.txt @@ -0,0 +1,13 @@ +Example 3 +========= + +This example project gives an example of some passing, ignored, and failing tests. +It's simple and meant for you to look over and get an idea for what all of this stuff does. + +You can build and test using rake. The rake version will let you test with gcc or a couple +versions of IAR. You can tweak the yaml files to get those versions running. + +Ruby is required if you're using the rake version (obviously). This version shows off most of +Unity's advanced features (automatically creating test runners, fancy summaries, etc.) +Without ruby, you have to maintain your own test runners. Do that for a while and you'll learn +why you really want to start using the Ruby tools. diff --git a/tests/unity/examples/example_3/src/ProductionCode.c b/tests/unity/examples/example_3/src/ProductionCode.c @@ -0,0 +1,24 @@ + +#include "ProductionCode.h" + +int Counter = 0; +int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0. + +// This function is supposed to search through NumbersToFind and find a particular number. +// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since +// NumbersToFind is indexed from 1. Unfortunately it's broken +// (and should therefore be caught by our tests) +int FindFunction_WhichIsBroken(int NumberToFind) +{ + int i = 0; + while (i <= 8) //Notice I should have been in braces + i++; + if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it! + return i; + return 0; +} + +int FunctionWhichReturnsLocalVariable(void) +{ + return Counter; +} diff --git a/tests/unity/examples/example_3/src/ProductionCode.h b/tests/unity/examples/example_3/src/ProductionCode.h @@ -0,0 +1,3 @@ + +int FindFunction_WhichIsBroken(int NumberToFind); +int FunctionWhichReturnsLocalVariable(void); diff --git a/tests/unity/examples/example_3/src/ProductionCode2.c b/tests/unity/examples/example_3/src/ProductionCode2.c @@ -0,0 +1,11 @@ + +#include "ProductionCode2.h" + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) +{ + (void)Poor; + (void)LittleFunction; + //Since There Are No Tests Yet, This Function Could Be Empty For All We Know. + // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget + return (char*)0; +} diff --git a/tests/unity/examples/example_3/src/ProductionCode2.h b/tests/unity/examples/example_3/src/ProductionCode2.h @@ -0,0 +1,2 @@ + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/tests/unity/examples/example_3/target_gcc_32.yml b/tests/unity/examples/example_3/target_gcc_32.yml @@ -0,0 +1,46 @@ +# Copied from ~Unity/targets/gcc_32.yml +unity_root: &unity_root '../..' +compiler: + path: gcc + source_path: 'src/' + unit_tests_path: &unit_tests_path 'test/' + build_path: &build_path 'build/' + options: + - '-c' + - '-m32' + - '-Wall' + - '-Wno-address' + - '-std=c99' + - '-pedantic' + includes: + prefix: '-I' + items: + - 'src/' + - '../../src/' + - *unit_tests_path + defines: + prefix: '-D' + items: + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + object_files: + prefix: '-o' + extension: '.o' + destination: *build_path +linker: + path: gcc + options: + - -lm + - '-m32' + includes: + prefix: '-I' + object_files: + path: *build_path + extension: '.o' + bin_files: + prefix: '-o' + extension: '.exe' + destination: *build_path +colour: true +:unity: + :plugins: [] diff --git a/tests/unity/examples/example_3/test/TestProductionCode.c b/tests/unity/examples/example_3/test/TestProductionCode.c @@ -0,0 +1,62 @@ + +#include "ProductionCode.h" +#include "unity.h" + +//sometimes you may want to get at local data in a module. +//for example: If you plan to pass by reference, this could be useful +//however, it should often be avoided +extern int Counter; + +void setUp(void) +{ + //This is run before EACH TEST + Counter = 0x5a5a; +} + +void tearDown(void) +{ +} + +void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void) +{ + //All of these should pass + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); +} + +void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) +{ + // You should see this line fail in your test summary + TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); + + // Notice the rest of these didn't get a chance to run because the line above failed. + // Unit tests abort each test function on the first sign of trouble. + // Then NEXT test function runs as normal. + TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void) +{ + //This should be true because setUp set this up for us before this test + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); + + //This should be true because we can still change our answer + Counter = 0x1234; + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void) +{ + //This should be true again because setup was rerun before this test (and after we changed it to 0x1234) + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void) +{ + //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell + // you what actually happened...which in this case was a failure to setup the initial condition. + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} diff --git a/tests/unity/examples/example_3/test/TestProductionCode2.c b/tests/unity/examples/example_3/test/TestProductionCode2.c @@ -0,0 +1,31 @@ + +#include "ProductionCode2.h" +#include "unity.h" + +/* These should be ignored because they are commented out in various ways: +#include "whatever.h" +*/ +//#include "somethingelse.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_IgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); +} + +void test_AnotherIgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); +} + +void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void) +{ + TEST_IGNORE(); //Like This +} diff --git a/tests/unity/examples/unity_config.h b/tests/unity/examples/unity_config.h @@ -0,0 +1,237 @@ +/* Unity Configuration + * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529 + * Update: December 29th, 2016 + * See Also: Unity/docs/UnityConfigurationGuide.pdf + * + * 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 in order 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. + */ + +#ifndef UNITY_CONFIG_H +#define UNITY_CONFIG_H + +/* ************************* AUTOMATIC INTEGER TYPES *************************** + * 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. + **************************************************************************** */ + +/* The first attempt to guess your types is to check `limits.h`. Some compilers + * that don't support `stdint.h` could include `limits.h`. If you don't + * want Unity to check this file, define this to make it skip the inclusion. + * Unity looks at UINT_MAX & ULONG_MAX, which were available since C89. + */ +/* #define UNITY_EXCLUDE_LIMITS_H */ + +/* The second thing that Unity does to guess your types is check `stdint.h`. + * This file defines `UINTPTR_MAX`, since C99, that Unity can make use of to + * learn about your system. It's possible you don't want it to do this or 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. + */ +/* #define UNITY_EXCLUDE_STDINT_H */ + +/* ********************** MANUAL INTEGER TYPE DEFINITION *********************** + * If you've disabled all of the automatic options above, you're going to have + * to do the configuration yourself. There are just a handful of defines that + * you are going to specify if you don't like the defaults. + **************************************************************************** */ + + /* Define this to be the number of bits an `int` takes up on your system. The + * default, if not auto-detected, is 32 bits. + * + * Example: + */ +/* #define UNITY_INT_WIDTH 16 */ + +/* 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 */ + +/* 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 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. + */ +/* #define UNITY_INCLUDE_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. + **************************************************************************** */ + + /* 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, just float, + * or both, as suits your needs. + */ +/* #define UNITY_EXCLUDE_FLOAT */ +#define UNITY_INCLUDE_DOUBLE +/* #define UNITY_EXCLUDE_DOUBLE */ + +/* For features that are enabled, the following floating point options also + * become available. + */ + +/* 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. To keep Unity universal, though, we eventually chose to develop + * our own floating point print routines. Still, the display of floating point + * values during a failure are optional. By default, Unity will print the + * actual results of floating point assertion failures. So a failed assertion + * will produce a message like "Expected 4.0 Was 4.25". If you would like less + * verbose failure messages for floating point assertions, use this option to + * give a failure message `"Values Not Within Delta"` and trim the binary size. + */ +/* #define UNITY_EXCLUDE_FLOAT_PRINT */ + +/* 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 */ + +/* 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 */ + +/* If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as + * documented in the 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 */ +/* #define UNITY_DOUBLE_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 operate properly. These macros will help in those + * situations. + **************************************************************************** */ + +/* 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: + */ +/* #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) */ +/* #define UNITY_OUTPUT_FLUSH() RS232_flush() */ +/* #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) */ +/* #define UNITY_OUTPUT_COMPLETE() RS232_close() */ + +/* 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_SUPPORT_WEAK` 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). The + * most common options for this feature are: + */ +/* #define UNITY_SUPPORT_WEAK weak */ +/* #define UNITY_SUPPORT_WEAK __attribute__((weak)) */ +/* #define UNITY_NO_WEAK */ + +/* 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 */ + +#endif /* UNITY_CONFIG_H */ diff --git a/tests/unity/extras/eclipse/error_parsers.txt b/tests/unity/extras/eclipse/error_parsers.txt @@ -0,0 +1,26 @@ +Eclipse error parsers +===================== + +These are a godsend for extracting & quickly navigating to +warnings & error messages from console output. Unforunately +I don't know how to write an Eclipse plugin so you'll have +to add them manually. + +To add a console parser to Eclipse, go to Window --> Preferences +--> C/C++ --> Build --> Settings. Click on the 'Error Parsers' +tab and then click the 'Add...' button. See the table below for +the parser fields to add. + +Eclipse will only parse the console output during a build, so +running your unit tests must be part of your build process. +Either add this to your make/rakefile, or add it as a post- +build step in your Eclipse project settings. + + +Unity unit test error parsers +----------------------------- +Severity Pattern File Line Description +------------------------------------------------------------------------------- +Error (\.+)(.*?):(\d+):(.*?):FAIL: (.*) $2 $3 $5 +Warning (\.+)(.*?):(\d+):(.*?):IGNORE: (.*) $2 $3 $5 +Warning (\.+)(.*?):(\d+):(.*?):IGNORE\s*$ $2 $3 Ignored test diff --git a/tests/unity/extras/fixture/rakefile.rb b/tests/unity/extras/fixture/rakefile.rb @@ -0,0 +1,48 @@ +# ========================================== +# 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] +# ========================================== + +HERE = File.expand_path(File.dirname(__FILE__)) + '/' + +require 'rake' +require 'rake/clean' +require 'rake/testtask' +require HERE + 'rakefile_helper' + +TEMP_DIRS = [ + File.join(HERE, 'build') +] + +TEMP_DIRS.each do |dir| + directory(dir) + CLOBBER.include(dir) +end + +task :prepare_for_tests => TEMP_DIRS + +include RakefileHelpers + +# Load default configuration, for now +DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml' +configure_toolchain(DEFAULT_CONFIG_FILE) + +task :unit => [:prepare_for_tests] do + run_tests +end + +desc "Build and test Unity Framework" +task :all => [:clean, :unit] +task :default => [:clobber, :all] +task :ci => [:no_color, :default] +task :cruise => [:no_color, :default] + +desc "Load configuration" +task :config, :config_file do |t, args| + configure_toolchain(args[:config_file]) +end + +task :no_color do + $colour_output = false +end diff --git a/tests/unity/extras/fixture/rakefile_helper.rb b/tests/unity/extras/fixture/rakefile_helper.rb @@ -0,0 +1,179 @@ +# ========================================== +# 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' +require 'fileutils' +require HERE+'../../auto/unity_test_summary' +require HERE+'../../auto/generate_test_runner' +require HERE+'../../auto/colour_reporter' + +module RakefileHelpers + + C_EXTENSION = '.c' + + def load_configuration(config_file) + unless ($configured) + $cfg_file = HERE+"../../test/targets/#{config_file}" unless (config_file =~ /[\\|\/]/) + $cfg = YAML.load(File.read($cfg_file)) + $colour_output = false unless $cfg['colour'] + $configured = true if (config_file != DEFAULT_CONFIG_FILE) + end + end + + def configure_clean + CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? + end + + def configure_toolchain(config_file=DEFAULT_CONFIG_FILE) + config_file += '.yml' unless config_file =~ /\.yml$/ + config_file = config_file unless config_file =~ /[\\|\/]/ + load_configuration(config_file) + configure_clean + end + + def tackit(strings) + if strings.is_a?(Array) + result = "\"#{strings.join}\"" + else + result = strings + end + return result + end + + def squash(prefix, items) + result = '' + items.each { |item| result += " #{prefix}#{tackit(item)}" } + return result + end + + def build_compiler_fields + command = tackit($cfg['compiler']['path']) + if $cfg['compiler']['defines']['items'].nil? + defines = '' + else + defines = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar']) + end + options = squash('', $cfg['compiler']['options']) + includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) + includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + return {:command => command, :defines => defines, :options => options, :includes => includes} + end + + def compile(file, defines=[]) + compiler = build_compiler_fields + unity_include = $cfg['compiler']['includes']['prefix']+'../../src' + cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{file} " + + "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" + + "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" + execute(cmd_str) + end + + def build_linker_fields + command = tackit($cfg['linker']['path']) + if $cfg['linker']['options'].nil? + options = '' + else + options = squash('', $cfg['linker']['options']) + end + if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?) + includes = '' + else + includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) + end + includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + return {:command => command, :options => options, :includes => includes} + end + + def link_it(exe_name, obj_list) + linker = build_linker_fields + cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + + (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join + + $cfg['linker']['bin_files']['prefix'] + ' ' + + $cfg['linker']['bin_files']['destination'] + + exe_name + $cfg['linker']['bin_files']['extension'] + execute(cmd_str) + end + + def build_simulator_fields + return nil if $cfg['simulator'].nil? + if $cfg['simulator']['path'].nil? + command = '' + else + command = (tackit($cfg['simulator']['path']) + ' ') + end + if $cfg['simulator']['pre_support'].nil? + pre_support = '' + else + pre_support = squash('', $cfg['simulator']['pre_support']) + end + if $cfg['simulator']['post_support'].nil? + post_support = '' + else + post_support = squash('', $cfg['simulator']['post_support']) + end + return {:command => command, :pre_support => pre_support, :post_support => post_support} + end + + def execute(command_string, verbose=true) + report command_string + output = `#{command_string}`.chomp + report(output) if (verbose && !output.nil? && (output.length > 0)) + if ($?.exitstatus != 0) + raise "Command failed. (Returned #{$?.exitstatus})" + end + return output + end + + def report_summary + summary = UnityTestSummary.new + summary.set_root_path(HERE) + results_glob = "#{$cfg['compiler']['build_path']}*.test*" + results_glob.gsub!(/\\/, '/') + results = Dir[results_glob] + summary.set_targets(results) + summary.run + end + + def run_tests + report 'Running Unity system tests...' + + # Tack on TEST define for compiling unit tests + load_configuration($cfg_file) + test_defines = ['TEST'] + $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? + + # Get a list of all source files needed + src_files = Dir[HERE+'src/*.c'] + src_files += Dir[HERE+'test/*.c'] + src_files += Dir[HERE+'test/main/*.c'] + src_files << '../../src/unity.c' + + # Build object files + src_files.each { |f| compile(f, test_defines) } + obj_list = src_files.map {|f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) } + + # Link the test executable + test_base = "framework_test" + link_it(test_base, obj_list) + + # Execute unit test and generate results file + simulator = build_simulator_fields + executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + if simulator.nil? + cmd_str = executable + " -v -r" + else + cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" + end + output = execute(cmd_str) + test_results = $cfg['compiler']['build_path'] + test_base + if output.match(/OK$/m).nil? + test_results += '.testfail' + else + test_results += '.testpass' + end + File.open(test_results, 'w') { |f| f.print output } + end +end diff --git a/tests/unity/extras/fixture/readme.txt b/tests/unity/extras/fixture/readme.txt @@ -0,0 +1,9 @@ +Copyright (c) 2010 James Grenning and Contributed to Unity Project + +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 Framework is an optional add-on to Unity. By including unity_framework.h in place of unity.h, +you may now work with Unity in a manner similar to CppUTest. This framework adds the concepts of +test groups and gives finer control of your tests over the command line.+ \ No newline at end of file diff --git a/tests/unity/extras/fixture/src/unity_fixture.c b/tests/unity/extras/fixture/src/unity_fixture.c @@ -0,0 +1,432 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#include "unity_fixture.h" +#include "unity_internals.h" +#include <string.h> + +struct UNITY_FIXTURE_T UnityFixture; + +/* If you decide to use the function pointer approach. + * Build with -D UNITY_OUTPUT_CHAR=outputChar and include <stdio.h> + * int (*outputChar)(int) = putchar; */ + +#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) +void setUp(void) { /*does nothing*/ } +void tearDown(void) { /*does nothing*/ } +#endif + +static void announceTestRun(unsigned int runNumber) +{ + UnityPrint("Unity test run "); + UnityPrintNumberUnsigned(runNumber+1); + UnityPrint(" of "); + UnityPrintNumberUnsigned(UnityFixture.RepeatCount); + UNITY_PRINT_EOL(); +} + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)) +{ + int result = UnityGetCommandLineOptions(argc, argv); + unsigned int r; + if (result != 0) + return result; + + for (r = 0; r < UnityFixture.RepeatCount; r++) + { + UnityBegin(argv[0]); + announceTestRun(r); + runAllTests(); + if (!UnityFixture.Verbose) UNITY_PRINT_EOL(); + UnityEnd(); + } + + return (int)Unity.TestFailures; +} + +static int selected(const char* filter, const char* name) +{ + if (filter == 0) + return 1; + return strstr(name, filter) ? 1 : 0; +} + +static int testSelected(const char* test) +{ + return selected(UnityFixture.NameFilter, test); +} + +static int groupSelected(const char* group) +{ + return selected(UnityFixture.GroupFilter, group); +} + +void UnityTestRunner(unityfunction* setup, + unityfunction* testBody, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, + unsigned int line) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.TestFile = file; + Unity.CurrentTestName = printableName; + Unity.CurrentTestLineNumber = line; + if (!UnityFixture.Verbose) + UNITY_OUTPUT_CHAR('.'); + else + { + UnityPrint(printableName); + #ifndef UNITY_REPEAT_TEST_NAME + Unity.CurrentTestName = NULL; + #endif + } + + Unity.NumberOfTests++; + UnityMalloc_StartTest(); + UnityPointer_Init(); + + if (TEST_PROTECT()) + { + setup(); + testBody(); + } + if (TEST_PROTECT()) + { + teardown(); + } + if (TEST_PROTECT()) + { + UnityPointer_UndoAllSets(); + if (!Unity.CurrentTestFailed) + UnityMalloc_EndTest(); + } + UnityConcludeFixtureTest(); + } +} + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.NumberOfTests++; + Unity.TestIgnores++; + if (!UnityFixture.Verbose) + UNITY_OUTPUT_CHAR('!'); + else + { + UnityPrint(printableName); + UNITY_PRINT_EOL(); + } + } +} + + +/*------------------------------------------------- */ +/* Malloc and free stuff */ +#define MALLOC_DONT_FAIL -1 +static int malloc_count; +static int malloc_fail_countdown = MALLOC_DONT_FAIL; + +void UnityMalloc_StartTest(void) +{ + malloc_count = 0; + malloc_fail_countdown = MALLOC_DONT_FAIL; +} + +void UnityMalloc_EndTest(void) +{ + malloc_fail_countdown = MALLOC_DONT_FAIL; + if (malloc_count != 0) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!"); + } +} + +void UnityMalloc_MakeMallocFailAfterCount(int countdown) +{ + malloc_fail_countdown = countdown; +} + +/* These definitions are always included from unity_fixture_malloc_overrides.h */ +/* We undef to use them or avoid conflict with <stdlib.h> per the C standard */ +#undef malloc +#undef free +#undef calloc +#undef realloc + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES]; +static size_t heap_index; +#else +#include <stdlib.h> +#endif + +typedef struct GuardBytes +{ + size_t size; + size_t guard_space; +} Guard; + + +static const char end[] = "END"; + +void* unity_malloc(size_t size) +{ + char* mem; + Guard* guard; + size_t total_size = size + sizeof(Guard) + sizeof(end); + + if (malloc_fail_countdown != MALLOC_DONT_FAIL) + { + if (malloc_fail_countdown == 0) + return NULL; + malloc_fail_countdown--; + } + + if (size == 0) return NULL; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES) + { + guard = NULL; + } + else + { + guard = (Guard*)&unity_heap[heap_index]; + heap_index += total_size; + } +#else + guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size); +#endif + if (guard == NULL) return NULL; + malloc_count++; + guard->size = size; + guard->guard_space = 0; + mem = (char*)&(guard[1]); + memcpy(&mem[size], end, sizeof(end)); + + return (void*)mem; +} + +static int isOverrun(void* mem) +{ + Guard* guard = (Guard*)mem; + char* memAsChar = (char*)mem; + guard--; + + return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0; +} + +static void release_memory(void* mem) +{ + Guard* guard = (Guard*)mem; + guard--; + + malloc_count--; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + if (mem == unity_heap + heap_index - guard->size - sizeof(end)) + { + heap_index -= (guard->size + sizeof(Guard) + sizeof(end)); + } +#else + UNITY_FIXTURE_FREE(guard); +#endif +} + +void unity_free(void* mem) +{ + int overrun; + + if (mem == NULL) + { + return; + } + + overrun = isOverrun(mem); + release_memory(mem); + if (overrun) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()"); + } +} + +void* unity_calloc(size_t num, size_t size) +{ + void* mem = unity_malloc(num * size); + if (mem == NULL) return NULL; + memset(mem, 0, num * size); + return mem; +} + +void* unity_realloc(void* oldMem, size_t size) +{ + Guard* guard = (Guard*)oldMem; + void* newMem; + + if (oldMem == NULL) return unity_malloc(size); + + guard--; + if (isOverrun(oldMem)) + { + release_memory(oldMem); + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()"); + } + + if (size == 0) + { + release_memory(oldMem); + return NULL; + } + + if (guard->size >= size) return oldMem; + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */ + if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) && + heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES) + { + release_memory(oldMem); /* Not thread-safe, like unity_heap generally */ + return unity_malloc(size); /* No memcpy since data is in place */ + } +#endif + newMem = unity_malloc(size); + if (newMem == NULL) return NULL; /* Do not release old memory */ + memcpy(newMem, oldMem, guard->size); + release_memory(oldMem); + return newMem; +} + + +/*-------------------------------------------------------- */ +/*Automatic pointer restoration functions */ +struct PointerPair +{ + void** pointer; + void* old_value; +}; + +static struct PointerPair pointer_store[UNITY_MAX_POINTERS]; +static int pointer_index = 0; + +void UnityPointer_Init(void) +{ + pointer_index = 0; +} + +void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line) +{ + if (pointer_index >= UNITY_MAX_POINTERS) + { + UNITY_TEST_FAIL(line, "Too many pointers set"); + } + else + { + pointer_store[pointer_index].pointer = pointer; + pointer_store[pointer_index].old_value = *pointer; + *pointer = newValue; + pointer_index++; + } +} + +void UnityPointer_UndoAllSets(void) +{ + while (pointer_index > 0) + { + pointer_index--; + *(pointer_store[pointer_index].pointer) = + pointer_store[pointer_index].old_value; + } +} + +int UnityGetCommandLineOptions(int argc, const char* argv[]) +{ + int i; + UnityFixture.Verbose = 0; + UnityFixture.GroupFilter = 0; + UnityFixture.NameFilter = 0; + UnityFixture.RepeatCount = 1; + + if (argc == 1) + return 0; + + for (i = 1; i < argc; ) + { + if (strcmp(argv[i], "-v") == 0) + { + UnityFixture.Verbose = 1; + i++; + } + else if (strcmp(argv[i], "-g") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.GroupFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-n") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.NameFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-r") == 0) + { + UnityFixture.RepeatCount = 2; + i++; + if (i < argc) + { + if (*(argv[i]) >= '0' && *(argv[i]) <= '9') + { + unsigned int digit = 0; + UnityFixture.RepeatCount = 0; + while (argv[i][digit] >= '0' && argv[i][digit] <= '9') + { + UnityFixture.RepeatCount *= 10; + UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0'; + } + i++; + } + } + } + else + { + /* ignore unknown parameter */ + i++; + } + } + return 0; +} + +void UnityConcludeFixtureTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + UNITY_PRINT_EOL(); + } + else if (!Unity.CurrentTestFailed) + { + if (UnityFixture.Verbose) + { + UnityPrint(" PASS"); + UNITY_PRINT_EOL(); + } + } + else /* Unity.CurrentTestFailed */ + { + Unity.TestFailures++; + UNITY_PRINT_EOL(); + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; +} diff --git a/tests/unity/extras/fixture/src/unity_fixture.h b/tests/unity/extras/fixture/src/unity_fixture.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#ifndef UNITY_FIXTURE_H_ +#define UNITY_FIXTURE_H_ + +#include "unity.h" +#include "unity_internals.h" +#include "unity_fixture_malloc_overrides.h" +#include "unity_fixture_internals.h" + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)); + + +#define TEST_GROUP(group)\ + static const char* TEST_GROUP_##group = #group + +#define TEST_SETUP(group) void TEST_##group##_SETUP(void);\ + void TEST_##group##_SETUP(void) + +#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN(void);\ + void TEST_##group##_TEAR_DOWN(void) + + +#define TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityTestRunner(TEST_##group##_SETUP,\ + TEST_##group##_##name##_,\ + TEST_##group##_TEAR_DOWN,\ + "TEST(" #group ", " #name ")",\ + TEST_GROUP_##group, #name,\ + __FILE__, __LINE__);\ + }\ + void TEST_##group##_##name##_(void) + +#define IGNORE_TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityIgnoreTest("IGNORE_TEST(" #group ", " #name ")", TEST_GROUP_##group, #name);\ + }\ + void TEST_##group##_##name##_(void) + +/* Call this for each test, insider the group runner */ +#define RUN_TEST_CASE(group, name) \ + { void TEST_##group##_##name##_run(void);\ + TEST_##group##_##name##_run(); } + +/* This goes at the bottom of each test file or in a separate c file */ +#define TEST_GROUP_RUNNER(group)\ + void TEST_##group##_GROUP_RUNNER(void);\ + void TEST_##group##_GROUP_RUNNER(void) + +/* Call this from main */ +#define RUN_TEST_GROUP(group)\ + { void TEST_##group##_GROUP_RUNNER(void);\ + TEST_##group##_GROUP_RUNNER(); } + +/* CppUTest Compatibility Macros */ +#ifndef UNITY_EXCLUDE_CPPUTEST_ASSERTS +/* Sets a pointer and automatically restores it to its old value after teardown */ +#define UT_PTR_SET(ptr, newPointerValue) UnityPointer_Set((void**)&(ptr), (void*)(newPointerValue), __LINE__) +#define TEST_ASSERT_POINTERS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_PTR((expected), (actual)) +#define TEST_ASSERT_BYTES_EQUAL(expected, actual) TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual)) +#define FAIL(message) TEST_FAIL_MESSAGE((message)) +#define CHECK(condition) TEST_ASSERT_TRUE((condition)) +#define LONGS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_INT((expected), (actual)) +#define STRCMP_EQUAL(expected, actual) TEST_ASSERT_EQUAL_STRING((expected), (actual)) +#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual)) +#endif + +/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */ +void UnityMalloc_MakeMallocFailAfterCount(int count); + +#endif /* UNITY_FIXTURE_H_ */ diff --git a/tests/unity/extras/fixture/src/unity_fixture_internals.h b/tests/unity/extras/fixture/src/unity_fixture_internals.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#ifndef UNITY_FIXTURE_INTERNALS_H_ +#define UNITY_FIXTURE_INTERNALS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct UNITY_FIXTURE_T +{ + int Verbose; + unsigned int RepeatCount; + const char* NameFilter; + const char* GroupFilter; +}; +extern struct UNITY_FIXTURE_T UnityFixture; + +typedef void unityfunction(void); +void UnityTestRunner(unityfunction* setup, + unityfunction* body, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, unsigned int line); + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name); +void UnityMalloc_StartTest(void); +void UnityMalloc_EndTest(void); +int UnityGetCommandLineOptions(int argc, const char* argv[]); +void UnityConcludeFixtureTest(void); + +void UnityPointer_Set(void** ptr, void* newValue, UNITY_LINE_TYPE line); +void UnityPointer_UndoAllSets(void); +void UnityPointer_Init(void); +#ifndef UNITY_MAX_POINTERS +#define UNITY_MAX_POINTERS 5 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* UNITY_FIXTURE_INTERNALS_H_ */ diff --git a/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h b/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_ +#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_ + +#include <stddef.h> + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +/* Define this macro to remove the use of stdlib.h, malloc, and free. + * Many embedded systems do not have a heap or malloc/free by default. + * This internal unity_malloc() provides allocated memory deterministically from + * the end of an array only, unity_free() only releases from end-of-array, + * blocks are not coalesced, and memory not freed in LIFO order is stranded. */ + #ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES + #define UNITY_INTERNAL_HEAP_SIZE_BYTES 256 + #endif +#endif + +/* These functions are used by the Unity Fixture to allocate and release memory + * on the heap and can be overridden with platform-specific implementations. + * For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc() + * and UNITY_FIXTURE_FREE becomes vPortFree(). */ +#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE) + #define UNITY_FIXTURE_MALLOC(size) malloc(size) + #define UNITY_FIXTURE_FREE(ptr) free(ptr) +#else + extern void* UNITY_FIXTURE_MALLOC(size_t size); + extern void UNITY_FIXTURE_FREE(void* ptr); +#endif + +#define malloc unity_malloc +#define calloc unity_calloc +#define realloc unity_realloc +#define free unity_free + +void* unity_malloc(size_t size); +void* unity_calloc(size_t num, size_t size); +void* unity_realloc(void * oldMem, size_t size); +void unity_free(void * mem); + +#endif /* UNITY_FIXTURE_MALLOC_OVERRIDES_H_ */ diff --git a/tests/unity/extras/fixture/test/Makefile b/tests/unity/extras/fixture/test/Makefile @@ -0,0 +1,74 @@ +CC = gcc +ifeq ($(shell uname -s), Darwin) +CC = clang +endif +#DEBUG = -O0 -g +CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror +CFLAGS += $(DEBUG) +DEFINES = -D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar +SRC = ../src/unity_fixture.c \ + ../../../src/unity.c \ + unity_fixture_Test.c \ + unity_fixture_TestRunner.c \ + unity_output_Spy.c \ + main/AllTests.c + +INC_DIR = -I../src -I../../../src/ +BUILD_DIR = ../build +TARGET = ../build/fixture_tests.exe + +all: default noStdlibMalloc 32bits + +default: $(BUILD_DIR) + $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_SUPPORT_64 + @ echo "default build" + ./$(TARGET) + +32bits: $(BUILD_DIR) + $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -m32 + @ echo "32bits build" + ./$(TARGET) + +noStdlibMalloc: $(BUILD_DIR) + $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC + @ echo "build with noStdlibMalloc" + ./$(TARGET) + +C89: CFLAGS += -D UNITY_EXCLUDE_STDINT_H # C89 did not have type 'long long', <stdint.h> +C89: $(BUILD_DIR) + $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -std=c89 && ./$(TARGET) + $(CC) $(CFLAGS) $(DEFINES) $(SRC) $(INC_DIR) -o $(TARGET) -D UNITY_EXCLUDE_STDLIB_MALLOC -std=c89 + ./$(TARGET) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +clean: + rm -f $(TARGET) $(BUILD_DIR)/*.gc* + +cov: $(BUILD_DIR) + cd $(BUILD_DIR) && \ + $(CC) $(DEFINES) $(foreach i, $(SRC), ../test/$(i)) $(INC_DIR) -o $(TARGET) -fprofile-arcs -ftest-coverage + rm -f $(BUILD_DIR)/*.gcda + ./$(TARGET) > /dev/null ; ./$(TARGET) -v > /dev/null + cd $(BUILD_DIR) && \ + gcov unity_fixture.c | head -3 + grep '###' $(BUILD_DIR)/unity_fixture.c.gcov -C2 || true # Show uncovered lines + +# These extended flags DO get included before any target build runs +CFLAGS += -Wbad-function-cast +CFLAGS += -Wcast-qual +CFLAGS += -Wconversion +CFLAGS += -Wformat=2 +CFLAGS += -Wmissing-prototypes +CFLAGS += -Wold-style-definition +CFLAGS += -Wpointer-arith +CFLAGS += -Wshadow +CFLAGS += -Wstrict-overflow=5 +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wswitch-default +CFLAGS += -Wundef +CFLAGS += -Wno-error=undef # Warning only, this should not stop the build +CFLAGS += -Wunreachable-code +CFLAGS += -Wunused +CFLAGS += -fstrict-aliasing diff --git a/tests/unity/extras/fixture/test/main/AllTests.c b/tests/unity/extras/fixture/test/main/AllTests.c @@ -0,0 +1,22 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#include "unity_fixture.h" + +static void runAllTests(void) +{ + RUN_TEST_GROUP(UnityFixture); + RUN_TEST_GROUP(UnityCommandOptions); + RUN_TEST_GROUP(LeakDetection); + RUN_TEST_GROUP(InternalMalloc); +} + +int main(int argc, const char* argv[]) +{ + return UnityMain(argc, argv, runAllTests); +} + diff --git a/tests/unity/extras/fixture/test/template_fixture_tests.c b/tests/unity/extras/fixture/test/template_fixture_tests.c @@ -0,0 +1,39 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#include "unity_fixture.h" + +static int data = -1; + +TEST_GROUP(mygroup); + +TEST_SETUP(mygroup) +{ + data = 0; +} + +TEST_TEAR_DOWN(mygroup) +{ + data = -1; +} + +TEST(mygroup, test1) +{ + TEST_ASSERT_EQUAL_INT(0, data); +} + +TEST(mygroup, test2) +{ + TEST_ASSERT_EQUAL_INT(0, data); + data = 5; +} + +TEST(mygroup, test3) +{ + data = 7; + TEST_ASSERT_EQUAL_INT(7, data); +} diff --git a/tests/unity/extras/fixture/test/unity_fixture_Test.c b/tests/unity/extras/fixture/test/unity_fixture_Test.c @@ -0,0 +1,543 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#include "unity_fixture.h" +#include "unity_output_Spy.h" +#include <stdlib.h> +#include <string.h> + +TEST_GROUP(UnityFixture); + +TEST_SETUP(UnityFixture) +{ +} + +TEST_TEAR_DOWN(UnityFixture) +{ +} + +static int* pointer1 = 0; +static int* pointer2 = (int*)2; +static int* pointer3 = (int*)3; +static int int1; +static int int2; +static int int3; +static int int4; + +TEST(UnityFixture, PointerSetting) +{ + TEST_ASSERT_POINTERS_EQUAL(pointer1, 0); + UT_PTR_SET(pointer1, &int1); + UT_PTR_SET(pointer2, &int2); + UT_PTR_SET(pointer3, &int3); + TEST_ASSERT_POINTERS_EQUAL(pointer1, &int1); + TEST_ASSERT_POINTERS_EQUAL(pointer2, &int2); + TEST_ASSERT_POINTERS_EQUAL(pointer3, &int3); + UT_PTR_SET(pointer1, &int4); + UnityPointer_UndoAllSets(); + TEST_ASSERT_POINTERS_EQUAL(pointer1, 0); + TEST_ASSERT_POINTERS_EQUAL(pointer2, (int*)2); + TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3); +} + +TEST(UnityFixture, ForceMallocFail) +{ + void* m; + void* mfails; + UnityMalloc_MakeMallocFailAfterCount(1); + m = malloc(10); + CHECK(m); + mfails = malloc(10); + TEST_ASSERT_POINTERS_EQUAL(0, mfails); + free(m); +} + +TEST(UnityFixture, ReallocSmallerIsUnchanged) +{ + void* m1 = malloc(10); + void* m2 = realloc(m1, 5); + TEST_ASSERT_POINTERS_EQUAL(m1, m2); + free(m2); +} + +TEST(UnityFixture, ReallocSameIsUnchanged) +{ + void* m1 = malloc(10); + void* m2 = realloc(m1, 10); + TEST_ASSERT_POINTERS_EQUAL(m1, m2); + free(m2); +} + +TEST(UnityFixture, ReallocLargerNeeded) +{ + void* m1 = malloc(10); + void* m2; + CHECK(m1); + strcpy((char*)m1, "123456789"); + m2 = realloc(m1, 15); + /* CHECK(m1 != m2); //Depends on implementation */ + STRCMP_EQUAL("123456789", m2); + free(m2); +} + +TEST(UnityFixture, ReallocNullPointerIsLikeMalloc) +{ + void* m = realloc(0, 15); + CHECK(m != 0); + free(m); +} + +TEST(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer) +{ + void* m1 = malloc(10); + void* m2 = realloc(m1, 0); + TEST_ASSERT_POINTERS_EQUAL(0, m2); +} + +TEST(UnityFixture, CallocFillsWithZero) +{ + void* m = calloc(3, sizeof(char)); + char* s = (char*)m; + CHECK(m); + TEST_ASSERT_BYTES_EQUAL(0, s[0]); + TEST_ASSERT_BYTES_EQUAL(0, s[1]); + TEST_ASSERT_BYTES_EQUAL(0, s[2]); + free(m); +} + +static char *p1; +static char *p2; + +TEST(UnityFixture, PointerSet) +{ + char c1; + char c2; + char newC1; + char newC2; + p1 = &c1; + p2 = &c2; + + UnityPointer_Init(); + UT_PTR_SET(p1, &newC1); + UT_PTR_SET(p2, &newC2); + TEST_ASSERT_POINTERS_EQUAL(&newC1, p1); + TEST_ASSERT_POINTERS_EQUAL(&newC2, p2); + UnityPointer_UndoAllSets(); + TEST_ASSERT_POINTERS_EQUAL(&c1, p1); + TEST_ASSERT_POINTERS_EQUAL(&c2, p2); +} + +TEST(UnityFixture, FreeNULLSafety) +{ + free(NULL); +} + +TEST(UnityFixture, ConcludeTestIncrementsFailCount) +{ + UNITY_UINT savedFails = Unity.TestFailures; + UNITY_UINT savedIgnores = Unity.TestIgnores; + UnityOutputCharSpy_Enable(1); + Unity.CurrentTestFailed = 1; + UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */ + Unity.CurrentTestIgnored = 1; + UnityConcludeFixtureTest(); /* Resets TestIgnored */ + UnityOutputCharSpy_Enable(0); + TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures); + TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores); + Unity.TestFailures = savedFails; + Unity.TestIgnores = savedIgnores; +} + +/*------------------------------------------------------------ */ + +TEST_GROUP(UnityCommandOptions); + +static int savedVerbose; +static unsigned int savedRepeat; +static const char* savedName; +static const char* savedGroup; + +TEST_SETUP(UnityCommandOptions) +{ + savedVerbose = UnityFixture.Verbose; + savedRepeat = UnityFixture.RepeatCount; + savedName = UnityFixture.NameFilter; + savedGroup = UnityFixture.GroupFilter; +} + +TEST_TEAR_DOWN(UnityCommandOptions) +{ + UnityFixture.Verbose = savedVerbose; + UnityFixture.RepeatCount= savedRepeat; + UnityFixture.NameFilter = savedName; + UnityFixture.GroupFilter = savedGroup; +} + + +static const char* noOptions[] = { + "testrunner.exe" +}; + +TEST(UnityCommandOptions, DefaultOptions) +{ + UnityGetCommandLineOptions(1, noOptions); + TEST_ASSERT_EQUAL(0, UnityFixture.Verbose); + TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.GroupFilter); + TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(1, UnityFixture.RepeatCount); +} + +static const char* verbose[] = { + "testrunner.exe", + "-v" +}; + +TEST(UnityCommandOptions, OptionVerbose) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, verbose)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); +} + +static const char* group[] = { + "testrunner.exe", + "-g", "groupname" +}; + +TEST(UnityCommandOptions, OptionSelectTestByGroup) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, group)); + STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); +} + +static const char* name[] = { + "testrunner.exe", + "-n", "testname" +}; + +TEST(UnityCommandOptions, OptionSelectTestByName) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, name)); + STRCMP_EQUAL("testname", UnityFixture.NameFilter); +} + +static const char* repeat[] = { + "testrunner.exe", + "-r", "99" +}; + +TEST(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, repeat)); + TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount); +} + +TEST(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, repeat)); + TEST_ASSERT_EQUAL(99, UnityFixture.RepeatCount); +} + +static const char* multiple[] = { + "testrunner.exe", + "-v", + "-g", "groupname", + "-n", "testname", + "-r", "98" +}; + +TEST(UnityCommandOptions, MultipleOptions) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(8, multiple)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); + STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); + STRCMP_EQUAL("testname", UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount); +} + +static const char* dashRNotLast[] = { + "testrunner.exe", + "-v", + "-g", "gggg", + "-r", + "-n", "tttt", +}; + +TEST(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(7, dashRNotLast)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); + STRCMP_EQUAL("gggg", UnityFixture.GroupFilter); + STRCMP_EQUAL("tttt", UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount); +} + +static const char* unknownCommand[] = { + "testrunner.exe", + "-v", + "-g", "groupname", + "-n", "testname", + "-r", "98", + "-z" +}; +TEST(UnityCommandOptions, UnknownCommandIsIgnored) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(9, unknownCommand)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); + STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); + STRCMP_EQUAL("testname", UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount); +} + +TEST(UnityCommandOptions, GroupOrNameFilterWithoutStringFails) +{ + TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(3, unknownCommand)); + TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(5, unknownCommand)); + TEST_ASSERT_EQUAL(1, UnityMain(3, unknownCommand, NULL)); +} + +TEST(UnityCommandOptions, GroupFilterReallyFilters) +{ + UNITY_UINT saved = Unity.NumberOfTests; + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(4, unknownCommand)); + UnityIgnoreTest(NULL, "non-matching", NULL); + TEST_ASSERT_EQUAL(saved, Unity.NumberOfTests); +} + +IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored) +{ + TEST_FAIL_MESSAGE("This test should not run!"); +} + +/*------------------------------------------------------------ */ + +TEST_GROUP(LeakDetection); + +TEST_SETUP(LeakDetection) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + UnityOutputCharSpy_Create(200); +#else + UnityOutputCharSpy_Create(1000); +#endif +} + +TEST_TEAR_DOWN(LeakDetection) +{ + UnityOutputCharSpy_Destroy(); +} + +#define EXPECT_ABORT_BEGIN \ + { \ + jmp_buf TestAbortFrame; \ + memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \ + if (TEST_PROTECT()) \ + { + +#define EXPECT_ABORT_END \ + } \ + memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \ + } + +/* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */ +#ifdef __STDC_VERSION__ + +#if __STDC_VERSION__ >= 199901L +#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0) +#define ASSIGN_VALUE(a) VAL_##a +#define VAL_UnityOutputCharSpy_OutputChar 0, 1 +#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway) +#define SECOND_PARAM(a, b, ...) b +#if USING_SPY_AS(UNITY_OUTPUT_CHAR) + #define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */ +#endif +#endif /* >= 199901 */ + +#else /* __STDC_VERSION__ else */ +#define UnityOutputCharSpy_OutputChar 42 +#if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */ + #define USING_OUTPUT_SPY +#endif +#undef UnityOutputCharSpy_OutputChar +#endif /* __STDC_VERSION__ */ + +TEST(LeakDetection, DetectsLeak) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE_MESSAGE("Build with '-D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar' to enable tests"); +#else + void* m = malloc(10); + TEST_ASSERT_NOT_NULL(m); + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + UnityMalloc_EndTest(); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + CHECK(strstr(UnityOutputCharSpy_Get(), "This test leaks!")); + free(m); +#endif +} + +TEST(LeakDetection, BufferOverrunFoundDuringFree) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[10] = (char)0xFF; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + free(m); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()")); +#endif +} + +TEST(LeakDetection, BufferOverrunFoundDuringRealloc) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[10] = (char)0xFF; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + m = realloc(m, 100); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()")); +#endif +} + +TEST(LeakDetection, BufferGuardWriteFoundDuringFree) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[-1] = (char)0x00; /* Will not detect 0 */ + s[-2] = (char)0x01; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + free(m); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()")); +#endif +} + +TEST(LeakDetection, BufferGuardWriteFoundDuringRealloc) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[-1] = (char)0x0A; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + m = realloc(m, 100); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()")); +#endif +} + +TEST(LeakDetection, PointerSettingMax) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + int i; + for (i = 0; i < UNITY_MAX_POINTERS; i++) UT_PTR_SET(pointer1, &int1); + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + UT_PTR_SET(pointer1, &int1); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + CHECK(strstr(UnityOutputCharSpy_Get(), "Too many pointers set")); +#endif +} + +/*------------------------------------------------------------ */ + +TEST_GROUP(InternalMalloc); +#define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \ + ptr = malloc(10); free(ptr); \ + TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order"); + + +TEST_SETUP(InternalMalloc) { } +TEST_TEAR_DOWN(InternalMalloc) { } + +TEST(InternalMalloc, MallocPastBufferFails) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2); + free(m); + TEST_ASSERT_NOT_NULL(m); + TEST_ASSERT_NULL(n); + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); +#endif +} + +TEST(InternalMalloc, CallocPastBufferFails) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2); + free(m); + TEST_ASSERT_NOT_NULL(m); + TEST_ASSERT_NULL(n); + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); +#endif +} + +TEST(InternalMalloc, MallocThenReallocGrowsMemoryInPlace) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9); + free(n); + TEST_ASSERT_NOT_NULL(m); + TEST_ASSERT_EQUAL(m, n); + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); +#endif +} + +TEST(InternalMalloc, ReallocFailDoesNotFreeMem) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2); + void* n1 = malloc(10); + void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n2 = malloc(10); + + free(n2); + if (out_of_mem == NULL) free(n1); + free(m); + + TEST_ASSERT_NOT_NULL(m); /* Got a real memory location */ + TEST_ASSERT_NULL(out_of_mem); /* The realloc should have failed */ + TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */ + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2); +#endif +} diff --git a/tests/unity/extras/fixture/test/unity_fixture_TestRunner.c b/tests/unity/extras/fixture/test/unity_fixture_TestRunner.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#include "unity_fixture.h" + +TEST_GROUP_RUNNER(UnityFixture) +{ + RUN_TEST_CASE(UnityFixture, PointerSetting); + RUN_TEST_CASE(UnityFixture, ForceMallocFail); + RUN_TEST_CASE(UnityFixture, ReallocSmallerIsUnchanged); + RUN_TEST_CASE(UnityFixture, ReallocSameIsUnchanged); + RUN_TEST_CASE(UnityFixture, ReallocLargerNeeded); + RUN_TEST_CASE(UnityFixture, ReallocNullPointerIsLikeMalloc); + RUN_TEST_CASE(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer); + RUN_TEST_CASE(UnityFixture, CallocFillsWithZero); + RUN_TEST_CASE(UnityFixture, PointerSet); + RUN_TEST_CASE(UnityFixture, FreeNULLSafety); + RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount); +} + +TEST_GROUP_RUNNER(UnityCommandOptions) +{ + RUN_TEST_CASE(UnityCommandOptions, DefaultOptions); + RUN_TEST_CASE(UnityCommandOptions, OptionVerbose); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByGroup); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByName); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount); + RUN_TEST_CASE(UnityCommandOptions, MultipleOptions); + RUN_TEST_CASE(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified); + RUN_TEST_CASE(UnityCommandOptions, UnknownCommandIsIgnored); + RUN_TEST_CASE(UnityCommandOptions, GroupOrNameFilterWithoutStringFails); + RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters); + RUN_TEST_CASE(UnityCommandOptions, TestShouldBeIgnored); +} + +TEST_GROUP_RUNNER(LeakDetection) +{ + RUN_TEST_CASE(LeakDetection, DetectsLeak); + RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringFree); + RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringRealloc); + RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringFree); + RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringRealloc); + RUN_TEST_CASE(LeakDetection, PointerSettingMax); +} + +TEST_GROUP_RUNNER(InternalMalloc) +{ + RUN_TEST_CASE(InternalMalloc, MallocPastBufferFails); + RUN_TEST_CASE(InternalMalloc, CallocPastBufferFails); + RUN_TEST_CASE(InternalMalloc, MallocThenReallocGrowsMemoryInPlace); + RUN_TEST_CASE(InternalMalloc, ReallocFailDoesNotFreeMem); +} diff --git a/tests/unity/extras/fixture/test/unity_output_Spy.c b/tests/unity/extras/fixture/test/unity_output_Spy.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + + +#include "unity_output_Spy.h" +#include "unity_fixture.h" + +#include <stdio.h> +#include <string.h> + +static int size; +static int count; +static char* buffer; +static int spy_enable; + +void UnityOutputCharSpy_Create(int s) +{ + size = (s > 0) ? s : 0; + count = 0; + spy_enable = 0; + buffer = malloc((size_t)size); + TEST_ASSERT_NOT_NULL_MESSAGE(buffer, "Internal malloc failed in Spy Create():" __FILE__); + memset(buffer, 0, (size_t)size); +} + +void UnityOutputCharSpy_Destroy(void) +{ + size = 0; + free(buffer); +} + +void UnityOutputCharSpy_OutputChar(int c) +{ + if (spy_enable) + { + if (count < (size-1)) + buffer[count++] = (char)c; + } + else + { + putchar(c); + } +} + +const char * UnityOutputCharSpy_Get(void) +{ + return buffer; +} + +void UnityOutputCharSpy_Enable(int enable) +{ + spy_enable = enable; +} diff --git a/tests/unity/extras/fixture/test/unity_output_Spy.h b/tests/unity/extras/fixture/test/unity_output_Spy.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2010 James Grenning and Contributed to Unity Project + * ========================================== + * 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] + * ========================================== */ + +#ifndef D_unity_output_Spy_H +#define D_unity_output_Spy_H + +void UnityOutputCharSpy_Create(int s); +void UnityOutputCharSpy_Destroy(void); +void UnityOutputCharSpy_OutputChar(int c); +const char * UnityOutputCharSpy_Get(void); +void UnityOutputCharSpy_Enable(int enable); + +#endif diff --git a/tests/unity/release/build.info b/tests/unity/release/build.info @@ -0,0 +1,2 @@ +120 + diff --git a/tests/unity/release/version.info b/tests/unity/release/version.info @@ -0,0 +1,2 @@ +2.4.0 + diff --git a/tests/unity/src/unity.c b/tests/unity/src/unity.c @@ -0,0 +1,1421 @@ +/* ========================================================================= + Unity Project - A Test Framework for C + Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +============================================================================ */ + +#include "unity.h" +#include <stddef.h> + +/* 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; TEST_ABORT(); } +#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; TEST_ABORT(); } +#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return + +struct UNITY_STORAGE_T Unity; + +static const char UnityStrOk[] = "OK"; +static const char UnityStrPass[] = "PASS"; +static const char UnityStrFail[] = "FAIL"; +static const char UnityStrIgnore[] = "IGNORE"; +static const char UnityStrNull[] = "NULL"; +static const char UnityStrSpacer[] = ". "; +static const char UnityStrExpected[] = " Expected "; +static const char UnityStrWas[] = " Was "; +static const char UnityStrElement[] = " Element "; +static const char UnityStrByte[] = " Byte "; +static const char UnityStrMemory[] = " Memory Mismatch."; +static const char UnityStrDelta[] = " Values Not Within Delta "; +static const char UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UnityStrNot[] = "Not "; +static const char UnityStrInf[] = "Infinity"; +static const char UnityStrNegInf[] = "Negative Infinity"; +static const char UnityStrNaN[] = "NaN"; +static const char UnityStrDet[] = "Determinate"; +static const char UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UnityStrBreaker[] = "-----------------------"; +static const char UnityStrResultsTests[] = " Tests "; +static const char UnityStrResultsFailures[] = " Failures "; +static const char UnityStrResultsIgnored[] = " Ignored "; +static const char UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; + +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*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); + } + pch++; + } + } +} + +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) + { + 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 = (UNITY_UINT)(-number_to_print); + } + 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 > (2 * sizeof(number))) + nibbles = 2 * sizeof(number); + + 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 +static void UnityPrintDecimalAndNumberWithLeadingZeros(UNITY_INT32 fraction_part, UNITY_INT32 divisor) +{ + UNITY_OUTPUT_CHAR('.'); + while (divisor > 0) + { + UNITY_OUTPUT_CHAR('0' + fraction_part / divisor); + fraction_part %= divisor; + divisor /= 10; + if (fraction_part == 0) break; /* Truncate trailing 0's */ + } +} +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO +/* If rounds up && remainder 0.5 && result odd && below cutoff for double precision issues */ + #define ROUND_TIES_TO_EVEN(orig, num_int, num) \ + if (num_int > (num) && (num) - (num_int-1) <= 0.5 && (num_int & 1) == 1 && orig < 1e22) \ + num_int -= 1 /* => a tie to round down to even */ +#else + #define ROUND_TIES_TO_EVEN(orig, num_int, num) /* Remove macro */ +#endif + +/* Printing floating point numbers is hard. Some goals of this implementation: works for embedded + * systems, floats or doubles, and has a reasonable format. The key paper in this area, + * 'How to Print Floating-Point Numbers Accurately' by Steele & White, shows an approximation by + * scaling called Dragon 2. This code uses a similar idea. The other core algorithm uses casts and + * floating subtraction to give exact remainders after the decimal, to be scaled into an integer. + * Extra trailing 0's are excluded. The output defaults to rounding to nearest, ties to even. You + * can enable rounding ties away from zero. Note: UNITY_DOUBLE param can typedef to float or double + + * The old version required compiling in snprintf. For reference, with a similar format as now: + * char buf[19]; + * if (number > 4294967296.0 || -number > 4294967296.0) snprintf(buf, sizeof buf, "%.8e", number); + * else snprintf(buf, sizeof buf, "%.6f", number); + * UnityPrint(buf); + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ + UNITY_DOUBLE number; + + if (input_number < 0) + { + UNITY_OUTPUT_CHAR('-'); + number = -input_number; + } else + { + number = input_number; + } + + if (isnan(number)) UnityPrint(UnityStrNaN); + else if (isinf(number)) UnityPrintLen(UnityStrInf, 3); + else if (number <= 0.0000005 && number > 0) UnityPrint("0.000000..."); /* Small number */ + else if (number < 4294967295.9999995) /* Rounded result fits in 32 bits, "%.6f" format */ + { + const UNITY_INT32 divisor = 1000000/10; + UNITY_UINT32 integer_part = (UNITY_UINT32)number; + UNITY_INT32 fraction_part = (UNITY_INT32)((number - (UNITY_DOUBLE)integer_part)*1000000.0 + 0.5); + /* Double precision calculation gives best performance for six rounded decimal places */ + ROUND_TIES_TO_EVEN(number, fraction_part, (number - (UNITY_DOUBLE)integer_part)*1000000.0); + + if (fraction_part == 1000000) /* Carry across the decimal point */ + { + fraction_part = 0; + integer_part += 1; + } + + UnityPrintNumberUnsigned(integer_part); + UnityPrintDecimalAndNumberWithLeadingZeros(fraction_part, divisor); + } + else /* Number is larger, use exponential format of 9 digits, "%.8e" */ + { + const UNITY_INT32 divisor = 1000000000/10; + UNITY_INT32 integer_part; + UNITY_DOUBLE_TYPE divide = 10.0; + int exponent = 9; + + while (number / divide >= 1000000000.0 - 0.5) + { + divide *= 10; + exponent++; + } + integer_part = (UNITY_INT32)(number / divide + 0.5); + /* Double precision calculation required for float, to produce 9 rounded digits */ + ROUND_TIES_TO_EVEN(number, integer_part, number / divide); + + UNITY_OUTPUT_CHAR('0' + integer_part / divisor); + UnityPrintDecimalAndNumberWithLeadingZeros(integer_part % divisor, divisor / 10); + UNITY_OUTPUT_CHAR('e'); + UNITY_OUTPUT_CHAR('+'); + if (exponent < 10) UNITY_OUTPUT_CHAR('0'); + UnityPrintNumber(exponent); + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +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_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) +{ + if (expected == actual) return 0; /* Both are NULL or same pointer */ + + /* 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; + } +} + +#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) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + + 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--) + { + 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; + break; + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + break; + default: /* length 4 bytes */ + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + length = 4; + 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; + break; +#endif + } + + if (expect_val != actual_val) + { + if (style & UNITY_DISPLAY_RANGE_UINT && length < sizeof(expect_val)) + { /* 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; + } + expected = (UNITY_INTERNAL_PTR)(length + (const char*)expected); + actual = (UNITY_INTERNAL_PTR)(length + (const char*)actual); + } +} + +/*-----------------------------------------------*/ +#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) +{ + 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(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + 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(expected, 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(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) +{ + 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; + } + 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 - expected) > delta); + else + Unity.CurrentTestFailed = ((UNITY_UINT)(expected - actual) > delta); + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + Unity.CurrentTestFailed = ((UNITY_UINT)(actual - expected) > delta); + else + Unity.CurrentTestFailed = ((UNITY_UINT)(expected - 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 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(const char** expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i, j = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_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; + + do + { + /* if both pointers not null compare the strings */ + if (expected[j] && actual[j]) + { + for (i = 0; expected[j][i] || actual[j][i]; i++) + { + if (expected[j][i] != actual[j][i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected[j] != actual[j]) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings((const char*)(expected[j]), (const char*)(actual[j])); + 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) +{ + 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++; + } + } +} + +/*----------------------------------------------- + * 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; +} + +/*-----------------------------------------------*/ +#if defined(UNITY_WEAK_ATTRIBUTE) + UNITY_WEAK_ATTRIBUTE void setUp(void) { } + UNITY_WEAK_ATTRIBUTE void tearDown(void) { } +#elif defined(UNITY_WEAK_PRAGMA) + #pragma weak setUp + void setUp(void) { } + #pragma weak tearDown + void tearDown(void) { } +#endif +/*-----------------------------------------------*/ +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UnityConcludeTest(); +} + +/*-----------------------------------------------*/ +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) +{ + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + + for (int 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) +{ + char* lptr = (char*)longstring; + char* sptr = (char*)shortstring; + 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 = (char*)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/tests/unity/src/unity.h b/tests/unity/src/unity.h @@ -0,0 +1,291 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-14 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 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +void setUp(void); +void tearDown(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_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() + +/*------------------------------------------------------- + * 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(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") +#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_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_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 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_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) + +/* 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_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) + +/* 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_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_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) + +/*------------------------------------------------------- + * 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_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)) +#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_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)) + +/* 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_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)) + +/* 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_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)) + +/* 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_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_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)) + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/tests/unity/src/unity_internals.h b/tests/unity/src/unity_internals.h @@ -0,0 +1,732 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-14 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 + +#include "../examples/unity_config.h" + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include <setjmp.h> +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include <math.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. + * 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 + *-------------------------------------------------------*/ + +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_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; + +#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 */ + #ifndef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +extern void UNITY_OUTPUT_CHAR(int); + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +/* Default to using fflush, which is defined in stdio.h */ +#include <stdio.h> +#define UNITY_OUTPUT_FLUSH (void)fflush(stdout) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifndef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION +extern void UNITY_OUTPUT_FLUSH(void); + #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 + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Language Features Available + *-------------------------------------------------------*/ +#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) +# ifdef __GNUC__ /* includes clang */ +# if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__) +# define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) +# endif +# endif +#endif + +#ifdef UNITY_NO_WEAK +# undef UNITY_WEAK_ATTRIBUTE +# undef UNITY_WEAK_PRAGMA +#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) + +typedef enum +{ +UNITY_DISPLAY_STYLE_INT = sizeof(int)+ 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 = sizeof(unsigned) + 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_UNKNOWN +} UNITY_DISPLAY_STYLE_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 + +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; +#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 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); +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); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles); + +#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 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); + +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( const char** expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +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); + +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 UnityFail(const char* message, const UNITY_LINE_TYPE line); + +void UnityIgnore(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); + +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); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; + +/*------------------------------------------------------- + * 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 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 +#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 + +/*----------------------------------------------- + * 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_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_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_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)) + +#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) +#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) +#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) +#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) +#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) +#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) +#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) +#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) +#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) +#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) +#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) +#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) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((const char**)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) +#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)) + +#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) +#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) +#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) +#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) +#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) +#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_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)) +#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_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) +#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 diff --git a/tests/unity/test/Makefile b/tests/unity/test/Makefile @@ -0,0 +1,63 @@ +CC = gcc +ifeq ($(shell uname -s), Darwin) +CC = clang +endif +ifeq ($(findstring clang, $(CC)), clang) +E = -Weverything +CFLAGS += $E -Wno-unknown-warning-option -Wno-missing-prototypes +CFLAGS += -Wno-unused-macros -Wno-padded -Wno-missing-noreturn +endif +CFLAGS += -std=c99 -pedantic -Wall -Wextra -Wconversion -Werror +CFLAGS += -Wno-switch-enum -Wno-double-promotion +CFLAGS += -Wbad-function-cast -Wcast-qual -Wold-style-definition -Wshadow -Wstrict-overflow \ + -Wstrict-prototypes -Wswitch-default -Wundef +#DEBUG = -O0 -g +CFLAGS += $(DEBUG) +DEFINES = -D UNITY_OUTPUT_CHAR=putcharSpy +DEFINES += -D UNITY_SUPPORT_64 -D UNITY_INCLUDE_DOUBLE +SRC = ../src/unity.c tests/testunity.c build/testunityRunner.c +INC_DIR = -I ../src +COV_FLAGS = -fprofile-arcs -ftest-coverage -I ../../src +BUILD_DIR = build +TARGET = build/testunity-cov.exe + +# To generate coverage, call 'make -s', the default target runs. +# For verbose output of all the tests, run 'make test'. +default: coverage +.PHONY: default coverage test clean +coverage: DEFINES += -D UNITY_NO_WEAK +coverage: $(BUILD_DIR)/testunityRunner.c + cd $(BUILD_DIR) && \ + $(CC) $(CFLAGS) $(DEFINES) $(foreach i,$(SRC), ../$i) $(COV_FLAGS) -o ../$(TARGET) + rm -f $(BUILD_DIR)/*.gcda + ./$(TARGET) | grep 'Tests\|]]]' -A1 + cd $(BUILD_DIR) && \ + gcov unity.c | head -3 + grep '###' $(BUILD_DIR)/unity.c.gcov -C2 || true + +test: $(BUILD_DIR)/testunityRunner.c + $(CC) $(CFLAGS) $(DEFINES) $(INC_DIR) $(SRC) -o $(TARGET) + ./$(TARGET) + +# Compile only, for testing that preprocessor detection works +UNITY_C_ONLY =-c ../src/unity.c -o $(BUILD_DIR)/unity.o +intDetection: + $(CC) $(CFLAGS) $(INC_DIR) $(UNITY_C_ONLY) -D UNITY_EXCLUDE_STDINT_H + $(CC) $(CFLAGS) $(INC_DIR) $(UNITY_C_ONLY) -D UNITY_EXCLUDE_LIMITS_H + +$(BUILD_DIR)/testunityRunner.c: tests/testunity.c | $(BUILD_DIR) + awk $(AWK_SCRIPT) tests/testunity.c > $@ + +AWK_SCRIPT=\ + '/^void test/{ declarations[d++]=$$0; gsub(/\(?void\)? ?/,""); tests[t++]=$$0; line[u++]=NR } \ + END{ print "\#include \"unity.h\" /* Autogenerated by awk in Makefile */" ; \ + for (i=0; i<d; i++) { print declarations[i] ";" } \ + print "int main(void)\n{\n UnityBegin(\"" FILENAME "\");" ; \ + for (i=0; i<t; i++) { print " RUN_TEST(" tests[i] ", " line[i] ");" } \ + print " return UNITY_END();\n}" }' + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +clean: + rm -f $(TARGET) $(BUILD_DIR)/*.gc* $(BUILD_DIR)/testunityRunner.c diff --git a/tests/unity/test/expectdata/testsample_cmd.c b/tests/unity/test/expectdata/testsample_cmd.c @@ -0,0 +1,61 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_def.c b/tests/unity/test/expectdata/testsample_def.c @@ -0,0 +1,57 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_head1.c b/tests/unity/test/expectdata/testsample_head1.c @@ -0,0 +1,55 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "testsample_head1.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_head1.h b/tests/unity/test/expectdata/testsample_head1.h @@ -0,0 +1,15 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#ifndef _TESTSAMPLE_HEAD1_H +#define _TESTSAMPLE_HEAD1_H + +#include "unity.h" +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +void test_TheFirstThingToTest(void); +void test_TheSecondThingToTest(void); +void test_TheThirdThingToTest(void); +void test_TheFourthThingToTest(void); +#endif + diff --git a/tests/unity/test/expectdata/testsample_mock_cmd.c b/tests/unity/test/expectdata/testsample_mock_cmd.c @@ -0,0 +1,80 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_def.c b/tests/unity/test/expectdata/testsample_mock_def.c @@ -0,0 +1,76 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_head1.c b/tests/unity/test/expectdata/testsample_mock_head1.c @@ -0,0 +1,75 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "testsample_mock_head1.h" +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_head1.h b/tests/unity/test/expectdata/testsample_mock_head1.h @@ -0,0 +1,13 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#ifndef _TESTSAMPLE_MOCK_HEAD1_H +#define _TESTSAMPLE_MOCK_HEAD1_H + +#include "unity.h" +#include "cmock.h" +#include "funky.h" +#include <setjmp.h> + +void test_TheFirstThingToTest(void); +void test_TheSecondThingToTest(void); +#endif + diff --git a/tests/unity/test/expectdata/testsample_mock_new1.c b/tests/unity/test/expectdata/testsample_mock_new1.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + GlobalExpectCount = 0; + GlobalVerifyOrder = 0; + GlobalOrderError = NULL; + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_new2.c b/tests/unity/test/expectdata/testsample_mock_new2.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return suite_teardown(UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_param.c b/tests/unity/test/expectdata/testsample_mock_param.c @@ -0,0 +1,77 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST_NO_ARGS +#define RUN_TEST(TestFunc, TestLineNum, ...) \ +{ \ + Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(__VA_ARGS__); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_run1.c b/tests/unity/test/expectdata/testsample_mock_run1.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + GlobalExpectCount = 0; + GlobalVerifyOrder = 0; + GlobalOrderError = NULL; + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_run2.c b/tests/unity/test/expectdata/testsample_mock_run2.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return suite_teardown(UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_mock_yaml.c b/tests/unity/test/expectdata/testsample_mock_yaml.c @@ -0,0 +1,90 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "two.h" +#include "three.h" +#include <four.h> +#include "funky.h" +#include <setjmp.h> +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_yaml_setup(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_new1.c b/tests/unity/test/expectdata/testsample_new1.c @@ -0,0 +1,67 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_new2.c b/tests/unity/test/expectdata/testsample_new2.c @@ -0,0 +1,70 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return suite_teardown(UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_param.c b/tests/unity/test/expectdata/testsample_param.c @@ -0,0 +1,58 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST_NO_ARGS +#define RUN_TEST(TestFunc, TestLineNum, ...) \ +{ \ + Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(__VA_ARGS__); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheThirdThingToTest, 53, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheFourthThingToTest, 58, RUN_TEST_NO_ARGS); + + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_run1.c b/tests/unity/test/expectdata/testsample_run1.c @@ -0,0 +1,67 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_run2.c b/tests/unity/test/expectdata/testsample_run2.c @@ -0,0 +1,70 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return suite_teardown(UnityEnd()); +} diff --git a/tests/unity/test/expectdata/testsample_yaml.c b/tests/unity/test/expectdata/testsample_yaml.c @@ -0,0 +1,71 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include <setjmp.h> +#include <stdio.h> +#include "CException.h" +#include "two.h" +#include "three.h" +#include <four.h> +#include "funky.h" +#include "stanky.h" +#include <setjmp.h> + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_yaml_setup(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/tests/unity/test/rakefile b/tests/unity/test/rakefile @@ -0,0 +1,72 @@ +# ========================================== +# 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] +# ========================================== + +UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/' +$verbose = false + +require 'rake' +require 'rake/clean' +require UNITY_ROOT + 'rakefile_helper' +require 'rspec/core/rake_task' + +TEMP_DIRS = [ + File.join(UNITY_ROOT, 'build'), + File.join(UNITY_ROOT, 'sandbox') +] + +TEMP_DIRS.each do |dir| + directory(dir) + CLOBBER.include(dir) +end + +task :prepare_for_tests => TEMP_DIRS + +include RakefileHelpers + +# Load proper GCC as defult configuration +DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml' +configure_toolchain(DEFAULT_CONFIG_FILE) + +desc "Test unity with its own unit tests" +task :unit => [:prepare_for_tests] do + run_tests get_unit_test_files +end + +desc "Test unity's helper scripts" +task :scripts => [:prepare_for_tests] do + Dir['tests/test_*.rb'].each do |scriptfile| + require "./"+scriptfile + end +end + +desc "Run all rspecs" +RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = 'spec/**/*_spec.rb' +end + +desc "Generate test summary" +task :summary do + report_summary +end + +desc "Build and test Unity" +task :all => [:clean, :prepare_for_tests, :scripts, :unit, :summary] +task :default => [:clobber, :all] +task :ci => [:no_color, :default] +task :cruise => [:no_color, :default] + +desc "Load configuration" +task :config, :config_file do |t, args| + configure_toolchain(args[:config_file]) +end + +task :no_color do + $colour_output = false +end + +task :verbose do + $verbose = true +end diff --git a/tests/unity/test/rakefile_helper.rb b/tests/unity/test/rakefile_helper.rb @@ -0,0 +1,257 @@ +# ========================================== +# 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' +require 'fileutils' +require UNITY_ROOT + '../auto/unity_test_summary' +require UNITY_ROOT + '../auto/generate_test_runner' +require UNITY_ROOT + '../auto/colour_reporter' + +module RakefileHelpers + + C_EXTENSION = '.c' + + def load_configuration(config_file) + unless ($configured) + $cfg_file = "targets/#{config_file}" unless (config_file =~ /[\\|\/]/) + $cfg = YAML.load(File.read($cfg_file)) + $colour_output = false unless $cfg['colour'] + $configured = true if (config_file != DEFAULT_CONFIG_FILE) + end + end + + def configure_clean + CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? + end + + def configure_toolchain(config_file=DEFAULT_CONFIG_FILE) + config_file += '.yml' unless config_file =~ /\.yml$/ + config_file = config_file unless config_file =~ /[\\|\/]/ + load_configuration(config_file) + configure_clean + end + + def get_unit_test_files + path = $cfg['compiler']['unit_tests_path'] + 'test*' + C_EXTENSION + path.gsub!(/\\/, '/') + FileList.new(path) + end + + def get_local_include_dirs + include_dirs = $cfg['compiler']['includes']['items'].dup + include_dirs.delete_if {|dir| dir.is_a?(Array)} + return include_dirs + end + + def extract_headers(filename) + includes = [] + lines = File.readlines(filename) + lines.each do |line| + m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) + if not m.nil? + includes << m[1] + end + end + return includes + end + + def find_source_file(header, paths) + paths.each do |dir| + src_file = dir + header.ext(C_EXTENSION) + if (File.exists?(src_file)) + return src_file + end + end + return nil + end + + def tackit(strings) + if strings.is_a?(Array) + result = "\"#{strings.join}\"" + else + result = strings + end + return result + end + + def squash(prefix, items) + result = '' + items.each { |item| result += " #{prefix}#{tackit(item)}" } + return result + end + + def should(behave, &block) + if block + puts "Should " + behave + yield block + else + puts "UNIMPLEMENTED CASE: Should #{behave}" + end + end + + def build_compiler_fields(inject_defines) + command = tackit($cfg['compiler']['path']) + if $cfg['compiler']['defines']['items'].nil? + defines = '' + else + defines = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + inject_defines) + end + options = squash('', $cfg['compiler']['options']) + includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) + includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + return {:command => command, :defines => defines, :options => options, :includes => includes} + end + + def compile(file, defines=[]) + compiler = build_compiler_fields(defines) + defines = + cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " + + "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" + obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" + execute(cmd_str + obj_file) + return obj_file + end + + def build_linker_fields + command = tackit($cfg['linker']['path']) + if $cfg['linker']['options'].nil? + options = '' + else + options = squash('', $cfg['linker']['options']) + end + if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?) + includes = '' + else + includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) + end + includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + return {:command => command, :options => options, :includes => includes} + end + + def link_it(exe_name, obj_list) + linker = build_linker_fields + cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + + (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join + + $cfg['linker']['bin_files']['prefix'] + ' ' + + $cfg['linker']['bin_files']['destination'] + + exe_name + $cfg['linker']['bin_files']['extension'] + execute(cmd_str) + end + + def build_simulator_fields + return nil if $cfg['simulator'].nil? + if $cfg['simulator']['path'].nil? + command = '' + else + command = (tackit($cfg['simulator']['path']) + ' ') + end + if $cfg['simulator']['pre_support'].nil? + pre_support = '' + else + pre_support = squash('', $cfg['simulator']['pre_support']) + end + if $cfg['simulator']['post_support'].nil? + post_support = '' + else + post_support = squash('', $cfg['simulator']['post_support']) + end + return {:command => command, :pre_support => pre_support, :post_support => post_support} + end + + def execute(command_string, ok_to_fail=false) + report command_string if $verbose + output = `#{command_string}`.chomp + report(output) if ($verbose && !output.nil? && (output.length > 0)) + if (($?.exitstatus != 0) && !ok_to_fail) + raise "Command failed. (Returned #{$?.exitstatus})" + end + return output + end + + def report_summary + summary = UnityTestSummary.new + summary.set_root_path(UNITY_ROOT) + results_glob = "#{$cfg['compiler']['build_path']}*.test*" + results_glob.gsub!(/\\/, '/') + results = Dir[results_glob] + summary.set_targets(results) + report summary.run + end + + def run_tests(test_files) + report 'Running Unity system tests...' + + # Tack on TEST define for compiling unit tests + load_configuration($cfg_file) + test_defines = ['TEST'] + $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? + $cfg['compiler']['defines']['items'] << 'TEST' + + include_dirs = get_local_include_dirs + + # Build and execute each unit test + test_files.each do |test| + obj_list = [] + + if !$cfg['compiler']['aux_sources'].nil? + $cfg['compiler']['aux_sources'].each do |aux| + obj_list << compile(aux, test_defines) + end + end + + # Detect dependencies and build required modules + extract_headers(test).each do |header| + # Compile corresponding source file if it exists + src_file = find_source_file(header, include_dirs) + if !src_file.nil? + obj_list << compile(src_file, test_defines) + end + end + + # Build the test runner (generate if configured to do so) + test_base = File.basename(test, C_EXTENSION) + + runner_name = test_base + '_Runner.c' + runner_path = '' + + if $cfg['compiler']['runner_path'].nil? + runner_path = $cfg['compiler']['build_path'] + runner_name + else + runner_path = $cfg['compiler']['runner_path'] + runner_name + end + + options = $cfg[:unity] + options[:use_param_tests] = (test =~ /parameterized/) ? true : false + UnityTestRunnerGenerator.new(options).run(test, runner_path) + obj_list << compile(runner_path, test_defines) + + # Build the test module + obj_list << compile(test, test_defines) + + # Link the test executable + link_it(test_base, obj_list) + + # Execute unit test and generate results file + simulator = build_simulator_fields + executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + if simulator.nil? + cmd_str = executable + else + cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" + end + output = execute(cmd_str) + test_results = $cfg['compiler']['build_path'] + test_base + if output.match(/OK$/m).nil? + test_results += '.testfail' + else + report output if (!$verbose) #verbose already prints this line, as does a failure + test_results += '.testpass' + end + File.open(test_results, 'w') { |f| f.print output } + + end + end +end diff --git a/tests/unity/test/spec/generate_module_existing_file_spec.rb b/tests/unity/test/spec/generate_module_existing_file_spec.rb @@ -0,0 +1,158 @@ + +require '../auto/generate_module.rb' +require 'fileutils' + +def touch_src(file) + FileUtils.touch "sandbox/src/#{file}" +end + +def touch_test(file) + FileUtils.touch "sandbox/test/#{file}" +end + +def create_src_with_known_content(file) + File.open("sandbox/src/#{file}", "w") {|f| f.write("the original #{file}")} +end + +def create_test_with_known_content(file) + File.open("sandbox/test/#{file}", "w") {|f| f.write("the original #{file}")} +end + +def expect_src_content_didnt_change(file) + expect(File.read("sandbox/src/#{file}")).to eq("the original #{file}") +end + +def expect_test_content_didnt_change(file) + expect(File.read("sandbox/test/#{file}")).to eq("the original #{file}") +end + +def expect_src_file_to_exist(file) + expect(File.exist?("sandbox/src/#{file}")).to be true +end + +def expect_test_file_to_exist(file) + expect(File.exist?("sandbox/test/#{file}")).to be true +end + +describe "UnityModuleGenerator" do + + before do + # clean sandbox and setup our "project" folders + FileUtils.rm_rf "sandbox" + FileUtils.mkdir_p "sandbox" + FileUtils.mkdir_p "sandbox/src" + FileUtils.mkdir_p "sandbox/test" + + @options = { + :path_src => "sandbox/src", + :path_tst => "sandbox/test", + } + end + + context "with src pattern" do + before do + @options[:pattern] = "src" + end + + it "fails when all files already exist" do + # create an existing triad of files + touch_src "meh.c" + touch_src "meh.h" + touch_test "Testmeh.c" + expect { + UnityModuleGenerator.new(@options).generate("meh") + }.to raise_error("ERROR: File meh already exists. Exiting.") + end +