Compare commits

..

91 Commits

Author SHA1 Message Date
Max Bruckner
cbc05de76f Release version 1.7.6 2018-04-13 12:32:30 +08:00
Max Bruckner
7996a4a2ee Readme: Deprecate the Makefile 2018-04-13 12:12:26 +08:00
Max Bruckner
ed8fefc9ca Makefile: Fix #252, put soname in the ELF file 2018-04-13 12:03:33 +08:00
Max Bruckner
e6869c2e03 cJSON_Utils.h: Add include guards and extern C for C++ 2018-04-13 10:32:29 +08:00
Max Bruckner
0e0c463491 Release version 1.7.5 2018-03-22 20:29:17 +01:00
Max Bruckner
2336a0348d Contributors: Add Bob Kocisko 2018-03-22 20:28:54 +01:00
Max Bruckner
5d50f4efe1 Contributors: Thank all the non-code contributors 2018-03-22 20:28:30 +01:00
Max Bruckner
8abf110750 Merge pull request #251 from bobkocisko/master
json patch: adding to a subfield of a non-object now fails as expected
2018-03-22 20:00:24 +01:00
Bob Kocisko
d26a42af8d json patch: adding to a subfield of a non-object now fails as expected 2018-03-22 11:10:29 -04:00
Max Bruckner
6f264b5d0c Merge pull request #249 from DaveGamble/fix-add-item
Release 1.7.4
2018-03-02 20:04:29 +01:00
Max Bruckner
5da9edc8b1 Release version 1.7.4 2018-03-02 19:57:36 +01:00
Max Bruckner
22a7d04fa0 add_item_to_object: Fix use-after-free when string is aliased
If the `string` property of the item that is added is an alias to the
`string` parameter of `add_item_to_object`, and `constant` is false,
`cJSON_strdup` would access the string after it has been freed.

Thanks @hhallen for reporting this in #248.
2018-03-02 19:49:55 +01:00
Max Bruckner
a559eac472 Release version 1.7.3 2018-02-07 21:16:35 +01:00
Max Bruckner
d514bb866e Fix #241, potential double free 2018-02-07 19:36:59 +01:00
Max Bruckner
27caa364b0 Release version 1.7.2 2018-02-06 11:38:41 +01:00
Max Bruckner
f47271f455 Fix pkgconfig and installation. Thanks @zeerd for reporting
CMAKE_INSTALL_FULL_... needs to be used.
2018-02-06 11:24:03 +01:00
Max Bruckner
7cc52f6035 Merge pull request #231 from DaveGamble/fixes
Release Version 1.7.1
2018-01-09 22:34:48 +01:00
Max Bruckner
b60b5d3744 Update version to 1.7.1 2018-01-09 21:59:42 +01:00
Max Bruckner
4d84acf926 print_number: fix Off-By-One error
Thanks @liuyunbin for reporting this in #230
2018-01-09 21:40:55 +01:00
Max Bruckner
28d4410f42 print: fix: realloc was allocating too much memory
Thanks @liuyunbin for reporting this in #230
2018-01-09 20:53:33 +01:00
Max Bruckner
f33fa95f3d print: Fix default buffer size in printbuffer
Thanks @liuyunbin for reporting this in #230
2018-01-09 20:49:03 +01:00
Max Bruckner
984dc85a5f Merge pull request #228 from DaveGamble/develop
Release Version 1.7.0
2017-12-31 02:20:27 +01:00
Max Bruckner
13a2d337a8 Update version number to 1.7 2017-12-31 02:03:40 +01:00
Max Bruckner
17b83e76e9 Update Changelog for version 1.7 2017-12-31 02:01:53 +01:00
Max Bruckner
43754e7833 Merge pull request #215 from DaveGamble/new-documentation
New documentation
2017-12-31 01:43:11 +01:00
Max Bruckner
1e95363638 README: Caveats: Duplicate object members 2017-12-31 01:40:57 +01:00
Max Bruckner
d7e711c0de README: new doc: Add links for 4th level sections 2017-12-31 01:35:09 +01:00
Max Bruckner
f26d8f3175 README: Add small note about CMake on Windows. 2017-12-31 01:35:09 +01:00
Max Bruckner
e7d0c1dc37 Tests: Test if the readme examples are working 2017-12-31 01:35:09 +01:00
Max Bruckner
5605fa4ad5 README: new doc: Remove old explanation. 2017-12-31 01:35:08 +01:00
Max Bruckner
cdcd553769 README: new doc: Example 2017-12-31 01:35:08 +01:00
Max Bruckner
61dd7f1e41 README: new doc: Working with the data structure 2017-12-31 01:35:08 +01:00
Max Bruckner
1285e6ac68 README: new doc: Printing 2017-12-31 01:35:07 +01:00
Max Bruckner
b54b81251e README: new doc: Parsing 2017-12-31 01:35:05 +01:00
Max Bruckner
c31ee79ad1 README: new doc: Data Structure section 2017-12-31 01:26:41 +01:00
Max Bruckner
a1a1e60cb0 Merge pull request #226 from DaveGamble/boolean_add
Convert cJSON_Add..ToObject macros into functions with return values
2017-12-29 23:30:20 +01:00
Max Bruckner
1b21bcd150 cJSON_Add..ToObject: Add comment to header file 2017-12-29 23:29:09 +01:00
Max Bruckner
77931e7fc0 cJSON_Add...ToObject: Add tests for failure conditions 2017-12-29 23:26:53 +01:00
Max Bruckner
5865faffa3 Convert cJSON_Add...ToObject macros into functions
These functions return the added object. Functions to add objects and
arrays have also been added.
2017-12-28 23:56:39 +01:00
Max Bruckner
f966409b33 Add tests for cJSON_Add...ToObject macros 2017-12-28 22:56:57 +01:00
Max Bruckner
de729a1635 Extract add_item_to_object function that returns a boolean 2017-12-28 21:40:24 +01:00
Max Bruckner
55c597c719 add_item_to_array with boolean return value 2017-12-28 12:45:28 +01:00
Max Bruckner
2a087843e4 Add overrides for BUILD_SHARED_LIBS 2017-11-28 17:16:11 +01:00
Max Bruckner
eb7c681a4b Fix tests when building as static library 2017-11-28 16:44:24 +01:00
Max Bruckner
0476590a0c Update Unity to 2.4.3 2017-11-28 03:15:50 +01:00
Max Bruckner
da8c48668d Squashed 'tests/unity/' changes from 60b13f0..287e076
287e076 Post release
774da10 Merge pull request #296 from jlindgren90/master
629b86d Merge unity_setup.h into unity.h.
0914d80 Merge pull request #308 from codehearts/patch-1
5ee55fe Fix missing TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE
38c387b Merge pull request #304 from VLambret/master
17d4ea9 Color test results using ANSI escape codes
031b1ba Merge pull request #300 from jsalling/bugfix/greater-than
df78aad Make weak symbol usage more portable:
a7e8797 Fix link errors with MinGW.
94a3008 Update continuous integration to build 32-bit Unity
b119919 Add 64-bit comparison asserts
91bcbe1 Add 'greater/less or equal to' asserts on integers
8caade7 Fix bug in greater/less than asserts on unsigned int
1381a1a Update documentation.
2593c31 Allow suiteSetUp() and suiteTearDown() to be provided as normal C functions.
60def10 Update configuration docs

git-subtree-dir: tests/unity
git-subtree-split: 287e076962ec711cd2bdf08364a8df9ce51e106b
2017-11-28 03:15:50 +01:00
Max Bruckner
11844dd5a6 Add cJSON_Create{Array,Object}Reference 2017-11-28 03:06:02 +01:00
Max Bruckner
1f543f0e28 cast_away_const: Generalize for void* 2017-11-28 02:05:02 +01:00
Max Bruckner
eaa90a6b74 Add cJSON_CreateStringReference 2017-11-28 02:02:55 +01:00
Max Bruckner
440390a9a5 extract function cast_away_const_from_string 2017-11-28 01:54:21 +01:00
Max Bruckner
043507872e Update json-patch-tests 2017-11-20 22:04:57 +01:00
Max Bruckner
2718d30a3d Squashed 'tests/json-patch-tests/' changes from 0dd0fbc..99264bb
99264bb Merge pull request #37 from FormAPI/missing_parent_key
c2fae3a Added a test case to check replace op with a missing parent key

git-subtree-dir: tests/json-patch-tests
git-subtree-split: 99264bb634d32c03df7472f21afb7d3681d8619e
2017-11-20 22:04:57 +01:00
Max Bruckner
b2afbd3c9f cJSON_GetStringValue 2017-11-15 18:47:49 +01:00
Max Bruckner
27a4303f87 Contributors: Add yangfl 2017-11-04 14:26:50 +01:00
Max Bruckner
b5f2e5c540 Merge pull request #212 from yangfl/temp2
Remove trailing space
2017-11-04 14:24:47 +01:00
yangfl
fa00278f66 Remove trailing space 2017-11-04 21:19:15 +08:00
Max Bruckner
8412b1e2cd README: fixup last commit 2017-11-04 13:42:20 +01:00
Max Bruckner
35907223e1 README: Explain including cJSON, fix #211 2017-11-04 13:39:58 +01:00
Max Bruckner
8a11f8ce17 Merge pull request #210 from yangfl/upstream
CMakeLists.txt: swap GNUInstallDirs and project
2017-11-04 13:30:59 +01:00
yangfl
df1c49dba1 CMakeLists.txt: swap GNUInstallDirs and project 2017-11-04 20:14:56 +08:00
Max Bruckner
c083421f40 Release version 1.6.0 2017-10-08 23:36:41 +02:00
Max Bruckner
96c33e5abb ENABLE_LOCALES: Actually disable the include as well 2017-10-08 23:28:49 +02:00
Max Bruckner
f437767fa9 Contributors: Add Simon Ricaldone and Casperinous 2017-10-08 23:13:30 +02:00
Max Bruckner
c51a19be51 CONTRIBUTING.md: Fix '4 tabs' -> '4 spaces' 2017-10-08 22:05:19 +02:00
Max Bruckner
97d7347a6e Merge branch 'develop' 2017-10-08 22:05:02 +02:00
Max Bruckner
28328a0b34 Merge pull request #203 from Casperinous/master
Fix for #202 issue.
2017-10-08 21:48:46 +02:00
casperinous
9b960fa870 Small indentation fix in order to follow the contribution rules. 2017-10-08 22:02:52 +03:00
casperinous
4f9e9dfc30 Fix for issue #202, regarding the lack of implementation of the localeconv method in some SDK's.
A macro named `ENABLE_LOCALES` was added and an option with the same name too in the CMakeLists.txt
2017-10-08 21:55:58 +03:00
Max Bruckner
b7bfe1e91a Squashed 'tests/unity/' changes from 3b69bea..60b13f0
60b13f0 Bump version in preparation of release.
f278c18 Fix bug #288 - invalid line numbers on partial name matches
bdd4cb1 Merge pull request #294 from jlindgren90/master
fcd4883 Fix compiler warning due to reusing symbol 'exp'.
05daf95 Update to match Ruby style guide
7b2ad10 Merge pull request #285 from dpostorivo/gt_lt_asserts
0547aab Merge pull request #291 from jlindgren90/master
2ae2bdb Make code C89-compliant.
dbdd168 Fix test link error.
0e7eb54 Rewrite UnityPrintFloat to match printf("%.6g").
a868b2e Merge pull request #286 from palaviv/fix-UNITY_OUTPUT_FLUSH
e56378e Add UNITY_OUTPUT_CHAR_HEADER_DECLARATION to fixture tests rakefile_helper.rb
ad37302 Add UNITY_OUTPUT_CHAR_HEADER_DECLARATION to tests rakefile_helper.rb
b3de931 Add UNITY_OUTPUT_CHAR_HEADER_DECLARATION to fixture tests Makefile defines
59182c4 Add UNITY_OUTPUT_CHAR_HEADER_DECLARATION to tests Makefile defines
a07d07c Allow specifying custom header declaration
c1bc32d - Generator will not change names by default - Fixed some style issues.
f2fdf1a Added Greater than and Less than asserts from other PR

git-subtree-dir: tests/unity
git-subtree-split: 60b13f0685246b009810aecbffafe17fb665d970
2017-09-12 18:30:07 +02:00
Max Bruckner
acf80470f8 Update Unity to version v2.4.2
Merge commit 'b7bfe1e91a0b55d72f849944d5a33b7962d7bf51' into develop
2017-09-12 18:30:07 +02:00
Max Bruckner
afd5d186b7 Release version 1.5.9 2017-09-08 13:54:24 +02:00
Max Bruckner
7456637793 CONTRIBUTORS.md: Add Robin Mallinson 2017-09-08 13:52:15 +02:00
Max Bruckner
d92754cd30 Add valgrind suppressions for ARMv7 2017-09-08 13:25:14 +02:00
Max Bruckner
e4980b65b9 Merge pull request #200 from rmallins/cJSON_ParseWithOpts_fix_ErrorPtr_behaviour
Fix error pointer behaviour of cJSON_ParseWithOpts()
2017-09-08 12:05:19 +02:00
rmallins
629c354390 Rewrite test for cJSON_ParseWithOpts() to expect non-null error
pointer in error case and change code to match new expectations.
2017-09-08 01:22:10 +01:00
rmallins
1b2236a9a6 Improve existing tests showing behaviour of Parse and ParseWithOpts functions. 2017-09-08 01:20:52 +01:00
Max Bruckner
1925d1bbe5 Release version 1.5.8 2017-08-21 11:06:10 +02:00
Max Bruckner
76b705576f Makefile: Fix 'make test'
make test tried to execute the test for cJSON_Utils, which has been
ported to CUnity tests.
2017-08-21 10:58:49 +02:00
Max Bruckner
469a437e2a Add valgrind suppressions for ARVMv7 ArchlinuxARM 2017-07-15 11:59:47 +02:00
Max Bruckner
7e2781a734 Merge pull request #187 from simon-p-r/appveyor
First commit of appveyor
2017-07-15 10:19:14 +02:00
simon-p-r
f0f3e55d48 fixed appveyor script 2017-07-15 09:06:10 +01:00
simon-p-r
2caa884f6a removed x64 Visual Studio 9 2008 build 2017-07-15 09:03:13 +01:00
Max Bruckner
88d66c5da9 Release version 1.5.7 2017-07-12 23:13:14 +02:00
Max Bruckner
954d61e5e7 Fix #189, ensure returns an invalid pointer
If realloc returns NULL, ensure didn't abort but returned
printbuffer.offset instead. If an attacker can control
printbuffer.offset and also make realloc fail at just the right moment,
this would make cJSON potentially write at an arbitrary memory address.
2017-07-12 23:02:31 +02:00
simon-p-r
c6f7f78cbb added copy to powershell script 2017-07-10 10:50:55 +01:00
simon-p-r
824e1b2a99 patch for Visual Studio 9 2008 x64 failed builds 2017-07-10 10:38:21 +01:00
simon-p-r
dd980008f7 add appveyor 2017-07-09 22:31:21 +01:00
Max Bruckner
ecdff7837c Merge pull request #185 from jwilk-forks/spelling
Fix typos in json.dict
2017-07-08 20:16:33 +02:00
Jakub Wilk
a3c2eba991 Fix typos in json.dict 2017-07-08 09:39:06 +02:00
Max Bruckner
bf0bc22a11 CMake: Add ENABLE_SAFE_STACK option 2017-07-05 10:49:32 +02:00
Max Bruckner
5baa77f86c cJSON_Parse{,WithOpts}: Skip UTF-8 (Byte Order Marks) 2017-07-03 22:28:04 +02:00
60 changed files with 2998 additions and 927 deletions

View File

@@ -15,7 +15,7 @@ Coding Style
------------
The coding style has been discussed in [#24](https://github.com/DaveGamble/cJSON/issues/24). The basics are:
* Use 4 tabs for indentation
* Use 4 spaces for indentation
* No oneliners (conditions, loops, variable declarations ...)
* Always use parenthesis for control structures
* Don't implicitly rely on operator precedence, use round brackets in expressions. e.g. `(a > b) && (c < d)` instead of `a>b && c<d`

1
.gitignore vendored
View File

@@ -13,3 +13,4 @@ cJSON_test_utils
libcjson.so.*
libcjson_utils.so.*
*.orig
.vscode

View File

@@ -23,6 +23,6 @@ addons:
script:
- mkdir build
- cd build
- cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_VALGRIND="${VALGRIND}" -DENABLE_SANITIZERS="${SANITIZERS}"
- cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_VALGRIND="${VALGRIND}" -DENABLE_SAFE_STACK="${VALGRIND}" -DENABLE_SANITIZERS="${SANITIZERS}"
- make
- make test CTEST_OUTPUT_ON_FAILURE=On

View File

@@ -1,3 +1,98 @@
1.7.6
=====
Fixes:
------
* Add `SONAME` to the ELF files built by the Makefile (see #252), thanks @YanhaoMo for reporting
* Add include guards and `extern "C"` to `cJSON_Utils.h` (see #256), thanks @daschfg for reporting
Other changes:
--------------
* Mark the Makefile as deprecated in the README.
1.7.5
=====
Fixes:
------
* Fix a bug in the JSON Patch implementation of `cJSON Utils` (see #251), thanks @bobkocisko.
1.7.4
=====
Fixes:
------
* Fix potential use after free if the `string` parameter to `cJSON_AddItemToObject` is an alias of the `string` property of the object that is added (#248). Thanks @hhallen for reporting.
1.7.3
=====
Fixes:
------
* Fix potential double free, thanks @projectgus for reporting (see #241)
1.7.2
=====
Fixes:
------
* Fix the use of GNUInstallDirs variables and the pkgconfig file. Thanks @zeerd for reporting (see #240)
1.7.1
=====
Fixes:
------
* Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting (see #230)
* Fixed two errors with buffered printing. Thanks @liuyunbin for reporting (see #230)
1.7.0
=====
Features:
---------
* Large rewrite of the documentation, see #215
* Added the `cJSON_GetStringValue` function
* Added the `cJSON_CreateStringReference` function
* Added the `cJSON_CreateArrayReference` function
* Added the `cJSON_CreateObjectReference` function
* The `cJSON_Add...ToObject` macros are now functions that return a pointer to the added item, see #226
Fixes:
------
* Fix a problem with `GNUInstallDirs` in the CMakeLists.txt, thanks @yangfl, see #210
* Fix linking the tests when building as static library, see #213
* New overrides for the CMake option `BUILD_SHARED_LIBS`, see #207
Other Changes:
--------------
* Readme: Explain how to include cJSON, see #211
* Removed some trailing spaces in the code, thanks @yangfl, see#212
* Updated [Unity](https://github.com/ThrowTheSwitch/Unity) and [json-patch-tests](https://github.com/json-patch/json-patch-tests)
1.6.0
=====
Features:
---------
* You can now build cJSON as both shared and static library at once with CMake using `-DBUILD_SHARED_AND_STATIC_LIBS=On`, see #178
* UTF-8 byte order marks are now ignored, see #184
* Locales can now be disabled with the option `-DENABLE_LOCALES=Off`, see #202, thanks @Casperinous
* Better support for MSVC and Visual Studio
Other Changes:
--------------
* Add the new warnings `-Wswitch-enum`, `-Wused-but-makred-unused`, `-Wmissing-variable-declarations`, `-Wunused-macro`
* More number printing tests.
* Continuous integration testing with AppVeyor (semi automatic at this point), thanks @simon-p-r
1.5.9
=====
* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`. See #200, thanks @rmallins
1.5.8
=====
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this (#195)
1.5.7
=====
Fixes:
------
* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses. (see #189), fixed in (954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
* Fix a spelling mistake in the AFL fuzzer dictionary (#185), thanks @jwilk
1.5.6
=====
Fixes:

View File

@@ -1,12 +1,12 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
cmake_minimum_required(VERSION 2.8.5)
include(GNUInstallDirs)
project(cJSON C)
include(GNUInstallDirs)
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 5)
set(PROJECT_VERSION_MINOR 7)
set(PROJECT_VERSION_PATCH 6)
set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_VERSION_SO 1)
@@ -73,6 +73,16 @@ if (ENABLE_SANITIZERS)
)
endif()
option(ENABLE_SAFE_STACK "Enables the SafeStack instrumentation pass by the Code Pointer Integrity Project" OFF)
if (ENABLE_SAFE_STACK)
if (ENABLE_SANITIZERS)
message(FATAL_ERROR "ENABLE_SAFE_STACK cannot be used in combination with ENABLE_SANITIZERS")
endif()
list(APPEND custom_compiler_flags
-fsanitize=safe-stack
)
endif()
option(ENABLE_PUBLIC_SYMBOLS "Export library symbols." On)
if (ENABLE_PUBLIC_SYMBOLS)
list(APPEND custom_compiler_flags -fvisibility=hidden)
@@ -97,12 +107,6 @@ endforeach()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${supported_compiler_flags}")
#variables for pkg-config
set(prefix "${CMAKE_INSTALL_PREFIX}")
set(libdir "${CMAKE_INSTALL_LIBDIR}")
set(version "${PROJECT_VERSION}")
set(includedir "${CMAKE_INSTALL_INCLUDEDIR}")
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON)
@@ -113,9 +117,18 @@ file(GLOB HEADERS cJSON.h)
set(SOURCES cJSON.c)
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off)
option(CJSON_OVERRIDE_BUILD_SHARED_LIBS "Override BUILD_SHARED_LIBS with CJSON_BUILD_SHARED_LIBS" OFF)
option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BUILD_SHARED_LIBS is enabled" ON)
if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS))
set(CJSON_LIBRARY_TYPE SHARED)
else()
set(CJSON_LIBRARY_TYPE STATIC)
endif()
if (NOT BUILD_SHARED_AND_STATIC_LIBS)
add_library("${CJSON_LIB}" "${HEADERS}" "${SOURCES}")
add_library("${CJSON_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS}" "${SOURCES}")
else()
# See https://cmake.org/Wiki/CMake_FAQ#How_do_I_make_my_shared_and_static_libraries_have_the_same_root_name.2C_but_different_suffixes.3F
add_library("${CJSON_LIB}" SHARED "${HEADERS}" "${SOURCES}")
@@ -130,15 +143,15 @@ endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" @ONLY)
install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" EXPORT "${CJSON_LIB}")
install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_LIB}")
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON")
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
set_target_properties("${CJSON_LIB}"
@@ -155,7 +168,7 @@ if(ENABLE_CJSON_UTILS)
set(SOURCES_UTILS cJSON_Utils.c)
if (NOT BUILD_SHARED_AND_STATIC_LIBS)
add_library("${CJSON_UTILS_LIB}" "${HEADERS_UTILS}" "${SOURCES_UTILS}")
add_library("${CJSON_UTILS_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
else()
add_library("${CJSON_UTILS_LIB}" SHARED "${HEADERS_UTILS}" "${SOURCES_UTILS}")
@@ -169,15 +182,15 @@ if(ENABLE_CJSON_UTILS)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson_utils.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY)
install(TARGETS "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}")
install(TARGETS "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}")
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON")
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
set_target_properties("${CJSON_UTILS_LIB}"
@@ -197,7 +210,7 @@ configure_file(
# Install package config files
install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON")
DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
option(ENABLE_CJSON_TEST "Enable building cJSON test" ON)
if(ENABLE_CJSON_TEST)
@@ -224,5 +237,11 @@ if(ENABLE_CJSON_TEST)
DEPENDS ${TEST_CJSON})
endif()
# Enable the use of locales
option(ENABLE_LOCALES "Enable the use of locales" ON)
if(ENABLE_LOCALES)
add_definitions(-DENABLE_LOCALES)
endif()
add_subdirectory(tests)
add_subdirectory(fuzzing)

View File

@@ -1,11 +1,15 @@
Contributors
============
Original Author: [Dave Gamble](https://github.com/DaveGamble)
Current Maintainer: [Max Bruckner](https://github.com/FSMaxB)
* [Ajay Bhargav](https://github.com/ajaybhargav)
* [Alper Akcan](https://github.com/alperakcan)
* [Anton Sergeev](https://github.com/anton-sergeev)
* [Bob Kocisko](https://github.com/bobkocisko)
* [Christian Schulze](https://github.com/ChristianSch)
* [Dave Gamble](https://github.com/DaveGamble)
* [Casperinous](https://github.com/Casperinous)
* [Debora Grosse](https://github.com/DeboraG)
* [dieyushi](https://github.com/dieyushi)
* [Dōngwén Huáng (黄东文)](https://github.com/DongwenHuang)
@@ -15,13 +19,13 @@ Contributors
* Ian Mobley
* Irwan Djadjadi
* [IvanVoid](https://github.com/npi3pak)
* [Jakub Wilk](https://github.com/jwilk)
* [Jiri Zouhar](https://github.com/loigu)
* [Jonathan Fether](https://github.com/jfether)
* [Julián Vásquez](https://github.com/juvasquezg)
* [Kevin Branigan](https://github.com/kbranigan)
* [Kyle Chisholm](https://github.com/ChisholmKyle)
* [Linus Wallgren](https://github.com/ecksun)
* [Max Bruckner](https://github.com/FSMaxB)
* Mike Pontillo
* [Mike Jerris](https://github.com/mjerris)
* [Mike Robinson](https://github.com/mhrobinson)
@@ -29,10 +33,15 @@ Contributors
* [Pawel Winogrodzki](https://github.com/PawelWMS)
* [prefetchnta](https://github.com/prefetchnta)
* [Rafael Leal Dias](https://github.com/rafaeldias)
* [Robin Mallinson](https://github.com/rmallins)
* [Rod Vagg](https://github.com/rvagg)
* [Roland Meertens](https://github.com/rmeertens)
* [Romain Porte](https://github.com/MicroJoe)
* [Simon Ricaldone](https://github.com/simon-p-r)
* [Stephan Gatzka](https://github.com/gatzka)
* [Weston Schmidt](https://github.com/schmidtw)
* [yangfl](https://github.com/yangfl)
And probably more people on [SourceForge](https://sourceforge.net/p/cjson/bugs/search/?q=status%3Aclosed-rejected+or+status%3Aclosed-out-of-date+or+status%3Awont-fix+or+status%3Aclosed-fixed+or+status%3Aclosed&page=0)
Also thanks to all the people who reported bugs and suggested new features.

38
LICENSE
View File

@@ -1,20 +1,20 @@
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.
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.

View File

@@ -8,10 +8,13 @@ CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm
LIBVERSION = 1.5.6
LIBVERSION = 1.7.6
CJSON_SOVERSION = 1
UTILS_SOVERSION = 1
CJSON_SO_LDFLAG=-Wl,-soname=$(CJSON_LIBNAME).so.$(CJSON_SOVERSION)
UTILS_SO_LDFLAG=-Wl,-soname=$(UTILS_LIBNAME).so.$(UTILS_SOVERSION)
PREFIX ?= /usr/local
INCLUDE_PATH ?= include/cjson
LIBRARY_PATH ?= lib
@@ -42,6 +45,8 @@ STATIC = a
## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS)
ifeq (Darwin, $(uname))
SHARED = dylib
CJSON_SO_LDFLAG = ""
UTILS_SO_LDFLAG = ""
endif
#cJSON library names
@@ -66,11 +71,10 @@ shared: $(CJSON_SHARED) $(UTILS_SHARED)
static: $(CJSON_STATIC) $(UTILS_STATIC)
tests: $(CJSON_TEST) $(UTILS_TEST)
tests: $(CJSON_TEST)
test: tests
./$(CJSON_TEST)
./$(UTILS_TEST)
.c.o:
$(CC) -c $(R_CFLAGS) $<
@@ -91,10 +95,10 @@ $(UTILS_STATIC): $(UTILS_OBJ)
#shared libraries .so.1.0.0
#cJSON
$(CJSON_SHARED_VERSION): $(CJSON_OBJ)
$(CC) -shared -o $@ $< $(LDFLAGS)
$(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS)
#cJSON_Utils
$(UTILS_SHARED_VERSION): $(UTILS_OBJ)
$(CC) -shared -o $@ $< $(LDFLAGS)
$(CC) -shared -o $@ $< $(UTILS_SO_LDFLAG) $(LDFLAGS)
#objects
#cJSON
@@ -150,4 +154,4 @@ clean:
$(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files
$(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON
$(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils
$(RM) $(CJSON_TEST) $(UTILS_TEST) #delete tests
$(RM) $(CJSON_TEST) #delete test

548
README.md
View File

@@ -7,9 +7,29 @@ Ultralightweight JSON parser in ANSI C.
* [Usage](#usage)
* [Welcome to cJSON](#welcome-to-cjson)
* [Building](#building)
* [Some JSON](#some-json)
* [Here's the structure](#heres-the-structure)
* [Copying the source](#copying-the-source)
* [CMake](#cmake)
* [Makefile](#makefile)
* [Including cJSON](#including-cjson)
* [Data Structure](#data-structure)
* [Working with the data structure](#working-with-the-data-structure)
* [Basic types](#basic-types)
* [Arrays](#arrays)
* [Objects](#objects)
* [Parsing JSON](#parsing-json)
* [Printing JSON](#printing-json)
* [Example](#example)
* [Printing](#printing)
* [Parsing](#parsing)
* [Caveats](#caveats)
* [Zero Character](#zero-character)
* [Character Encoding](#character-encoding)
* [C Standard](#c-standard)
* [Floating Point Numbers](#floating-point-numbers)
* [Deep Nesting Of Arrays And Objects](#deep-nesting-of-arrays-and-objects)
* [Thread Safety](#thread-safety)
* [Case Sensitivity](#case-sensitivity)
* [Duplicate Object Members](#duplicate-object-members)
* [Enjoy cJSON!](#enjoy-cjson)
## License
@@ -88,9 +108,12 @@ You can change the build process with a list of different options that you can p
* `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang, GCC and MSVC). 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)
* `-DENABLE_SAFE_STACK`: Enable the [SafeStack](https://clang.llvm.org/docs/SafeStack.html) instrumentation pass. Currently only works with the Clang compiler. (off by default)
* `-DBUILD_SHARED_LIBS=On`: Build the shared libraries. (on by default)
* `-DBUILD_SHARED_AND_STATIC_LIBS=On`: Build both shared and static libraries. (off by default)
* `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation.
* `-DENABLE_LOCALES=On`: Enable the usage of localeconv method. ( on by default )
* `-DCJSON_OVERRIDE_BUILD_SHARED_LIBS=On`: Enable overriding the value of `BUILD_SHARED_LIBS` with `-DCJSON_BUILD_SHARED_LIBS`.
If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example:
```
@@ -101,10 +124,14 @@ make
make DESTDIR=$pkgdir install
```
On Windows CMake is usually used to create a Visual Studio solution file by running it inside the Developer Command Prompt for Visual Studio, for exact steps follow the official documentation from CMake and Microsoft and use the online search engine of your choice. The descriptions of the the options above still generally apply, although not all of them work on Windows.
#### Makefile
**NOTE:** This Method is deprecated. Use CMake if at all possible. Makefile support is limited to fixing bugs.
If you don't have CMake available, but still have GNU make. You can use the makefile to build cJSON:
Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program.
Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program (not the full test suite).
```
make all
@@ -112,269 +139,347 @@ make all
If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`.
### Some JSON:
### Including cJSON
If you installed it via CMake or the Makefile, you can include cJSON like this:
```json
```c
#include <cjson/cJSON.h>
```
### Data Structure
cJSON represents JSON data using the `cJSON` struct data type:
```c
/* The cJSON structure: */
typedef struct cJSON
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
```
Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
you have a `char *` to it. Everything is a `cJSON` struct.
Get it parsed:
```c
cJSON * root = cJSON_Parse(my_json_string);
```
This is an object. We're in C. We don't have objects. But we do have structs.
What's the framerate?
```c
cJSON *format = cJSON_GetObjectItemCaseSensitive(root, "format");
cJSON *framerate_item = cJSON_GetObjectItemCaseSensitive(format, "frame rate");
double framerate = 0;
if (cJSON_IsNumber(framerate_item))
{
framerate = framerate_item->valuedouble;
}
```
Want to change the framerate?
```c
cJSON *framerate_item = cJSON_GetObjectItemCaseSensitive(format, "frame rate");
cJSON_SetNumberValue(framerate_item, 25);
```
Back to disk?
```c
char *rendered = cJSON_Print(root);
```
Finished? Delete the root (this takes care of everything else).
```c
cJSON_Delete(root);
```
That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers
before you dereference them. If you want to see how you'd build this struct in code?
```c
cJSON *root;
cJSON *fmt;
root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
cJSON_AddStringToObject(fmt, "type", "rect");
cJSON_AddNumberToObject(fmt, "width", 1920);
cJSON_AddNumberToObject(fmt, "height", 1080);
cJSON_AddFalseToObject (fmt, "interlace");
cJSON_AddNumberToObject(fmt, "frame rate", 24);
```
Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
Look at `test.c` for a bunch of nice examples, mostly all ripped off the [json.org](http://json.org) site, and
a few from elsewhere.
What about manual mode? First up you need some detail.
Let's cover how the `cJSON` objects represent the JSON data.
cJSON doesn't distinguish arrays from objects in handling; just type.
Each `cJSON` has, potentially, a child, siblings, value, a name.
* The `root` object has: *Object* Type and a Child
* The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
* Sibling has type *Object*, name "format", and a child.
* That child has type *String*, name "type", value "rect", and a sibling:
* Sibling has type *Number*, name "width", value 1920, and a sibling:
* Sibling has type *Number*, name "height", value 1080, and a sibling:
* Sibling has type *False*, name "interlace", and a sibling:
* Sibling has type *Number*, name "frame rate", value 24
### Here's the structure:
```c
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint; /* writing to valueint is DEPRECATED, please use cJSON_SetNumberValue instead */
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
double valuedouble;
char *string;
} cJSON;
```
By default all values are 0 unless set by virtue of being meaningful.
An item of this type represents a JSON value. The type is stored in `type` as a bit-flag (**this means that you cannot find out the type by just comparing the value of `type`**).
`next`/`prev` is a doubly linked list of siblings. `next` takes you to your sibling,
`prev` takes you back from your sibling to you.
Only objects and arrays have a `child`, and it's the head of the doubly linked list.
A `child` entry will have `prev == 0`, but next potentially points on. The last sibling has `next == 0`.
The type expresses *Null*/*True*/*False*/*Number*/*String*/*Array*/*Object*, all of which are `#defined` in
`cJSON.h`.
To check the type of an item, use the corresponding `cJSON_Is...` function. It does a `NULL` check followed by a type check and returns a boolean value if the item is of this type.
A *Number* has `valueint` and `valuedouble`. `valueint` is a relict of the past, so always use `valuedouble`.
The type can be one of the following:
* `cJSON_Invalid` (check with `cJSON_IsInvalid`): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes.
* `cJSON_False` (check with `cJSON_IsFalse`): Represents a `false` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
* `cJSON_True` (check with `cJSON_IsTrue`): Represents a `true` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
* `cJSON_NULL` (check with `cJSON_IsNull`): Represents a `null` value.
* `cJSON_Number` (check with `cJSON_IsNumber`): Represents a number value. The value is stored as a double in `valuedouble` and also in `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`.
* `cJSON_String` (check with `cJSON_IsString`): Represents a string value. It is stored in the form of a zero terminated string in `valuestring`.
* `cJSON_Array` (check with `cJSON_IsArray`): Represent an array value. This is implemented by pointing `child` to a linked list of `cJSON` items that represent the values in the array. The elements are linked together using `next` and `prev`, where the first element has `prev == NULL` and the last element `next == NULL`.
* `cJSON_Object` (check with `cJSON_IsObject`): Represents an object value. Objects are stored same way as an array, the only difference is that the items in the object store their keys in `string`.
* `cJSON_Raw` (check with `cJSON_IsRaw`): Represents any kind of JSON that is stored as a zero terminated array of characters in `valuestring`. This can be used, for example, to avoid printing the same static JSON over and over again to save performance. cJSON will never create this type when parsing. Also note that cJSON doesn't check if it is valid JSON.
Any entry which is in the linked list which is the child of an object will have a `string`
which is the "name" of the entry. When I said "name" in the above example, that's `string`.
`string` is the JSON name for the 'variable name' if you will.
Additionally there are the following two flags:
* `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not it's children/valuestring.
* `cJSON_StringIsConst`: This means that `string` points to a constant string. This means that `cJSON_Delete` and other functions will not try to deallocate `string`.
Now you can trivially walk the lists, recursively, and parse as you please.
You can invoke `cJSON_Parse` to get cJSON to parse for you, and then you can take
the root object, and traverse the structure (which is, formally, an N-tree),
and tokenise as you please. If you wanted to build a callback style parser, this is how
you'd do it (just an example, since these things are very specific):
### Working with the data structure
For every value type there is a `cJSON_Create...` function that can be used to create an item of that type.
All of these will allocate a `cJSON` struct that can later be deleted with `cJSON_Delete`.
Note that you have to delete them at some point, otherwise you will get a memory leak.
**Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted, it gets deleted as well.
#### Basic types
* **null** is created with `cJSON_CreateNull`
* **booleans** are created with `cJSON_CreateTrue`, `cJSON_CreateFalse` or `cJSON_CreateBool`
* **numbers** are created with `cJSON_CreateNumber`. This will set both `valuedouble` and `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`
* **strings** are created with `cJSON_CreateString` (copies the string) or with `cJSON_CreateStringReference` (directly points to the string. This means that `valuestring` won't be deleted by `cJSON_Delete` and you are responsible for it's lifetime, useful for constants)
#### Arrays
You can create an empty array with `cJSON_CreateArray`. `cJSON_CreateArrayReference` can be used to create an array that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
To add items to an array, use `cJSON_AddItemToArray` to append items to the end.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere.
To insert items in the middle, use `cJSON_InsertItemInArray`. It will insert an item at the given 0 based index and shift all the existing items to the right.
If you want to take an item out of an array at a given index and continue using it, use `cJSON_DetachItemFromArray`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
Deleting items is done with `cJSON_DeleteItemFromArray`. It works like `cJSON_DetachItemFromArray`, but deletes the detached item via `cJSON_Delete`.
You can also replace an item in an array in place. Either with `cJSON_ReplaceItemInArray` using an index or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.
To get the size of an array, use `cJSON_GetArraySize`. Use `cJSON_GetArrayItem` to get an element at a given index.
Because an array is stored as a linked list, iterating it via index is inefficient (`O(n²)`), so you can iterate over an array using the `cJSON_ArrayForEach` macro in `O(n)` time complexity.
#### Objects
You can create an empty object with `cJSON_CreateObject`. `cJSON_CreateObjectReference` can be used to create an object that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
To add items to an object, use `cJSON_AddItemToObject`. Use `cJSON_AddItemToObjectCS` to add an item to an object with a name that is a constant or reference (key of the item, `string` in the `cJSON` struct), so that it doesn't get freed by `cJSON_Delete`.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere.
If you want to take an item out of an object, use `cJSON_DetachItemFromObjectCaseSensitive`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
Deleting items is done with `cJSON_DeleteItemFromObjectCaseSensitive`. It works like `cJSON_DetachItemFromObjectCaseSensitive` followed by `cJSON_Delete`.
You can also replace an item in an object in place. Either with `cJSON_ReplaceItemInObjectCaseSensitive` using a key or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.
To get the size of an object, you can use `cJSON_GetArraySize`, this works because internally objects are stored as arrays.
If you want to access an item in an object, use `cJSON_GetObjectItemCaseSensitive`.
To iterate over an object, you can use the `cJSON_ArrayForEach` macro the same way as for arrays.
cJSON also provides convenient helper functions for quickly creating a new item and adding it to an object, like `cJSON_AddNullToObject`. They return a pointer to the new item or `NULL` if they failed.
### Parsing JSON
Given some JSON in a zero terminated string, you can parse it with `cJSON_Parse`.
```c
void parse_and_callback(cJSON *item, const char *prefix)
cJSON *json = cJSON_Parse(string);
```
It will parse the JSON and allocate a tree of `cJSON` items that represents it. Once it returns, you are fully responsible for deallocating it after use with `cJSON_Delete`.
The allocator used by `cJSON_Parse` is `malloc` and `free` by default but can be changed (globally) with `cJSON_InitHooks`.
If an error occurs a pointer to the position of the error in the input string can be accessed using `cJSON_GetErrorPtr`. Note though that this can produce race conditions in multithreading scenarios, in that case it is better to use `cJSON_ParseWithOpts` with `return_parse_end`.
By default, characters in the input string that follow the parsed JSON will not be considered as an error.
If you want more options, use `cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)`.
`return_parse_end` returns a pointer to the end of the JSON in the input string or the position that an error occurs at (thereby replacing `cJSON_GetErrorPtr` in a thread safe way). `require_null_terminated`, if set to `1` will make it an error if the input string contains data after the JSON.
### Printing JSON
Given a tree of `cJSON` items, you can print them as a string using `cJSON_Print`.
```c
char *string = cJSON_Print(json);
```
It will allocate a string and print a JSON representation of the tree into it. Once it returns, you are fully responsible for deallocating it after use with your allocator. (usually `free`, depends on what has been set with `cJSON_InitHooks`).
`cJSON_Print` will print with whitespace for formatting. If you want to print without formatting, use `cJSON_PrintUnformatted`.
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for it's first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and it's length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
### Example
In this example we want to build and parse the following JSON:
```json
{
while (item)
{
char *newprefix = malloc(strlen(prefix) + strlen(item->string) + 2);
sprintf(newprefix, "%s/%s", prefix, item->string);
int dorecurse = callback(newprefix, item->type, item);
if (item->child && dorecurse)
"name": "Awesome 4K",
"resolutions": [
{
parse_and_callback(item->child, newprefix);
"width": 1280,
"height": 720
},
{
"width": 1920,
"height": 1080
},
{
"width": 3840,
"height": 2160
}
item = item->next;
free(newprefix);
}
]
}
```
The `prefix` process will build you a separated list, to simplify your callback handling.
The `dorecurse` flag would let the callback decide to handle sub-arrays on it's own, or
let you invoke it per-item. For the item above, your callback might look like this:
#### Printing
Let's build the above JSON and print it to a string:
```c
int callback(const char *name, int type, cJSON *item)
//create a monitor with a list of supported resolutions
char* create_monitor(void)
{
if (!strcmp(name, "name"))
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *name = NULL;
cJSON *resolutions = NULL;
cJSON *resolution = NULL;
cJSON *width = NULL;
cJSON *height = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (monitor == NULL)
{
/* populate name */
}
else if (!strcmp(name, "format/type"))
{
/* handle "rect" */ }
else if (!strcmp(name, "format/width"))
{
/* 800 */
}
else if (!strcmp(name, "format/height"))
{
/* 600 */
}
else if (!strcmp(name, "format/interlace"))
{
/* false */
}
else if (!strcmp(name, "format/frame rate"))
{
/* 24 */
goto end;
}
return 1;
}
```
Alternatively, you might like to parse iteratively.
You'd use:
```c
void parse_object(cJSON *item)
{
int i;
for (i = 0; i < cJSON_GetArraySize(item); i++)
name = cJSON_CreateString("Awesome 4K");
if (name == NULL)
{
cJSON *subitem = cJSON_GetArrayItem(item, i);
// handle subitem
goto end;
}
}
```
/* after creation was successful, immediately add it to the monitor,
* thereby transfering ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
Or, for PROPER manual mode:
```c
void parse_object(cJSON *item)
{
cJSON *subitem = item->child;
while (subitem)
resolutions = cJSON_CreateArray();
if (resolutions == NULL)
{
// handle subitem
if (subitem->child)
goto end;
}
cJSON_AddItemToObject(monitor, "resolutions", resolutions);
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
resolution = cJSON_CreateObject();
if (resolution == NULL)
{
parse_object(subitem->child);
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
width = cJSON_CreateNumber(resolution_numbers[index][0]);
if (width == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "width", width);
height = cJSON_CreateNumber(resolution_numbers[index][1]);
if (height == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "height", height);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
```
Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lifes a little easier:
```c
char *create_monitor_with_helpers(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *resolutions = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
{
goto end;
}
resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
if (resolutions == NULL)
{
goto end;
}
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
cJSON *resolution = cJSON_CreateObject();
if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
{
goto end;
}
subitem = subitem->next;
if(cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
}
string = cJSON_Print(monitor);
if (string == NULL) {
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
```
Of course, this should look familiar, since this is just a stripped-down version
of the callback-parser.
This should cover most uses you'll find for parsing. The rest should be possible
to infer.. and if in doubt, read the source! There's not a lot of it! ;)
In terms of constructing JSON data, the example code above is the right way to do it.
You can, of course, hand your sub-objects to other functions to populate.
Also, if you find a use for it, you can manually build the objects.
For instance, suppose you wanted to build an array of objects?
#### Parsing
In this example we will parse a JSON in the above format and check if the monitor supports a Full HD resolution while printing some diagnostic output:
```c
cJSON *objects[24];
cJSON *Create_array_of_anything(cJSON **items, int num)
/* return 1 if the monitor supports full hd, 0 otherwise */
int supports_full_hd(const char * const monitor)
{
int i;
cJSON *prev;
cJSON *root = cJSON_CreateArray();
for (i = 0; i < 24; i++)
const cJSON *resolution = NULL;
const cJSON *resolutions = NULL;
const cJSON *name = NULL;
int status = 0;
cJSON *monitor_json = cJSON_Parse(monitor);
if (monitor_json == NULL)
{
if (!i)
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
root->child = objects[i];
fprintf(stderr, "Error before: %s\n", error_ptr);
}
else
{
prev->next = objects[i];
objects[i]->prev = prev;
}
prev = objects[i];
status = 0;
goto end;
}
return root;
name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
if (cJSON_IsString(name) && (name->valuestring != NULL))
{
printf("Checking monitor \"%s\"\n", name->valuestring);
}
resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
cJSON_ArrayForEach(resolution, resolutions)
{
cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
{
status = 0;
goto end;
}
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
{
status = 1;
goto end;
}
}
end:
cJSON_Delete(monitor_json);
return status;
}
```
and simply: `Create_array_of_anything(objects, 24);`
cJSON doesn't make any assumptions about what order you create things in.
You can attach the objects, as above, and later add children to each
of those objects.
As soon as you call `cJSON_Print`, it renders the structure to text.
The `test.c` code shows how to handle a bunch of typical cases. If you uncomment
the code, it'll load, parse and print a bunch of test files, also from [json.org](http://json.org),
which are more complex than I'd care to try and stash into a `const char array[]`.
Note that there are no NULL checks except for the result of `cJSON_Parse` because `cJSON_GetObjectItemCaseSensitive` checks for `NULL` inputs already, so a `NULL` value is just propagated and `cJSON_IsNumber` and `cJSON_IsString` return `0` if the input is `NULL`.
### Caveats
@@ -415,7 +520,12 @@ However it is thread safe under the following conditions:
When cJSON was originally created, it didn't follow the JSON standard and didn't make a distinction between uppercase and lowercase letters. If you want the correct, standard compliant, behavior, you need to use the `CaseSensitive` functions where available.
#### Duplicate Object Members
cJSON supports parsing and printing JSON that contains objects that have multiple members with the same name. `cJSON_GetObjectItemCaseSensitive` however will always only return the first one.
# Enjoy cJSON!
- Dave Gamble, Aug 2009
- [cJSON contributors](CONTRIBUTORS.md)
- Dave Gamble (original author)
- Max Bruckner (current maintainer)
- and the other [cJSON contributors](CONTRIBUTORS.md)

86
appveyor.yml Normal file
View File

@@ -0,0 +1,86 @@
os: Visual Studio 2015
# ENABLE_CUSTOM_COMPILER_FLAGS - on by default
# ENABLE_SANITIZERS - off by default
# ENABLE_PUBLIC_SYMBOLS - on by default
# BUILD_SHARED_LIBS - on by default
# ENABLE_TARGET_EXPORT - on by default
# ENABLE_CJSON_UTILS - off by default
# ENABLE_CJSON_TEST -on by default
# ENABLE_VALGRIND - off by default
# ENABLE_FUZZING - off by default
environment:
matrix:
- GENERATOR: "Visual Studio 14 2015"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 14 2015"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 12 2013"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 12 2013"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 11 2012"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 11 2012"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 10 2010"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 10 2010"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 9 2008"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 9 2008"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
platform:
- x86
- x64
matrix:
exclude:
- platform: x64
GENERATOR: "Visual Studio 9 2008"
configuration:
- Release
build_script:
- ps: if($env:PLATFORM -eq "x64") { $env:CMAKE_GEN_SUFFIX=" Win64" }
- cmake "-G%GENERATOR%%CMAKE_GEN_SUFFIX%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% -DENABLE_CJSON_TEST=%ENABLE_CJSON_TEST% -H. -Bbuild
- cmake --build build --config "%CONFIGURATION%"
on_failure:
- ps: if(Test-Path builds/CMakeFiles/CMakeOutput.log) { cat builds/CMakeFiles/CMakeOutput.log }
- ps: if(Test-Path builds/CMakeFiles/CMakeError.log) { cat builds/CMakeFiles/CMakeError.log }

295
cJSON.c
View File

@@ -44,7 +44,10 @@
#include <float.h>
#include <limits.h>
#include <ctype.h>
#ifdef ENABLE_LOCALES
#include <locale.h>
#endif
#if defined(_MSC_VER)
#pragma warning (pop)
@@ -70,8 +73,16 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position);
}
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
if (!cJSON_IsString(item)) {
return NULL;
}
return item->valuestring;
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 6)
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 6)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
@@ -227,8 +238,12 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
/* get the decimal point character of the current locale */
static unsigned char get_decimal_point(void)
{
#ifdef ENABLE_LOCALES
struct lconv *lconv = localeconv();
return (unsigned char) lconv->decimal_point[0];
#else
return '.';
#endif
}
typedef struct
@@ -410,6 +425,14 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
{
/* reallocate with realloc if available */
newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
if (newbuffer == NULL)
{
p->hooks.deallocate(p->buffer);
p->length = 0;
p->buffer = NULL;
return NULL;
}
}
else
{
@@ -489,7 +512,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
}
/* reserve appropriate space in the output */
output_pointer = ensure(output_buffer, (size_t)length);
output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
if (output_pointer == NULL)
{
return false;
@@ -958,6 +981,22 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
return buffer;
}
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
{
if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
{
return NULL;
}
if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
{
buffer->offset += 3;
}
return buffer;
}
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
{
@@ -984,7 +1023,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
goto fail;
}
if (!parse_value(item, buffer_skip_whitespace(&buffer)))
if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
{
/* parse failure. ep is set. */
goto fail;
@@ -1031,10 +1070,8 @@ fail:
{
*return_parse_end = (const char*)local_error.json + local_error.position;
}
else
{
global_error = local_error;
}
global_error = local_error;
}
return NULL;
@@ -1050,13 +1087,15 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
{
static const size_t default_buffer_size = 256;
printbuffer buffer[1];
unsigned char *printed = NULL;
memset(buffer, 0, sizeof(buffer));
/* create buffer */
buffer->buffer = (unsigned char*) hooks->allocate(256);
buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
buffer->length = default_buffer_size;
buffer->format = format;
buffer->hooks = *hooks;
if (buffer->buffer == NULL)
@@ -1074,7 +1113,7 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
/* check if reallocate is available */
if (hooks->reallocate != NULL)
{
printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->length);
printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
buffer->buffer = NULL;
if (printed == NULL) {
goto fail;
@@ -1222,7 +1261,6 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf
return parse_object(item, input_buffer);
}
return false;
}
@@ -1273,10 +1311,6 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp
size_t raw_length = 0;
if (item->valuestring == NULL)
{
if (!output_buffer->noalloc)
{
output_buffer->hooks.deallocate(output_buffer->buffer);
}
return false;
}
@@ -1808,14 +1842,13 @@ static cJSON *create_reference(const cJSON *item, const internal_hooks * const h
return reference;
}
/* Add item to array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
if ((item == NULL) || (array == NULL))
{
return;
return false;
}
child = array->child;
@@ -1834,19 +1867,14 @@ CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
}
suffix_object(child, item);
}
return true;
}
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
/* Add item to array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
if (item == NULL)
{
return;
}
/* call cJSON_AddItemToObjectCS for code reuse */
cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
/* remove cJSON_StringIsConst flag */
item->type &= ~cJSON_StringIsConst;
add_item_to_array(array, item);
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
@@ -1855,26 +1883,64 @@ CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSO
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
/* Add an item to an object with constant string as key */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
/* helper function to cast away const */
static void* cast_away_const(const void* string)
{
if ((item == NULL) || (string == NULL))
{
return;
}
if (!(item->type & cJSON_StringIsConst) && item->string)
{
global_hooks.deallocate(item->string);
}
item->string = (char*)string;
item->type |= cJSON_StringIsConst;
cJSON_AddItemToArray(object, item);
return (void*)string;
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic pop
#endif
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
{
char *new_key = NULL;
int new_type = cJSON_Invalid;
if ((object == NULL) || (string == NULL) || (item == NULL))
{
return false;
}
if (constant_key)
{
new_key = (char*)cast_away_const(string);
new_type = item->type | cJSON_StringIsConst;
}
else
{
new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
if (new_key == NULL)
{
return false;
}
new_type = item->type & ~cJSON_StringIsConst;
}
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{
hooks->deallocate(item->string);
}
item->string = new_key;
item->type = new_type;
return add_item_to_array(object, item);
}
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, false);
}
/* Add an item to an object with constant string as key */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, true);
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
{
if (array == NULL)
@@ -1882,7 +1948,7 @@ CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
return;
}
cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
add_item_to_array(array, create_reference(item, &global_hooks));
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
@@ -1892,7 +1958,115 @@ CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *str
return;
}
cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
}
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
{
cJSON *null = cJSON_CreateNull();
if (add_item_to_object(object, name, null, &global_hooks, false))
{
return null;
}
cJSON_Delete(null);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
{
cJSON *true_item = cJSON_CreateTrue();
if (add_item_to_object(object, name, true_item, &global_hooks, false))
{
return true_item;
}
cJSON_Delete(true_item);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
{
cJSON *false_item = cJSON_CreateFalse();
if (add_item_to_object(object, name, false_item, &global_hooks, false))
{
return false_item;
}
cJSON_Delete(false_item);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
{
cJSON *bool_item = cJSON_CreateBool(boolean);
if (add_item_to_object(object, name, bool_item, &global_hooks, false))
{
return bool_item;
}
cJSON_Delete(bool_item);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
{
cJSON *number_item = cJSON_CreateNumber(number);
if (add_item_to_object(object, name, number_item, &global_hooks, false))
{
return number_item;
}
cJSON_Delete(number_item);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
{
cJSON *string_item = cJSON_CreateString(string);
if (add_item_to_object(object, name, string_item, &global_hooks, false))
{
return string_item;
}
cJSON_Delete(string_item);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
{
cJSON *raw_item = cJSON_CreateRaw(raw);
if (add_item_to_object(object, name, raw_item, &global_hooks, false))
{
return raw_item;
}
cJSON_Delete(raw_item);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
{
cJSON *object_item = cJSON_CreateObject();
if (add_item_to_object(object, name, object_item, &global_hooks, false))
{
return object_item;
}
cJSON_Delete(object_item);
return NULL;
}
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
{
cJSON *array = cJSON_CreateArray();
if (add_item_to_object(object, name, array, &global_hooks, false))
{
return array;
}
cJSON_Delete(array);
return NULL;
}
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
@@ -1977,7 +2151,7 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
after_inserted = get_array_item(array, (size_t)which);
if (after_inserted == NULL)
{
cJSON_AddItemToArray(array, newitem);
add_item_to_array(array, newitem);
return;
}
@@ -2157,6 +2331,39 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
return item;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if (item != NULL)
{
item->type = cJSON_String | cJSON_IsReference;
item->valuestring = (char*)cast_away_const(string);
}
return item;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if (item != NULL) {
item->type = cJSON_Object | cJSON_IsReference;
item->child = (cJSON*)cast_away_const(child);
}
return item;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
cJSON *item = cJSON_New_Item(&global_hooks);
if (item != NULL) {
item->type = cJSON_Array | cJSON_IsReference;
item->child = (cJSON*)cast_away_const(child);
}
return item;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
{
cJSON *item = cJSON_New_Item(&global_hooks);

34
cJSON.h
View File

@@ -30,7 +30,7 @@ extern "C"
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 5
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 6
#include <stddef.h>
@@ -139,7 +139,7 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
@@ -165,6 +165,9 @@ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *st
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
@@ -189,6 +192,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/arrray that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items. */
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
@@ -234,14 +245,17 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
#define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s))
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))

View File

@@ -988,6 +988,12 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_
cJSON_AddItemToObject(parent, (char*)child_pointer, value);
value = NULL;
}
else /* parent is not an object */
{
/* Couldn't find object to add to. */
status = 9;
goto cleanup;
}
cleanup:
if (value != NULL)

View File

@@ -20,6 +20,14 @@
THE SOFTWARE.
*/
#ifndef cJSON_Utils__h
#define cJSON_Utils__h
#ifdef __cplusplus
extern "C"
{
#endif
#include "cJSON.h"
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
@@ -72,3 +80,9 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
/* Sorts the members of the object into alphabetical order. */
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,8 +1,8 @@
bf{
"name": "Jack (\"Bee\") Nimble",
"format": {"type": "rect",
"width": 1920,
"height": 1080,
"name": "Jack (\"Bee\") Nimble",
"format": {"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,"frame rate": 24
}
}

View File

@@ -6,7 +6,7 @@ bf{"widget": {
"width": 500,
"height": 500
},
"image": {
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
@@ -23,4 +23,4 @@ bf{"widget": {
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
}}

View File

@@ -6,7 +6,7 @@ bu{"widget": {
"width": 500,
"height": 500
},
"image": {
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
@@ -23,4 +23,4 @@ bu{"widget": {
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
}}

View File

@@ -6,7 +6,7 @@ uf{"widget": {
"width": 500,
"height": 500
},
"image": {
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
@@ -23,4 +23,4 @@ uf{"widget": {
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
}}

View File

@@ -6,7 +6,7 @@ uu{"widget": {
"width": 500,
"height": 500
},
"image": {
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
@@ -23,4 +23,4 @@ uu{"widget": {
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
}}

View File

@@ -1,5 +1,5 @@
bf{"web-app": {
"servlet": [
"servlet": [
{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
@@ -55,7 +55,7 @@ bf{"web-app": {
{
"servlet-name": "cofaxAdmin",
"servlet-class": "org.cofax.cds.AdminServlet"},
{
"servlet-name": "fileServlet",
"servlet-class": "org.cofax.cds.FileServlet"},
@@ -82,7 +82,7 @@ bf{"web-app": {
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"}}}

View File

@@ -25,8 +25,8 @@ escape_sequence_r="\\r"
escape_sequence_t="\\t"
escape_sequence_quote="\\\""
escape_sequence_backslash="\\\\"
escapce_sequence_slash="\\/"
escpae_sequence_utf16_base="\\u"
escape_sequence_slash="\\/"
escape_sequence_utf16_base="\\u"
escape_sequence_utf16="\\u12ab"
number_integer="1"

View File

@@ -2,8 +2,8 @@
set(CJSON_UTILS_FOUND @ENABLE_CJSON_UTILS@)
# The include directories used by cJSON
set(CJSON_INCLUDE_DIRS "@prefix@/@includedir@")
set(CJSON_INCLUDE_DIR "@prefix@/@includedir@")
set(CJSON_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
set(CJSON_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)

View File

@@ -1,9 +1,8 @@
prefix=@prefix@
libdir=${prefix}/@libdir@
includedir=${prefix}/@includedir@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: libcjson
Version: @version@
Version: @PROJECT_VERSION@
Description: Ultralightweight JSON parser in ANSI C
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson

View File

@@ -1,9 +1,8 @@
prefix=@prefix@
libdir=${prefix}/@libdir@
includedir=${prefix}/@includedir@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: libcjson_utils
Version: @version@
Version: @PROJECT_VERSION@
Description: An implementation of JSON Pointer, Patch and Merge Patch based on cJSON.
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson_utils

View File

@@ -1,58 +0,0 @@
project('cJSON', 'c', default_options: ['c_std=c89'])
version = '1.6.0'
soversion = '0'
compiler = meson.get_compiler('c')
compiler_flags = []
if (compiler.get_id() == 'clang') or (compiler.get_id() == 'gcc')
compiler_flags += [
'-pedantic',
'-Wall',
'-Wextra',
'-Werror',
'-Wstrict-prototypes',
'-Wwrite-strings',
'-Wshadow',
'-Winit-self',
'-Wcast-align',
'-Wformat=2',
'-Wmissing-prototypes',
'-Wstrict-overflow=2',
'-Wcast-qual',
'-Wundef',
'-Wswitch-default',
'-Wconversion',
'-Wc++-compat',
'-fstack-protector-strong',
'-Wcomma',
'-Wdouble-promotion',
'-Wparentheses',
'-Wformat-overflow',
'-Wunused-macros',
'-Wmissing-variable-declarations',
'-Wused-but-marked-unused',
'-Wswitch-enum'
]
endif
foreach flag : compiler_flags
if compiler.has_argument(flag)
add_project_arguments(flag, language: 'c')
endif
endforeach
math = compiler.find_library('m', required: false)
cjson = shared_library('cjson', 'cJSON.c', dependencies: math, version: version, soversion: soversion, install: true)
if get_option('enable_cjson_utils')
cjson_utils = shared_library('cjson_utils', 'cJSON_Utils.c', link_with: cjson, version: version, soversion: soversion, install: true)
endif
if get_option('enable_cjson_tests')
cjson_test = executable('cjson_test', 'test.c', link_with: cjson)
test('cjson_test', cjson_test)
endif
subdir('tests')

View File

@@ -1,2 +0,0 @@
option('enable_cjson_utils', type: 'boolean', value: true)
option('enable_cjson_tests', type: 'boolean', value: true)

View File

@@ -1,5 +1,5 @@
if(ENABLE_CJSON_TEST)
add_library(unity unity/src/unity.c)
add_library(unity "${CJSON_LIBRARY_TYPE}" unity/src/unity.c)
# Disable -Werror for Unity
if (FLAG_SUPPORTED_Werror)
@@ -55,10 +55,10 @@ if(ENABLE_CJSON_TEST)
misc_tests
parse_with_opts
compare_tests
cjson_add
readme_examples
)
add_library(test-common common.c)
option(ENABLE_VALGRIND OFF "Enable the valgrind memory checker for the tests.")
if (ENABLE_VALGRIND)
find_program(MEMORYCHECK_COMMAND valgrind)
@@ -66,13 +66,13 @@ if(ENABLE_CJSON_TEST)
message(WARNING "Valgrind couldn't be found.")
unset(MEMORYCHECK_COMMAND)
else()
set(MEMORYCHECK_COMMAND_OPTIONS --trace-children=yes --leak-check=full --error-exitcode=1)
set(MEMORYCHECK_COMMAND_OPTIONS --trace-children=yes --leak-check=full --error-exitcode=1 --suppressions=${CMAKE_CURRENT_SOURCE_DIR}/../valgrind.supp)
endif()
endif()
foreach(unity_test ${unity_tests})
add_executable("${unity_test}" "${unity_test}.c")
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity test-common)
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity)
if(MEMORYCHECK_COMMAND)
add_test(NAME "${unity_test}"
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${unity_test}")
@@ -97,7 +97,7 @@ if(ENABLE_CJSON_TEST)
foreach (cjson_utils_test ${cjson_utils_tests})
add_executable("${cjson_utils_test}" "${cjson_utils_test}.c")
target_link_libraries("${cjson_utils_test}" "${CJSON_LIB}" "${CJSON_UTILS_LIB}" unity test-common)
target_link_libraries("${cjson_utils_test}" "${CJSON_LIB}" "${CJSON_UTILS_LIB}" unity)
if(MEMORYCHECK_COMMAND)
add_test(NAME "${cjson_utils_test}"
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${cjson_utils_test}")

416
tests/cjson_add.c Normal file
View File

@@ -0,0 +1,416 @@
/*
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 "common.h"
static void *failing_malloc(size_t size)
{
(void)size;
return NULL;
}
static cJSON_Hooks failing_hooks = {
failing_malloc,
free
};
static void cjson_add_null_should_add_null(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *null = NULL;
cJSON_AddNullToObject(root, "null");
TEST_ASSERT_NOT_NULL(null = cJSON_GetObjectItemCaseSensitive(root, "null"));
TEST_ASSERT_EQUAL_INT(null->type, cJSON_NULL);
cJSON_Delete(root);
}
static void cjson_add_null_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddNullToObject(NULL, "null"));
TEST_ASSERT_NULL(cJSON_AddNullToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_null_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddNullToObject(root, "null"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_true_should_add_true(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *true_item = NULL;
cJSON_AddTrueToObject(root, "true");
TEST_ASSERT_NOT_NULL(true_item = cJSON_GetObjectItemCaseSensitive(root, "true"));
TEST_ASSERT_EQUAL_INT(true_item->type, cJSON_True);
cJSON_Delete(root);
}
static void cjson_add_true_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddTrueToObject(NULL, "true"));
TEST_ASSERT_NULL(cJSON_AddTrueToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_true_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddTrueToObject(root, "true"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_false_should_add_false(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *false_item = NULL;
cJSON_AddFalseToObject(root, "false");
TEST_ASSERT_NOT_NULL(false_item = cJSON_GetObjectItemCaseSensitive(root, "false"));
TEST_ASSERT_EQUAL_INT(false_item->type, cJSON_False);
cJSON_Delete(root);
}
static void cjson_add_false_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddFalseToObject(NULL, "false"));
TEST_ASSERT_NULL(cJSON_AddFalseToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_false_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddFalseToObject(root, "false"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_bool_should_add_bool(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *true_item = NULL;
cJSON *false_item = NULL;
/* true */
cJSON_AddBoolToObject(root, "true", true);
TEST_ASSERT_NOT_NULL(true_item = cJSON_GetObjectItemCaseSensitive(root, "true"));
TEST_ASSERT_EQUAL_INT(true_item->type, cJSON_True);
/* false */
cJSON_AddBoolToObject(root, "false", false);
TEST_ASSERT_NOT_NULL(false_item = cJSON_GetObjectItemCaseSensitive(root, "false"));
TEST_ASSERT_EQUAL_INT(false_item->type, cJSON_False);
cJSON_Delete(root);
}
static void cjson_add_bool_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddBoolToObject(NULL, "false", false));
TEST_ASSERT_NULL(cJSON_AddBoolToObject(root, NULL, false));
cJSON_Delete(root);
}
static void cjson_add_bool_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddBoolToObject(root, "false", false));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_number_should_add_number(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *number = NULL;
cJSON_AddNumberToObject(root, "number", 42);
TEST_ASSERT_NOT_NULL(number = cJSON_GetObjectItemCaseSensitive(root, "number"));
TEST_ASSERT_EQUAL_INT(number->type, cJSON_Number);
TEST_ASSERT_EQUAL_DOUBLE(number->valuedouble, 42);
TEST_ASSERT_EQUAL_INT(number->valueint, 42);
cJSON_Delete(root);
}
static void cjson_add_number_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddNumberToObject(NULL, "number", 42));
TEST_ASSERT_NULL(cJSON_AddNumberToObject(root, NULL, 42));
cJSON_Delete(root);
}
static void cjson_add_number_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddNumberToObject(root, "number", 42));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_string_should_add_string(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *string = NULL;
cJSON_AddStringToObject(root, "string", "Hello World!");
TEST_ASSERT_NOT_NULL(string = cJSON_GetObjectItemCaseSensitive(root, "string"));
TEST_ASSERT_EQUAL_INT(string->type, cJSON_String);
TEST_ASSERT_EQUAL_STRING(string->valuestring, "Hello World!");
cJSON_Delete(root);
}
static void cjson_add_string_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddStringToObject(NULL, "string", "string"));
TEST_ASSERT_NULL(cJSON_AddStringToObject(root, NULL, "string"));
cJSON_Delete(root);
}
static void cjson_add_string_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddStringToObject(root, "string", "string"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_raw_should_add_raw(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *raw = NULL;
cJSON_AddRawToObject(root, "raw", "{}");
TEST_ASSERT_NOT_NULL(raw = cJSON_GetObjectItemCaseSensitive(root, "raw"));
TEST_ASSERT_EQUAL_INT(raw->type, cJSON_Raw);
TEST_ASSERT_EQUAL_STRING(raw->valuestring, "{}");
cJSON_Delete(root);
}
static void cjson_add_raw_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddRawToObject(NULL, "raw", "{}"));
TEST_ASSERT_NULL(cJSON_AddRawToObject(root, NULL, "{}"));
cJSON_Delete(root);
}
static void cjson_add_raw_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddRawToObject(root, "raw", "{}"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cJSON_add_object_should_add_object(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *object = NULL;
cJSON_AddObjectToObject(root, "object");
TEST_ASSERT_NOT_NULL(object = cJSON_GetObjectItemCaseSensitive(root, "object"));
TEST_ASSERT_EQUAL_INT(object->type, cJSON_Object);
cJSON_Delete(root);
}
static void cjson_add_object_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddObjectToObject(NULL, "object"));
TEST_ASSERT_NULL(cJSON_AddObjectToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_object_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddObjectToObject(root, "object"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cJSON_add_array_should_add_array(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *array = NULL;
cJSON_AddArrayToObject(root, "array");
TEST_ASSERT_NOT_NULL(array = cJSON_GetObjectItemCaseSensitive(root, "array"));
TEST_ASSERT_EQUAL_INT(array->type, cJSON_Array);
cJSON_Delete(root);
}
static void cjson_add_array_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddArrayToObject(NULL, "array"));
TEST_ASSERT_NULL(cJSON_AddArrayToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_array_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddArrayToObject(root, "array"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(cjson_add_null_should_add_null);
RUN_TEST(cjson_add_null_should_fail_with_null_pointers);
RUN_TEST(cjson_add_null_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_true_should_add_true);
RUN_TEST(cjson_add_true_should_fail_with_null_pointers);
RUN_TEST(cjson_add_true_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_false_should_add_false);
RUN_TEST(cjson_add_false_should_fail_with_null_pointers);
RUN_TEST(cjson_add_false_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_bool_should_add_bool);
RUN_TEST(cjson_add_bool_should_fail_with_null_pointers);
RUN_TEST(cjson_add_bool_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_number_should_add_number);
RUN_TEST(cjson_add_number_should_fail_with_null_pointers);
RUN_TEST(cjson_add_number_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_string_should_add_string);
RUN_TEST(cjson_add_string_should_fail_with_null_pointers);
RUN_TEST(cjson_add_string_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_raw_should_add_raw);
RUN_TEST(cjson_add_raw_should_fail_with_null_pointers);
RUN_TEST(cjson_add_raw_should_fail_on_allocation_failure);
RUN_TEST(cJSON_add_object_should_add_object);
RUN_TEST(cjson_add_object_should_fail_with_null_pointers);
RUN_TEST(cjson_add_object_should_fail_on_allocation_failure);
RUN_TEST(cJSON_add_array_should_add_array);
RUN_TEST(cjson_add_array_should_fail_with_null_pointers);
RUN_TEST(cjson_add_array_should_fail_on_allocation_failure);
return UNITY_END();
}

View File

@@ -1,97 +0,0 @@
/*
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 "common.h"
CJSON_PUBLIC(void) reset(cJSON *item)
{
if ((item != NULL) && (item->child != NULL))
{
cJSON_Delete(item->child);
}
if ((item->valuestring != NULL) && !(item->type & cJSON_IsReference))
{
global_hooks.deallocate(item->valuestring);
}
if ((item->string != NULL) && !(item->type & cJSON_StringIsConst))
{
global_hooks.deallocate(item->string);
}
memset(item, 0, sizeof(cJSON));
}
CJSON_PUBLIC(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(""));
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;
}

View File

@@ -25,8 +25,79 @@
#include "../cJSON.c"
CJSON_PUBLIC(void) reset(cJSON *item);
CJSON_PUBLIC(char*) read_file(const char *filename);
void reset(cJSON *item);
void reset(cJSON *item) {
if ((item != NULL) && (item->child != NULL))
{
cJSON_Delete(item->child);
}
if ((item->valuestring != NULL) && !(item->type & cJSON_IsReference))
{
global_hooks.deallocate(item->valuestring);
}
if ((item->string != NULL) && !(item->type & cJSON_StringIsConst))
{
global_hooks.deallocate(item->string);
}
memset(item, 0, sizeof(cJSON));
}
char* read_file(const char *filename);
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(""));
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;
}
/* assertion helper macros */
#define assert_has_type(item, item_type) TEST_ASSERT_BITS_MESSAGE(0xFF, item_type, item->type, "Item doesn't have expected type.")

View File

@@ -1,8 +1,8 @@
{
"name": "Jack (\"Bee\") Nimble",
"format": {"type": "rect",
"width": 1920,
"height": 1080,
"name": "Jack (\"Bee\") Nimble",
"format": {"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,"frame rate": 24
}
}

View File

@@ -6,7 +6,7 @@
"width": 500,
"height": 500
},
"image": {
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
@@ -23,4 +23,4 @@
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
}}

View File

@@ -1,5 +1,5 @@
{"web-app": {
"servlet": [
"servlet": [
{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
@@ -55,7 +55,7 @@
{
"servlet-name": "cofaxAdmin",
"servlet-class": "org.cofax.cds.AdminServlet"},
{
"servlet-name": "fileServlet",
"servlet-class": "org.cofax.cds.FileServlet"},
@@ -82,7 +82,7 @@
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"}}}

View File

@@ -80,5 +80,12 @@
"doc": { "foo": ["bar"] },
"patch": [ { "op": "add", "path": "/foo/-", "value": ["abc", "def"] }],
"expected": {"foo": ["bar", ["abc", "def"]] }
}
},
{
"comment": "15",
"doc": {"foo": {"bar": 1}},
"patch": [{"op": "add", "path": "/foo/bar/baz", "value": "5"}],
"error": "attempting to add to subfield of non-object"
}
]

View File

@@ -202,6 +202,11 @@
"patch": [{"op": "replace", "path": "", "value": {"baz": "qux"}}],
"expected": {"baz": "qux"} },
{ "comment": "test replace with missing parent key should fail",
"doc": {"bar": "baz"},
"patch": [{"op": "replace", "path": "/foo/bar", "value": false}],
"error": "replace op should fail with missing parent key" },
{ "comment": "spurious patch properties",
"doc": {"foo": 1},
"patch": [{"op": "test", "path": "/foo", "value": 1, "spurious": 1}],

View File

@@ -1,58 +0,0 @@
if get_option('enable_cjson_tests')
unity_flags = []
if (compiler.get_id() == 'clang') or (compiler.get_id() == 'gcc')
unity_flags += [
'-Wno-switch-enum',
'-Wno-error',
'-fvisibility=default',
'-fno-sanitize=float-divide-by-zero'
]
endif
unity_c_args = []
foreach flag : unity_flags
if compiler.has_argument(flag)
unity_c_args += flag
endif
endforeach
unity = library('unity', 'unity/src/unity.c', c_args: unity_c_args)
common = library('test_common', 'common.c')
cjson_tests = [
'parse_examples',
'parse_number',
'parse_hex4',
'parse_string',
'parse_array',
'parse_object',
'parse_value',
'print_string',
'print_number',
'print_array',
'print_object',
'print_value',
'misc_tests',
'parse_with_opts',
'compare_tests'
]
foreach cjson_test : cjson_tests
exe = executable(cjson_test, cjson_test + '.c', link_with: [common, cjson, unity])
test(cjson_test, exe, workdir: meson.current_source_dir())
endforeach
if get_option('enable_cjson_utils')
cjson_utils_tests = [
'json_patch_tests',
'old_utils_tests',
'misc_utils_tests'
]
foreach cjson_utils_test : cjson_utils_tests
exe = executable(cjson_utils_test, cjson_utils_test + '.c', link_with: [common, cjson_utils, unity, cjson])
test(cjson_utils_test, exe, workdir: meson.current_source_dir())
endforeach
endif
endif

View File

@@ -410,6 +410,123 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
cJSON_Delete(item);
}
static void *failing_realloc(void *pointer, size_t size)
{
(void)size;
(void)pointer;
return NULL;
}
static void ensure_should_fail_on_failed_realloc(void)
{
printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
buffer.buffer = (unsigned char*)malloc(100);
TEST_ASSERT_NOT_NULL(buffer.buffer);
TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
}
static void skip_utf8_bom_should_skip_bom(void)
{
const unsigned char string[] = "\xEF\xBB\xBF{}";
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
buffer.content = string;
buffer.length = sizeof(string);
buffer.hooks = global_hooks;
TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
}
static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
{
const unsigned char string[] = " \xEF\xBB\xBF{}";
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
buffer.content = string;
buffer.length = sizeof(string);
buffer.hooks = global_hooks;
buffer.offset = 1;
TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
}
static void cjson_get_string_value_should_get_a_string(void)
{
cJSON *string = cJSON_CreateString("test");
cJSON *number = cJSON_CreateNumber(1);
TEST_ASSERT_TRUE(cJSON_GetStringValue(string) == string->valuestring);
TEST_ASSERT_NULL(cJSON_GetStringValue(number));
TEST_ASSERT_NULL(cJSON_GetStringValue(NULL));
cJSON_Delete(number);
cJSON_Delete(string);
}
static void cjson_create_string_reference_should_create_a_string_reference(void) {
const char *string = "I am a string!";
cJSON *string_reference = cJSON_CreateStringReference(string);
TEST_ASSERT_TRUE(string_reference->valuestring == string);
TEST_ASSERT_EQUAL_INT(cJSON_IsReference | cJSON_String, string_reference->type);
cJSON_Delete(string_reference);
}
static void cjson_create_object_reference_should_create_an_object_reference(void) {
cJSON *number_reference = NULL;
cJSON *number_object = cJSON_CreateObject();
cJSON *number = cJSON_CreateNumber(42);
const char key[] = "number";
TEST_ASSERT_TRUE(cJSON_IsNumber(number));
TEST_ASSERT_TRUE(cJSON_IsObject(number_object));
cJSON_AddItemToObjectCS(number_object, key, number);
number_reference = cJSON_CreateObjectReference(number);
TEST_ASSERT_TRUE(number_reference->child == number);
TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type);
cJSON_Delete(number_object);
cJSON_Delete(number_reference);
}
static void cjson_create_array_reference_should_create_an_array_reference(void) {
cJSON *number_reference = NULL;
cJSON *number_array = cJSON_CreateArray();
cJSON *number = cJSON_CreateNumber(42);
TEST_ASSERT_TRUE(cJSON_IsNumber(number));
TEST_ASSERT_TRUE(cJSON_IsArray(number_array));
cJSON_AddItemToArray(number_array, number);
number_reference = cJSON_CreateArrayReference(number);
TEST_ASSERT_TRUE(number_reference->child == number);
TEST_ASSERT_EQUAL_INT(cJSON_Array | cJSON_IsReference, number_reference->type);
cJSON_Delete(number_array);
cJSON_Delete(number_reference);
}
static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
{
cJSON *object = cJSON_CreateObject();
cJSON *number = cJSON_CreateNumber(42);
char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
TEST_ASSERT_NOT_NULL(object);
TEST_ASSERT_NOT_NULL(number);
TEST_ASSERT_NOT_NULL(name);
number->string = name;
/* The following should not have a use after free
* that would show up in valgrind or with AddressSanitizer */
cJSON_AddItemToObject(object, number->string, number);
cJSON_Delete(object);
}
int main(void)
{
UNITY_BEGIN();
@@ -425,6 +542,14 @@ int main(void)
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
RUN_TEST(cjson_functions_shouldnt_crash_with_null_pointers);
RUN_TEST(ensure_should_fail_on_failed_realloc);
RUN_TEST(skip_utf8_bom_should_skip_bom);
RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
RUN_TEST(cjson_get_string_value_should_get_a_string);
RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
return UNITY_END();
}

View File

@@ -142,7 +142,7 @@ static void file_test6_should_not_be_parsed(void)
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.");
TEST_ASSERT_EQUAL_PTR_MESSAGE(test6, cJSON_GetErrorPtr(), "Error pointer is incorrect.");
if (test6 != NULL)
{
@@ -179,6 +179,22 @@ static void file_test11_should_be_parsed_and_printed(void)
do_test("test11");
}
static void test12_should_not_be_parsed(void)
{
const char *test12 = "{ \"name\": ";
cJSON *tree = NULL;
tree = cJSON_Parse(test12);
TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse incomplete JSON.");
TEST_ASSERT_EQUAL_PTR_MESSAGE(test12 + strlen(test12), cJSON_GetErrorPtr(), "Error pointer is incorrect.");
if (tree != NULL)
{
cJSON_Delete(tree);
}
}
int main(void)
{
UNITY_BEGIN();
@@ -193,5 +209,6 @@ int main(void)
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);
RUN_TEST(test12_should_not_be_parsed);
return UNITY_END();
}

View File

@@ -40,11 +40,23 @@ static void parse_with_opts_should_handle_empty_strings(void)
{
const char empty_string[] = "";
const char *error_pointer = NULL;
TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, NULL, false));
error_pointer = cJSON_GetErrorPtr();
TEST_ASSERT_EQUAL_INT(0, error_pointer - empty_string);
TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr());
TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, &error_pointer, false));
TEST_ASSERT_EQUAL_INT(0, error_pointer - empty_string);
TEST_ASSERT_EQUAL_PTR(empty_string, error_pointer);
TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr());
}
static void parse_with_opts_should_handle_incomplete_json(void)
{
const char json[] = "{ \"name\": ";
const char *parse_end = NULL;
TEST_ASSERT_NULL(cJSON_ParseWithOpts(json, &parse_end, false));
TEST_ASSERT_EQUAL_PTR(json + strlen(json), parse_end);
TEST_ASSERT_EQUAL_PTR(json + strlen(json), cJSON_GetErrorPtr());
}
static void parse_with_opts_should_require_null_if_requested(void)
@@ -65,18 +77,36 @@ static void parse_with_opts_should_return_parse_end(void)
cJSON *item = cJSON_ParseWithOpts(json, &parse_end, false);
TEST_ASSERT_NOT_NULL(item);
TEST_ASSERT_EQUAL_INT(2, parse_end - json);
TEST_ASSERT_EQUAL_PTR(json + 2, parse_end);
cJSON_Delete(item);
}
static void parse_with_opts_should_parse_utf8_bom(void)
{
cJSON *with_bom = NULL;
cJSON *without_bom = NULL;
with_bom = cJSON_ParseWithOpts("\xEF\xBB\xBF{}", NULL, true);
TEST_ASSERT_NOT_NULL(with_bom);
without_bom = cJSON_ParseWithOpts("{}", NULL, true);
TEST_ASSERT_NOT_NULL(with_bom);
TEST_ASSERT_TRUE(cJSON_Compare(with_bom, without_bom, true));
cJSON_Delete(with_bom);
cJSON_Delete(without_bom);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(parse_with_opts_should_handle_null);
RUN_TEST(parse_with_opts_should_handle_empty_strings);
RUN_TEST(parse_with_opts_should_handle_incomplete_json);
RUN_TEST(parse_with_opts_should_require_null_if_requested);
RUN_TEST(parse_with_opts_should_return_parse_end);
RUN_TEST(parse_with_opts_should_parse_utf8_bom);
return UNITY_END();
}

258
tests/readme_examples.c Normal file
View File

@@ -0,0 +1,258 @@
/*
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 "common.h"
static const char *json = "{\n\
\t\"name\":\t\"Awesome 4K\",\n\
\t\"resolutions\":\t[{\n\
\t\t\t\"width\":\t1280,\n\
\t\t\t\"height\":\t720\n\
\t\t}, {\n\
\t\t\t\"width\":\t1920,\n\
\t\t\t\"height\":\t1080\n\
\t\t}, {\n\
\t\t\t\"width\":\t3840,\n\
\t\t\t\"height\":\t2160\n\
\t\t}]\n\
}";
static char* create_monitor(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *name = NULL;
cJSON *resolutions = NULL;
cJSON *resolution = NULL;
cJSON *width = NULL;
cJSON *height = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (monitor == NULL)
{
goto end;
}
name = cJSON_CreateString("Awesome 4K");
if (name == NULL)
{
goto end;
}
/* after creation was successful, immediately add it to the monitor,
* thereby transfering ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
resolutions = cJSON_CreateArray();
if (resolutions == NULL)
{
goto end;
}
cJSON_AddItemToObject(monitor, "resolutions", resolutions);
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
resolution = cJSON_CreateObject();
if (resolution == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
width = cJSON_CreateNumber(resolution_numbers[index][0]);
if (width == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "width", width);
height = cJSON_CreateNumber(resolution_numbers[index][1]);
if (height == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "height", height);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
static char *create_monitor_with_helpers(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *resolutions = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
{
goto end;
}
resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
if (resolutions == NULL)
{
goto end;
}
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
cJSON *resolution = cJSON_CreateObject();
if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
{
goto end;
}
if(cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
}
string = cJSON_Print(monitor);
if (string == NULL) {
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
/* return 1 if the monitor supports full hd, 0 otherwise */
static int supports_full_hd(const char * const monitor)
{
const cJSON *resolution = NULL;
const cJSON *resolutions = NULL;
const cJSON *name = NULL;
int status = 0;
cJSON *monitor_json = cJSON_Parse(monitor);
if (monitor_json == NULL)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
status = 0;
goto end;
}
name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
if (cJSON_IsString(name) && (name->valuestring != NULL))
{
printf("Checking monitor \"%s\"\n", name->valuestring);
}
resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
cJSON_ArrayForEach(resolution, resolutions)
{
cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
{
status = 0;
goto end;
}
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
{
status = 1;
goto end;
}
}
end:
cJSON_Delete(monitor_json);
return status;
}
static void create_monitor_should_create_a_monitor(void)
{
char *monitor = create_monitor();
TEST_ASSERT_EQUAL_STRING(monitor, json);
free(monitor);
}
static void create_monitor_with_helpers_should_create_a_monitor(void)
{
char *monitor = create_monitor_with_helpers();
TEST_ASSERT_EQUAL_STRING(json, monitor);
free(monitor);
}
static void supports_full_hd_should_check_for_full_hd_support(void)
{
static const char *monitor_without_hd = "{\n\
\t\t\"name\": \"lame monitor\",\n\
\t\t\"resolutions\":\t[{\n\
\t\t\t\"width\":\t640,\n\
\t\t\t\"height\":\t480\n\
\t\t}]\n\
}";
TEST_ASSERT(supports_full_hd(json));
TEST_ASSERT_FALSE(supports_full_hd(monitor_without_hd));
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(create_monitor_should_create_a_monitor);
RUN_TEST(create_monitor_with_helpers_should_create_a_monitor);
RUN_TEST(supports_full_hd_should_check_for_full_hd_support);
return UNITY_END();
}

View File

@@ -18,7 +18,9 @@ install:
script:
- cd test && rake ci
- make -s
- make -s DEBUG=-m32
- make -s DEBUG=-m32 #32-bit architecture with 64-bit support
- make -s DEBUG=-m32 UNITY_SUPPORT_64= #32-bit build without 64-bit types
- make -s UNITY_INCLUDE_DOUBLE= # without double
- cd ../extras/fixture/test && rake ci
- make -s default noStdlibMalloc
- make -s C89

View File

@@ -118,6 +118,17 @@ Another way of calling TEST_ASSERT_EQUAL_INT
Asserts that the actual value is within plus or minus delta of the expected value. This also comes in
size specific variants.
TEST_ASSERT_GREATER_THAN(threshold, actual)
Asserts that the actual value is greater than the threshold. This also comes in size specific variants.
TEST_ASSERT_LESS_THAN(threshold, actual)
Asserts that the actual value is less than the threshold. This also comes in size specific variants.
Arrays
------

View File

@@ -172,7 +172,7 @@ class UnityModuleGenerator
when 'camel' then part1
when 'snake' then part1.downcase
when 'caps' then part1.upcase
else part1.downcase
else part1
end
else
case (@options[:naming])
@@ -180,7 +180,7 @@ class UnityModuleGenerator
when 'camel' then part1 + part2
when 'snake' then part1.downcase + '_' + part2.downcase
when 'caps' then part1.upcase + '_' + part2.upcase
else part1.downcase + '_' + part2.downcase
else part1 + '_' + part2
end
end
end
@@ -290,7 +290,7 @@ if $0 == __FILE__
' -n"camel" sets the file naming convention.',
' bumpy - BumpyCaseFilenames.',
' camel - camelCaseFilenames.',
' snake - snake_case_filenames. (DEFAULT)',
' snake - snake_case_filenames.',
' caps - CAPS_CASE_FILENAMES.',
' -u update subversion too (requires subversion command line)',
' -y"my.yml" selects a different yaml config file for module generation',

View File

@@ -119,7 +119,7 @@ class UnityTestRunnerGenerator
source_index = 0
tests_and_line_numbers.size.times do |i|
source_lines[source_index..-1].each_with_index do |line, index|
next unless line =~ /#{tests_and_line_numbers[i][:test]}/
next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/
source_index += index
tests_and_line_numbers[i][:line_number] = source_index + 1
break
@@ -157,6 +157,9 @@ class UnityTestRunnerGenerator
output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
create_runtest(output, mocks)
output.puts("\n/*=======Automagically Detected Files To Include=====*/")
output.puts('#ifdef __WIN32__')
output.puts('#define UNITY_INCLUDE_SETUP_STUBS')
output.puts('#endif')
output.puts("#include \"#{@options[:framework]}.h\"")
output.puts('#include "cmock.h"') unless mocks.empty?
output.puts('#include <setjmp.h>')
@@ -235,22 +238,36 @@ class UnityTestRunnerGenerator
end
def create_suite_setup(output)
return if @options[:suite_setup].nil?
output.puts("\n/*=======Suite Setup=====*/")
output.puts('static void suite_setup(void)')
output.puts('{')
output.puts(@options[:suite_setup])
if @options[:suite_setup].nil?
# New style, call suiteSetUp() if we can use weak symbols
output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
output.puts(' suiteSetUp();')
output.puts('#endif')
else
# Old style, C code embedded in the :suite_setup option
output.puts(@options[:suite_setup])
end
output.puts('}')
end
def create_suite_teardown(output)
return if @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])
if @options[:suite_teardown].nil?
# New style, call suiteTearDown() if we can use weak symbols
output.puts('#if defined(UNITY_WEAK_ATTRIBUTE) || defined(UNITY_WEAK_PRAGMA)')
output.puts(' return suiteTearDown(num_failures);')
output.puts('#else')
output.puts(' return num_failures;')
output.puts('#endif')
else
# Old style, C code embedded in the :suite_teardown option
output.puts(@options[:suite_teardown])
end
output.puts('}')
end
@@ -342,7 +359,7 @@ class UnityTestRunnerGenerator
output.puts("int #{main_name}(void)")
output.puts('{')
end
output.puts(' suite_setup();') unless @options[:suite_setup].nil?
output.puts(' suite_setup();')
output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
if @options[:use_param_tests]
tests.each do |test|
@@ -357,7 +374,7 @@ class UnityTestRunnerGenerator
end
output.puts
output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
output.puts(" return #{@options[:suite_teardown].nil? ? '' : 'suite_teardown'}(UnityEnd());")
output.puts(" return suite_teardown(UnityEnd());")
output.puts('}')
end

0
tests/unity/auto/stylize_as_junit.rb Normal file → Executable file
View File

View File

@@ -290,6 +290,60 @@ Asserts the specified bit of the `actual` parameter is high.
Asserts the specified bit of the `actual` parameter is low.
### Integer Less Than / Greater Than
These assertions verify that the `actual` parameter is less than or greater
than `threshold` (exclusive). For example, if the threshold value is 0 for the
greater than assertion will fail if it is 0 or less.
##### `TEST_ASSERT_GREATER_THAN (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_INT (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_INT8 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_INT16 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_INT32 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_UINT (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_UINT8 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_UINT16 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_UINT32 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_HEX8 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_HEX16 (threshold, actual)`
##### `TEST_ASSERT_GREATER_THAN_HEX32 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_INT (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_INT8 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_INT16 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_INT32 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_UINT (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_UINT8 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_UINT16 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_UINT32 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_HEX8 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_HEX16 (threshold, actual)`
##### `TEST_ASSERT_LESS_THAN_HEX32 (threshold, actual)`
### Integer Ranges (of all sizes)

View File

@@ -79,18 +79,7 @@ _Example:_
#define UNITY_EXCLUDE_LIMITS_H
##### `UNITY_EXCLUDE_SIZEOF`
The third and final attempt to guess your types is to use the `sizeof()`
operator. Even if the first two options don't work, this one covers most cases.
There _is_ a rare compiler or two out there that doesn't support sizeof() in the
preprocessing stage, though. For these, you have the ability to disable this
feature as well.
_Example:_
#define UNITY_EXCLUDE_SIZEOF
If you've disabled all of the automatic options above, you're going to have to
If you've disabled both of the automatic options above, you're going to have to
do the configuration yourself. Don't worry. Even this isn't too bad... there are
just a handful of defines that you are going to specify if you don't like the
defaults.
@@ -127,7 +116,7 @@ _Example:_
#define UNITY_POINTER_WIDTH 64
##### `UNITY_INCLUDE_64`
##### `UNITY_SUPPORT_64`
Unity will automatically include 64-bit support if it auto-detects it, or if
your `int`, `long`, or pointer widths are greater than 32-bits. Define this to
@@ -136,7 +125,7 @@ can be a significant size and speed impact to enabling 64-bit support on small
targets, so don't define it if you don't need it.
_Example:_
#define UNITY_INCLUDE_64
#define UNITY_SUPPORT_64
### Floating Point Types
@@ -170,24 +159,20 @@ _Example:_
#define UNITY_INCLUDE_DOUBLE
##### `UNITY_FLOAT_VERBOSE`
##### `UNITY_DOUBLE_VERBOSE`
##### `UNITY_EXCLUDE_FLOAT_PRINT`
Unity aims for as small of a footprint as possible and avoids most standard
library calls (some embedded platforms don't have a standard library!). Because
library calls (some embedded platforms dont have a standard library!). Because
of this, its routines for printing integer values are minimalist and hand-coded.
To keep Unity universal, though, we chose to _not_ develop our own floating
point print routines. Instead, the display of floating point values during a
failure are optional. By default, Unity will not print the actual results of
floating point assertion failure. So a failed assertion will produce a message
like `"Values Not Within Delta"`. If you would like verbose failure messages for
floating point assertions, use these options to give more explicit failure
messages (e.g. `"Expected 4.56 Was 4.68"`). Note that this feature requires the
use of `sprintf` so might not be desirable in all cases.
Therefore, the display of floating point values during a failure are optional.
By default, Unity will print the actual results of floating point assertion
failure (e.g. ”Expected 4.56 Was 4.68”). To not include this extra support, you
can use this define to instead respond to a failed assertion with a message like
Values Not Within Delta. If you would like verbose failure messages for floating
point assertions, use these options to give more explicit failure messages.
_Example:_
#define UNITY_DOUBLE_VERBOSE
#define UNITY_EXCLUDE_FLOAT_PRINT
##### `UNITY_FLOAT_TYPE`
@@ -277,25 +262,32 @@ will declare an instance of your function by default. If you want to disable
this behavior, add `UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION`.
##### `UNITY_SUPPORT_WEAK`
##### `UNITY_WEAK_ATTRIBUTE`
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:
##### `UNITY_WEAK_PRAGMA`
##### `UNITY_NO_WEAK`
For some targets, Unity can make the otherwise required setUp() and tearDown()
functions optional. This is a nice convenience for test writers since setUp and
tearDown dont often actually do anything. If youre using gcc or clang, this
option is automatically defined for you. Other compilers can also support this
behavior, if they support a C feature called weak functions. A weak function is
a function that is compiled into your executable unless a non-weak version of
the same function is defined elsewhere. If a non-weak version is found, the weak
version is ignored as if it never existed. If your compiler supports this feature,
you can let Unity know by defining UNITY_WEAK_ATTRIBUTE or UNITY_WEAK_PRAGMA as
the function attributes that would need to be applied to identify a function as
weak. If your compiler lacks support for weak functions, you will always need to
define setUp and tearDown functions (though they can be and often will be just
empty). You can also force Unity to NOT use weak functions by defining
UNITY_NO_WEAK. The most common options for this feature are:
_Example:_
#define UNITY_SUPPORT_WEAK weak
#define UNITY_SUPPORT_WEAK __attribute__((weak))
#define UNITY_WEAK_ATTRIBUTE weak
#define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
#define UNITY_WEAK_PRAGMA
#define UNITY_NO_WEAK
##### `UNITY_PTR_ATTRIBUTE`
@@ -309,6 +301,51 @@ _Example:_
#define UNITY_PTR_ATTRIBUTE near
##### `UNITY_PRINT_EOL`
By default, Unity outputs \n at the end of each line of output. This is easy
to parse by the scripts, by Ceedling, etc, but it might not be ideal for YOUR
system. Feel free to override this and to make it whatever you wish.
_Example:_
#define UNITY_PRINT_EOL { UNITY_OUTPUT_CHAR('\r'); UNITY_OUTPUT_CHAR('\n') }
##### `UNITY_EXCLUDE_DETAILS`
This is an option for if you absolutely must squeeze every byte of memory out of
your system. Unity stores a set of internal scratchpads which are used to pass
extra detail information around. It's used by systems like CMock in order to
report which function or argument flagged an error. If you're not using CMock and
you're not using these details for other things, then you can exclude them.
_Example:_
#define UNITY_EXCLUDE_DETAILS
##### `UNITY_EXCLUDE_SETJMP`
If your embedded system doesn't support the standard library setjmp, you can
exclude Unity's reliance on this by using this define. This dropped dependence
comes at a price, though. You will be unable to use custom helper functions for
your tests, and you will be unable to use tools like CMock. Very likely, if your
compiler doesn't support setjmp, you wouldn't have had the memory space for those
things anyway, though... so this option exists for those situations.
_Example:_
#define UNITY_EXCLUDE_SETJMP
##### `UNITY_OUTPUT_COLOR`
If you want to add color using ANSI escape codes you can use this define.
t
_Example:_
#define UNITY_OUTPUT_COLOR
## Getting Into The Guts
There will be cases where the options above aren't quite going to get everything

View File

@@ -124,7 +124,7 @@ demonstrates using a Ruby hash.
##### `:includes`
This option specifies an array of file names to be ?#include?'d at the top of
This option specifies an array of file names to be `#include`'d at the top of
your runner C file. You might use it to reference custom types or anything else
universally needed in your generated runners.
@@ -133,11 +133,23 @@ universally needed in your generated runners.
Define this option with C code to be executed _before any_ test cases are run.
Alternatively, if your C compiler supports weak symbols, you can leave this
option unset and instead provide a `void suiteSetUp(void)` function in your test
suite. The linker will look for this symbol and fall back to a Unity-provided
stub if it is not found.
##### `:suite_teardown`
Define this option with C code to be executed ?after all?test cases have
finished.
Define this option with C code to be executed _after all_ test cases have
finished. An integer variable `num_failures` is available for diagnostics.
The code should end with a `return` statement; the value returned will become
the exit code of `main`. You can normally just return `num_failures`.
Alternatively, if your C compiler supports weak symbols, you can leave this
option unset and instead provide a `int suiteTearDown(int num_failures)`
function in your test suite. The linker will look for this symbol and fall
back to a Unity-provided stub if it is not found.
##### `:enforce_strict_ordering`

View File

@@ -201,10 +201,12 @@
* `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() */
/* #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) */
/* #define UNITY_OUTPUT_CHAR_HEADER_DECLARATION RS232_putc(int) */
/* #define UNITY_OUTPUT_FLUSH() RS232_flush() */
/* #define UNITY_OUTPUT_FLUSH_HEADER_DECLARATION RS232_flush(void) */
/* #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

View File

@@ -53,7 +53,7 @@ module RakefileHelpers
defines = if $cfg['compiler']['defines']['items'].nil?
''
else
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'])
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'] + ['UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)'])
end
options = squash('', $cfg['compiler']['options'])
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])

View File

@@ -6,6 +6,7 @@ endif
CFLAGS += -std=c99 -pedantic -Wall -Wextra -Werror
CFLAGS += $(DEBUG)
DEFINES = -D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar
DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)
SRC = ../src/unity_fixture.c \
../../../src/unity.c \
unity_fixture_Test.c \

View File

@@ -1,2 +1,2 @@
120
122

View File

@@ -1,2 +1,2 @@
2.4.1
2.4.3

View File

@@ -4,6 +4,7 @@
[Released under MIT License. Please refer to license.txt for details]
============================================================================ */
#define UNITY_INCLUDE_SETUP_STUBS
#include "unity.h"
#include <stddef.h>
@@ -19,14 +20,24 @@ void UNITY_OUTPUT_CHAR(int);
struct UNITY_STORAGE_T Unity;
#ifdef UNITY_OUTPUT_COLOR
static const char UnityStrOk[] = "\033[42mOK\033[00m";
static const char UnityStrPass[] = "\033[42mPASS\033[00m";
static const char UnityStrFail[] = "\033[41mFAIL\033[00m";
static const char UnityStrIgnore[] = "\033[43mIGNORE\033[00m";
#else
static const char UnityStrOk[] = "OK";
static const char UnityStrPass[] = "PASS";
static const char UnityStrFail[] = "FAIL";
static const char UnityStrIgnore[] = "IGNORE";
#endif
static const char UnityStrNull[] = "NULL";
static const char UnityStrSpacer[] = ". ";
static const char UnityStrExpected[] = " Expected ";
static const char UnityStrWas[] = " Was ";
static const char UnityStrGt[] = " to be greater than ";
static const char UnityStrLt[] = " to be less than ";
static const char UnityStrOrEqual[] = "or equal to ";
static const char UnityStrElement[] = " Element ";
static const char UnityStrByte[] = " Byte ";
static const char UnityStrMemory[] = " Memory Mismatch.";
@@ -81,6 +92,18 @@ void UnityPrint(const char* string)
UNITY_OUTPUT_CHAR('\\');
UNITY_OUTPUT_CHAR('n');
}
#ifdef UNITY_OUTPUT_COLOR
/* print ANSI escape code */
else if (*pch == 27 && *(pch + 1) == '[')
{
while (*pch && *pch != 'm')
{
UNITY_OUTPUT_CHAR(*pch);
pch++;
}
UNITY_OUTPUT_CHAR('m');
}
#endif
/* unprintable characters are shown as codes */
else
{
@@ -235,95 +258,97 @@ void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
/*-----------------------------------------------*/
#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);
*/
/* This function prints a floating-point value in a format similar to
* printf("%.6g"). It can work with either single- or double-precision,
* but for simplicity, it prints only 6 significant digits in either case.
* Printing more than 6 digits accurately is hard (at least in the single-
* precision case) and isn't attempted here. */
void UnityPrintFloat(const UNITY_DOUBLE input_number)
{
UNITY_DOUBLE number;
UNITY_DOUBLE number = input_number;
if (input_number < 0)
/* print minus sign (including for negative zero) */
if (number < 0.0f || (number == 0.0f && 1.0f / number < 0.0f))
{
UNITY_OUTPUT_CHAR('-');
number = -input_number;
} else
{
number = input_number;
number = -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 */
/* handle zero, NaN, and +/- infinity */
if (number == 0.0f) UnityPrint("0");
else if (isnan(number)) UnityPrint("nan");
else if (isinf(number)) UnityPrint("inf");
else
{
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);
int exponent = 0;
int decimals, digits;
UNITY_INT32 n;
char buf[16];
if (fraction_part == 1000000) /* Carry across the decimal point */
/* scale up or down by powers of 10 */
while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; }
while (number < 100000.0f) { number *= 10.0f; exponent--; }
while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; }
while (number > 1000000.0f) { number /= 10.0f; exponent++; }
/* round to nearest integer */
n = ((UNITY_INT32)(number + number) + 1) / 2;
if (n > 999999)
{
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;
n = 100000;
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);
/* determine where to place decimal point */
decimals = (exponent <= 0 && exponent >= -9) ? -exponent : 5;
exponent += decimals;
/* truncate trailing zeroes after decimal point */
while (decimals > 0 && n % 10 == 0)
{
n /= 10;
decimals--;
}
/* build up buffer in reverse order */
digits = 0;
while (n != 0 || digits < decimals + 1)
{
buf[digits++] = (char)('0' + n % 10);
n /= 10;
}
while (digits > 0)
{
if(digits == decimals) UNITY_OUTPUT_CHAR('.');
UNITY_OUTPUT_CHAR(buf[--digits]);
}
/* print exponent if needed */
if (exponent != 0)
{
UNITY_OUTPUT_CHAR('e');
if(exponent < 0)
{
UNITY_OUTPUT_CHAR('-');
exponent = -exponent;
}
else
{
UNITY_OUTPUT_CHAR('+');
}
digits = 0;
while (exponent != 0 || digits < 2)
{
buf[digits++] = (char)('0' + exponent % 10);
exponent /= 10;
}
while (digits > 0)
{
UNITY_OUTPUT_CHAR(buf[--digits]);
}
}
}
}
#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */
@@ -526,6 +551,45 @@ void UnityAssertEqualNumber(const UNITY_INT expected,
}
}
/*-----------------------------------------------*/
void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
const UNITY_INT actual,
const UNITY_COMPARISON_T compare,
const char *msg,
const UNITY_LINE_TYPE lineNumber,
const UNITY_DISPLAY_STYLE_T style)
{
int failed = 0;
RETURN_IF_FAIL_OR_IGNORE;
if (threshold == actual && compare & UNITY_EQUAL_TO) return;
if (threshold == actual) failed = 1;
if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
{
if (actual > threshold && compare & UNITY_SMALLER_THAN) failed = 1;
if (actual < threshold && compare & UNITY_GREATER_THAN) failed = 1;
}
else /* UINT or HEX */
{
if ((UNITY_UINT)actual > (UNITY_UINT)threshold && compare & UNITY_SMALLER_THAN) failed = 1;
if ((UNITY_UINT)actual < (UNITY_UINT)threshold && compare & UNITY_GREATER_THAN) failed = 1;
}
if (failed)
{
UnityTestResultsFailBegin(lineNumber);
UnityPrint(UnityStrExpected);
UnityPrintNumberByStyle(actual, style);
if (compare & UNITY_GREATER_THAN) UnityPrint(UnityStrGt);
if (compare & UNITY_SMALLER_THAN) UnityPrint(UnityStrLt);
if (compare & UNITY_EQUAL_TO) UnityPrint(UnityStrOrEqual);
UnityPrintNumberByStyle(threshold, style);
UnityAddMsgIfSpecified(msg);
UNITY_FAIL_AND_BAIL;
}
}
#define UnityPrintPointlessAndBail() \
{ \
UnityTestResultsFailBegin(lineNumber); \
@@ -1025,7 +1089,7 @@ void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
{
UNITY_UINT32 i = 0;
UNITY_UINT32 j = 0;
const char* exp = NULL;
const char* expd = NULL;
const char* act = NULL;
RETURN_IF_FAIL_OR_IGNORE;
@@ -1048,7 +1112,7 @@ void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
if (flags != UNITY_ARRAY_TO_ARRAY)
{
exp = (const char*)expected;
expd = (const char*)expected;
}
do
@@ -1056,15 +1120,15 @@ void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
act = actual[j];
if (flags == UNITY_ARRAY_TO_ARRAY)
{
exp = ((const char* const*)expected)[j];
expd = ((const char* const*)expected)[j];
}
/* if both pointers not null compare the strings */
if (exp && act)
if (expd && act)
{
for (i = 0; exp[i] || act[i]; i++)
for (i = 0; expd[i] || act[i]; i++)
{
if (exp[i] != act[i])
if (expd[i] != act[i])
{
Unity.CurrentTestFailed = 1;
break;
@@ -1073,7 +1137,7 @@ void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
}
else
{ /* handle case of one pointers being null (if both null, test should pass) */
if (exp != act)
if (expd != act)
{
Unity.CurrentTestFailed = 1;
}
@@ -1087,7 +1151,7 @@ void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
UnityPrint(UnityStrElement);
UnityPrintNumberUnsigned(j);
}
UnityPrintExpectedAndActualStrings(exp, act);
UnityPrintExpectedAndActualStrings(expd, act);
UnityAddMsgIfSpecified(msg);
UNITY_FAIL_AND_BAIL;
}
@@ -1262,17 +1326,6 @@ void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
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)
{

View File

@@ -15,9 +15,43 @@ extern "C"
#include "unity_internals.h"
/*-------------------------------------------------------
* Test Setup / Teardown
*-------------------------------------------------------*/
/* These functions are intended to be called before and after each test. */
void setUp(void);
void tearDown(void);
/* These functions are intended to be called at the beginning and end of an
* entire test suite. suiteTearDown() is passed the number of tests that
* failed, and its return value becomes the exit code of main(). */
void suiteSetUp(void);
int suiteTearDown(int num_failures);
/* If the compiler supports it, the following block provides stub
* implementations of the above functions as weak symbols. Note that on
* some platforms (MinGW for example), weak function implementations need
* to be in the same translation unit they are called from. This can be
* achieved by defining UNITY_INCLUDE_SETUP_STUBS before including unity.h. */
#ifdef UNITY_INCLUDE_SETUP_STUBS
#ifdef UNITY_WEAK_ATTRIBUTE
UNITY_WEAK_ATTRIBUTE void setUp(void) { }
UNITY_WEAK_ATTRIBUTE void tearDown(void) { }
UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { }
UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; }
#elif defined(UNITY_WEAK_PRAGMA)
#pragma weak setUp
void setUp(void) { }
#pragma weak tearDown
void tearDown(void) { }
#pragma weak suiteSetUp
void suiteSetUp(void) { }
#pragma weak suiteTearDown
int suiteTearDown(int num_failures) { return num_failures; }
#endif
#endif
/*-------------------------------------------------------
* Configuration Options
*-------------------------------------------------------
@@ -114,6 +148,71 @@ void tearDown(void);
#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
/* Integer Greater Than/ Less Than (of all sizes) */
#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
/* 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)
@@ -241,6 +340,71 @@ void tearDown(void);
#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 Greater Than/ Less Than (of all sizes) */
#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
@@ -295,7 +459,7 @@ void tearDown(void);
#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message))
#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))

View File

@@ -244,8 +244,8 @@ typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
#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);
#ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION
extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION;
#endif
#endif
@@ -253,22 +253,22 @@ extern void UNITY_OUTPUT_CHAR(int);
#ifdef UNITY_USE_FLUSH_STDOUT
/* We want to use the stdout flush utility */
#include <stdio.h>
#define UNITY_OUTPUT_FLUSH (void)fflush(stdout)
#define UNITY_OUTPUT_FLUSH() (void)fflush(stdout)
#else
/* We've specified nothing, therefore flush should just be ignored */
#define UNITY_OUTPUT_FLUSH
#define UNITY_OUTPUT_FLUSH()
#endif
#else
/* We've defined flush as something else, so 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);
#ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION
extern void UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION;
#endif
#endif
#ifndef UNITY_OUTPUT_FLUSH
#define UNITY_FLUSH_CALL()
#else
#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH
#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH()
#endif
#ifndef UNITY_PRINT_EOL
@@ -299,7 +299,7 @@ extern void UNITY_OUTPUT_FLUSH(void);
* Language Features Available
*-------------------------------------------------------*/
#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
# ifdef __GNUC__ /* includes clang */
# if defined(__GNUC__) || defined(__ghs__) /* __GNUC__ includes clang */
# if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__)
# define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
# endif
@@ -350,6 +350,15 @@ UNITY_DISPLAY_STYLE_UINT = sizeof(unsigned) + UNITY_DISPLAY_RANGE_UINT,
UNITY_DISPLAY_STYLE_UNKNOWN
} UNITY_DISPLAY_STYLE_T;
typedef enum
{
UNITY_EQUAL_TO = 1,
UNITY_GREATER_THAN = 2,
UNITY_GREATER_OR_EQUAL = 2 + UNITY_EQUAL_TO,
UNITY_SMALLER_THAN = 4,
UNITY_SMALLER_OR_EQUAL = 4 + UNITY_EQUAL_TO
} UNITY_COMPARISON_T;
#ifndef UNITY_EXCLUDE_FLOAT
typedef enum UNITY_FLOAT_TRAIT
{
@@ -453,6 +462,13 @@ void UnityAssertEqualNumber(const UNITY_INT expected,
const UNITY_LINE_TYPE lineNumber,
const UNITY_DISPLAY_STYLE_T style);
void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
const UNITY_INT actual,
const UNITY_COMPARISON_T compare,
const char *msg,
const UNITY_LINE_TYPE lineNumber,
const UNITY_DISPLAY_STYLE_T style);
void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
UNITY_INTERNAL_PTR actual,
const UNITY_UINT32 num_elements,
@@ -650,6 +666,54 @@ int UnityTestMatches(void);
#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_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
#define UNITY_TEST_ASSERT_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)
@@ -710,6 +774,18 @@ int UnityTestMatches(void);
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
#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)
@@ -720,6 +796,18 @@ int UnityTestMatches(void);
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
#endif
#ifdef UNITY_EXCLUDE_FLOAT

View File

@@ -14,7 +14,10 @@ CFLAGS += -Wbad-function-cast -Wcast-qual -Wold-style-definition -Wshadow -Wstri
#DEBUG = -O0 -g
CFLAGS += $(DEBUG)
DEFINES = -D UNITY_OUTPUT_CHAR=putcharSpy
DEFINES += -D UNITY_SUPPORT_64 -D UNITY_INCLUDE_DOUBLE
DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\)
DEFINES += $(UNITY_SUPPORT_64) $(UNITY_INCLUDE_DOUBLE)
UNITY_SUPPORT_64 = -D UNITY_SUPPORT_64
UNITY_INCLUDE_DOUBLE = -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

View File

@@ -91,7 +91,7 @@ module RakefileHelpers
defines = if $cfg['compiler']['defines']['items'].nil?
''
else
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + inject_defines)
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + ['UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\)'] + inject_defines)
end
options = squash('', $cfg['compiler']['options'])
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])

View File

@@ -764,8 +764,9 @@ void testNotEqualBitsLow(void)
EXPECT_ABORT_BEGIN
TEST_ASSERT_BITS_LOW(v0, v1);
VERIFY_FAILS_END
}
void testEqualShorts(void)
{
short v0, v1;
@@ -1305,6 +1306,415 @@ void testINT8sNotWithinDeltaAndCustomMessage(void)
VERIFY_FAILS_END
}
//-----------------
void testGreaterThan(void)
{
UNITY_INT v0, v1;
UNITY_INT *p0, *p1;
v0 = 0;
v1 = 1;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN(v0, v1);
TEST_ASSERT_GREATER_THAN(*p0, v1);
TEST_ASSERT_GREATER_THAN(v0, *p1);
TEST_ASSERT_GREATER_THAN(*p0, *p1);
}
void testGreaterThanINT(void)
{
UNITY_INT v0, v1;
UNITY_INT *p0, *p1;
v0 = 302;
v1 = 3334;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_INT(v0, v1);
TEST_ASSERT_GREATER_THAN_INT(*p0, v1);
TEST_ASSERT_GREATER_THAN_INT(v0, *p1);
TEST_ASSERT_GREATER_THAN_INT(*p0, *p1);
}
void testGreaterThanINT8(void)
{
UNITY_INT8 v0, v1;
UNITY_INT8 *p0, *p1;
v0 = -128;
v1 = 127;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_INT8(v0, v1);
TEST_ASSERT_GREATER_THAN_INT8(*p0, v1);
TEST_ASSERT_GREATER_THAN_INT8(v0, *p1);
TEST_ASSERT_GREATER_THAN_INT8(*p0, *p1);
}
void testGreaterThanINT16(void)
{
UNITY_INT16 v0, v1;
UNITY_INT16 *p0, *p1;
v0 = -32768;
v1 = 32767;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_INT16(v0, v1);
TEST_ASSERT_GREATER_THAN_INT16(*p0, v1);
TEST_ASSERT_GREATER_THAN_INT16(v0, *p1);
TEST_ASSERT_GREATER_THAN_INT16(*p0, *p1);
}
void testGreaterThanINT32(void)
{
UNITY_INT32 v0, v1;
UNITY_INT32 *p0, *p1;
v0 = -214783648;
v1 = 214783647;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_INT32(v0, v1);
TEST_ASSERT_GREATER_THAN_INT32(*p0, v1);
TEST_ASSERT_GREATER_THAN_INT32(v0, *p1);
TEST_ASSERT_GREATER_THAN_INT32(*p0, *p1);
}
void testGreaterThanUINT(void)
{
UNITY_UINT v0, v1;
UNITY_UINT *p0, *p1;
v0 = 0;
v1 = 1;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_UINT(v0, v1);
TEST_ASSERT_GREATER_THAN_UINT(*p0, v1);
TEST_ASSERT_GREATER_THAN_UINT(v0, *p1);
TEST_ASSERT_GREATER_THAN_UINT(*p0, *p1);
}
void testGreaterThanUINT8(void)
{
UNITY_UINT8 v0, v1;
UNITY_UINT8 *p0, *p1;
v0 = 0;
v1 = 255;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_UINT8(v0, v1);
TEST_ASSERT_GREATER_THAN_UINT8(*p0, v1);
TEST_ASSERT_GREATER_THAN_UINT8(v0, *p1);
TEST_ASSERT_GREATER_THAN_UINT8(*p0, *p1);
}
void testGreaterThanUINT16(void)
{
UNITY_UINT16 v0, v1;
UNITY_UINT16 *p0, *p1;
v0 = 0;
v1 = 65535;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_UINT16(v0, v1);
TEST_ASSERT_GREATER_THAN_UINT16(*p0, v1);
TEST_ASSERT_GREATER_THAN_UINT16(v0, *p1);
TEST_ASSERT_GREATER_THAN_UINT16(*p0, *p1);
}
void testGreaterThanUINT32(void)
{
UNITY_UINT32 v0, v1;
UNITY_UINT32 *p0, *p1;
v0 = 0;
v1 = 4294967295;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_UINT32(v0, v1);
TEST_ASSERT_GREATER_THAN_UINT32(*p0, v1);
TEST_ASSERT_GREATER_THAN_UINT32(v0, *p1);
TEST_ASSERT_GREATER_THAN_UINT32(*p0, *p1);
}
void testGreaterThanHEX8(void)
{
UNITY_UINT8 v0, v1;
UNITY_UINT8 *p0, *p1;
v0 = 0x00;
v1 = 0xFF;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_HEX8(v0, v1);
TEST_ASSERT_GREATER_THAN_HEX8(*p0, v1);
TEST_ASSERT_GREATER_THAN_HEX8(v0, *p1);
TEST_ASSERT_GREATER_THAN_HEX8(*p0, *p1);
}
void testGreaterThanHEX16(void)
{
UNITY_UINT16 v0, v1;
UNITY_UINT16 *p0, *p1;
v0 = 0x0000;
v1 = 0xFFFF;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_HEX16(v0, v1);
TEST_ASSERT_GREATER_THAN_HEX16(*p0, v1);
TEST_ASSERT_GREATER_THAN_HEX16(v0, *p1);
TEST_ASSERT_GREATER_THAN_HEX16(*p0, *p1);
}
void testGreaterThanHEX32(void)
{
UNITY_UINT32 v0, v1;
UNITY_UINT32 *p0, *p1;
v0 = 0x00000000;
v1 = 0xFFFFFFFF;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_GREATER_THAN_HEX32(v0, v1);
TEST_ASSERT_GREATER_THAN_HEX32(*p0, v1);
TEST_ASSERT_GREATER_THAN_HEX32(v0, *p1);
TEST_ASSERT_GREATER_THAN_HEX32(*p0, *p1);
}
void testNotGreaterThan(void)
{
EXPECT_ABORT_BEGIN
TEST_ASSERT_GREATER_THAN(0, -1);
VERIFY_FAILS_END
}
void testLessThan(void)
{
UNITY_INT v0, v1;
UNITY_INT *p0, *p1;
v0 = 0;
v1 = -1;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN(v0, v1);
TEST_ASSERT_LESS_THAN(*p0, v1);
TEST_ASSERT_LESS_THAN(v0, *p1);
TEST_ASSERT_LESS_THAN(*p0, *p1);
}
void testLessThanINT(void)
{
UNITY_INT v0, v1;
UNITY_INT *p0, *p1;
v0 = 3334;
v1 = 302;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_INT(v0, v1);
TEST_ASSERT_LESS_THAN_INT(*p0, v1);
TEST_ASSERT_LESS_THAN_INT(v0, *p1);
TEST_ASSERT_LESS_THAN_INT(*p0, *p1);
}
void testLessThanINT8(void)
{
UNITY_INT8 v0, v1;
UNITY_INT8 *p0, *p1;
v0 = 127;
v1 = -128;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_INT8(v0, v1);
TEST_ASSERT_LESS_THAN_INT8(*p0, v1);
TEST_ASSERT_LESS_THAN_INT8(v0, *p1);
TEST_ASSERT_LESS_THAN_INT8(*p0, *p1);
}
void testLessThanINT16(void)
{
UNITY_INT16 v0, v1;
UNITY_INT16 *p0, *p1;
v0 = 32767;
v1 = -32768;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_INT16(v0, v1);
TEST_ASSERT_LESS_THAN_INT16(*p0, v1);
TEST_ASSERT_LESS_THAN_INT16(v0, *p1);
TEST_ASSERT_LESS_THAN_INT16(*p0, *p1);
}
void testLessThanINT32(void)
{
UNITY_INT32 v0, v1;
UNITY_INT32 *p0, *p1;
v0 = 214783647;
v1 = -214783648;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_INT32(v0, v1);
TEST_ASSERT_LESS_THAN_INT32(*p0, v1);
TEST_ASSERT_LESS_THAN_INT32(v0, *p1);
TEST_ASSERT_LESS_THAN_INT32(*p0, *p1);
}
void testLessThanUINT(void)
{
UNITY_UINT v0, v1;
UNITY_UINT *p0, *p1;
v0 = 1;
v1 = 0;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_UINT(v0, v1);
TEST_ASSERT_LESS_THAN_UINT(*p0, v1);
TEST_ASSERT_LESS_THAN_UINT(v0, *p1);
TEST_ASSERT_LESS_THAN_UINT(*p0, *p1);
}
void testLessThanUINT8(void)
{
UNITY_UINT8 v0, v1;
UNITY_UINT8 *p0, *p1;
v0 = 255;
v1 = 0;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_UINT8(v0, v1);
TEST_ASSERT_LESS_THAN_UINT8(*p0, v1);
TEST_ASSERT_LESS_THAN_UINT8(v0, *p1);
TEST_ASSERT_LESS_THAN_UINT8(*p0, *p1);
}
void testLessThanUINT16(void)
{
UNITY_UINT16 v0, v1;
UNITY_UINT16 *p0, *p1;
v0 = 65535;
v1 = 0;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_UINT16(v0, v1);
TEST_ASSERT_LESS_THAN_UINT16(*p0, v1);
TEST_ASSERT_LESS_THAN_UINT16(v0, *p1);
TEST_ASSERT_LESS_THAN_UINT16(*p0, *p1);
}
void testLessThanUINT32(void)
{
UNITY_UINT32 v0, v1;
UNITY_UINT32 *p0, *p1;
v0 = 4294967295;
v1 = 0;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_UINT32(v0, v1);
TEST_ASSERT_LESS_THAN_UINT32(*p0, v1);
TEST_ASSERT_LESS_THAN_UINT32(v0, *p1);
TEST_ASSERT_LESS_THAN_UINT32(*p0, *p1);
}
void testLessThanHEX8(void)
{
UNITY_UINT8 v0, v1;
UNITY_UINT8 *p0, *p1;
v0 = 0xFF;
v1 = 0x00;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_HEX8(v0, v1);
TEST_ASSERT_LESS_THAN_HEX8(*p0, v1);
TEST_ASSERT_LESS_THAN_HEX8(v0, *p1);
TEST_ASSERT_LESS_THAN_HEX8(*p0, *p1);
}
void testLessThanHEX16(void)
{
UNITY_UINT16 v0, v1;
UNITY_UINT16 *p0, *p1;
v0 = 0xFFFF;
v1 = 0x0000;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_HEX16(v0, v1);
TEST_ASSERT_LESS_THAN_HEX16(*p0, v1);
TEST_ASSERT_LESS_THAN_HEX16(v0, *p1);
TEST_ASSERT_LESS_THAN_HEX16(*p0, *p1);
}
void testLessThanHEX32(void)
{
UNITY_UINT32 v0, v1;
UNITY_UINT32 *p0, *p1;
v0 = 0xFFFFFFFF;
v1 = 0x00000000;
p0 = &v0;
p1 = &v1;
TEST_ASSERT_LESS_THAN_HEX32(v0, v1);
TEST_ASSERT_LESS_THAN_HEX32(*p0, v1);
TEST_ASSERT_LESS_THAN_HEX32(v0, *p1);
TEST_ASSERT_LESS_THAN_HEX32(*p0, *p1);
}
void testNotLessThan(void)
{
EXPECT_ABORT_BEGIN
TEST_ASSERT_LESS_THAN(0, 1);
VERIFY_FAILS_END
}
//-----------------
void testEqualStrings(void)
{
const char *testString = "foo";
@@ -4056,61 +4466,46 @@ void testFloatPrinting(void)
#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY)
TEST_IGNORE();
#else
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0", 0.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.000000...", 0.000000499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.000001", 0.00000050000005f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.100469499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0", 0.9999995f); /*Rounding to int place*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0", 1.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("7.999999", 7.999999f); /*Not rounding*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000002", 16.000002f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000004", 16.000004f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.000006", 16.000006f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4294967040.0", 4294967040.0f); /*Last full print integer*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.00000050000005f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.100469499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 0.9999995f); /*Rounding to int place*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("7.99999", 7.99999f); /*Not rounding*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0002", 16.0002f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0004", 16.0004f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0006", 16.0006f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("999999", 999999.0f); /*Last full print integer*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0", -0.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.000000...",-0.000000499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.000001", -0.00000050000005f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.100469499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0", -0.9999995f); /*Rounding to int place*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0", -1.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.999999", -7.999999f); /*Not rounding*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000002", -16.000002f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000004", -16.000004f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.000006", -16.000006f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4294967040.0",-4294967040.0f); /*Last full print integer*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.00000050000005f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.100469499f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -0.9999995f); /*Rounding to int place*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.99999", -7.99999f); /*Not rounding*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0002", -16.0002f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0004", -16.0004f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0006", -16.0006f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-999999", -999999.0f); /*Last full print integer*/
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("5.0e+09", 5000000000.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("8.0e+09", 8.0e+09f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("8.3099991e+09", 8309999104.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 1.0e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 10000000000.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("5e+09", 5000000000.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("8e+09", 8.0e+09f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("8.31e+09", 8309999104.0f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 1.0e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000000.0f);
/* Some compilers have trouble with inexact float constants, a float cast works generally */
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00005499e+10", (float)1.000055e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.10000006e+38", (float)1.10000005e+38f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.63529943e+10", 1.63529943e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("3.40282347e+38", 3.40282346638e38f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00005e+10", (float)1.000054e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.1e+38", (float)1.10000005e+38f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.6353e+10", 1.63529943e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("3.40282e+38", 3.40282346638e38f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.0e+10", -1.0e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.40282347e+38",-3.40282346638e38f);
#endif
}
void testFloatPrintingRoundTiesToEven(void)
{
#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY)
TEST_IGNORE();
#else
#ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.007813", 0.0078125f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.976563", 0.9765625f);
#else /* Default to Round ties to even */
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.007182", 0.0071825f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.976562", 0.9765625f);
#endif
TEST_ASSERT_EQUAL_PRINT_FLOATING("-1e+10", -1.0e+10f);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.40282e+38", -3.40282346638e38f);
#endif
}
@@ -4119,105 +4514,69 @@ void testFloatPrintingInfinityAndNaN(void)
#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY)
TEST_IGNORE();
#else
TEST_ASSERT_EQUAL_PRINT_FLOATING("Inf", 1.0f / f_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-Inf", -1.0f / f_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0f / f_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0f / f_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("NaN", 0.0f / f_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0f / f_zero);
#endif
}
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
static void AllFloatPrinting_LessThan32Bits(void)
static void printFloatValue(float f)
{
char expected[18];
union { float f_value; int32_t int_value; } u;
/* Float representations are laid out in integer order, walk up the list */
for (u.f_value = 0.00000050000005f; u.f_value <= 4294967040.0f; u.int_value += 1)
char expected_lower[18];
char expected_higher[18];
startPutcharSpy();
UnityPrintFloat(f);
sprintf(expected, "%.6g", f);
/* We print all NaN's as "nan", not "-nan" */
if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan");
/* Allow for rounding differences in last digit */
double lower = (double)f * 0.9999995;
double higher = (double)f * 1.0000005;
if (isfinite(lower)) sprintf(expected_lower, "%.6g", lower); else strcpy(expected_lower, expected);
if (isfinite(higher)) sprintf(expected_higher, "%.6g", higher); else strcpy(expected_higher, expected);
if (strcmp(expected, getBufferPutcharSpy()) != 0 &&
strcmp(expected_lower, getBufferPutcharSpy()) != 0 &&
strcmp(expected_higher, getBufferPutcharSpy()) != 0)
{
startPutcharSpy();
UnityPrintFloat(u.f_value); /*1.5x as fast as sprintf 5e-7f - 0.01f, 20s vs 30s*/
int len = sprintf(expected, "%.6f", u.f_value);
while (expected[len - 1] == '0' && expected[len - 2] != '.') { len--; }
expected[len] = '\0'; /* delete trailing 0's */
if (strcmp(expected, getBufferPutcharSpy()) != 0)
{
double six_digits = ((double)u.f_value - (uint32_t)u.f_value)*1000000.0;
/* Not a tie (remainder != 0.5) => Can't explain the different strings */
if (six_digits - (uint32_t)six_digits != 0.5)
{
/* Fail with diagnostic printing */
TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, u.f_value);
}
}
}
}
/* Compared to perfect, floats are occasionally rounded wrong. It doesn't affect
* correctness, though. Two examples (of 13 total found during testing):
* Printed: 6.19256349e+20, Exact: 619256348499999981568.0f <= Eliminated by ROUND_TIES_TO_EVEN
* Printed: 2.19012272e+35, Exact: 219012271499999993621766990196637696.0f */
static void AllFloatPrinting_Larger(const float start, const float end)
{
unsigned int wrong = 0;
char expected[18];
union { float f_value; int32_t int_value; } u;
for (u.f_value = start; u.f_value <= end; u.int_value += 1)
{
startPutcharSpy();
UnityPrintFloat(u.f_value); /*Twice as fast as sprintf 2**32-1e12, 10s vs 21s*/
sprintf(expected, "%.8e", u.f_value);
int len = 11 - 1; /* 11th char is 'e' in exponential format */
while (expected[len - 1] == '0' && expected[len - 2] != '.') { len --; }
if (expected[14] != '\0') memmove(&expected[12], &expected[13], 3); /* Two char exponent */
memmove(&expected[len], &expected[11 - 1], sizeof "e+09"); /* 5 char length */
if (strcmp(expected, getBufferPutcharSpy()) != 0)
{
wrong++;
/* endPutcharSpy(); UnityPrint("Expected "); UnityPrint(expected);
UnityPrint(" Was "); UnityPrint(getBufferPutcharSpy()); UNITY_OUTPUT_CHAR('\n'); */
if (wrong > 10 || (wrong > 3 && end <= 1e25f))
TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, u.f_value);
/* Empirical values from the current routine, don't be worse when making changes */
}
/* Fail with diagnostic printing */
TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f);
}
}
#endif
/* Exhaustive testing of all float values we differentiate when printing. Doubles
* are not explored here -- too many. These tests confirm that the routine works
* for all floats > 5e-7, positives only. Off by default due to test time.
* Compares Unity's routine to your sprintf() C lib, tested to pass on 3 platforms.
* Part1 takes a long time, around 3 minutes compiled with -O2
* Runs through all floats from 0.000001 - 2**32, ~300 million values */
void testAllFloatPrintingPart1_LessThan32Bits(void)
void testFloatPrintingRandomSamples(void)
{
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
AllFloatPrinting_LessThan32Bits();
#if !defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) || !defined(USING_OUTPUT_SPY)
TEST_IGNORE();
#else
TEST_IGNORE(); /* Ignore one of three */
#endif
}
union { float f_value; uint32_t int_value; } u;
/* Test takes a long time, around 3.5 minutes compiled with -O2, try ~500 million values */
void testAllFloatPrintingPart2_Larger(void)
{
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
AllFloatPrinting_Larger(4294967296.0f, 1e25f);
#endif
}
/* These values are not covered by the MINSTD generator */
u.int_value = 0x00000000; printFloatValue(u.f_value);
u.int_value = 0x80000000; printFloatValue(u.f_value);
u.int_value = 0x7fffffff; printFloatValue(u.f_value);
u.int_value = 0xffffffff; printFloatValue(u.f_value);
/* Test takes a long time, around 3.5 minutes compiled with -O2, try ~500 million values */
void testAllFloatPrintingPart3_LargerStill(void)
{
#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY)
AllFloatPrinting_Larger(1e25f, 3.40282347e+38f);
uint32_t a = 1;
for(int num_tested = 0; num_tested < 1000000; num_tested++)
{
/* MINSTD pseudo-random number generator */
a = (uint32_t)(((uint64_t)a * 48271u) % 2147483647u);
/* MINSTD does not set the highest bit; test both possibilities */
u.int_value = a; printFloatValue(u.f_value);
u.int_value = a | 0x80000000; printFloatValue(u.f_value);
}
#endif
}
@@ -4893,35 +5252,20 @@ void testDoublePrinting(void)
#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
TEST_IGNORE();
#else
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.10046949999999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4294967295.999999", 4294967295.999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967295.9999995);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 9999999995.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199254740990.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("7.0e+100", 7.0e+100);
TEST_ASSERT_EQUAL_PRINT_FLOATING("3.0e+200", 3.0e+200);
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23456789e+300", 9.23456789e+300);
TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469", 0.10046949999999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967295.999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967295.9999995);
TEST_ASSERT_EQUAL_PRINT_FLOATING("4.29497e+09", 4294967296.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.0072e+15", 9007199254740990.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100);
TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200);
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23457e+300", 9.23456789e+300);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.10046949999999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4294967295.999999", -4294967295.999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.2949673e+09", -4294967295.9999995);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.0e+100", -7.0e+100);
#endif
}
void testDoublePrintingRoundTiesToEven(void)
{
#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
TEST_IGNORE();
#else
#ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00000001e+10", 10000000050.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199245000000.0);
#else /* Default to Round ties to even */
TEST_ASSERT_EQUAL_PRINT_FLOATING("1.0e+10", 10000000050.0);
TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719924e+15", 9007199245000000.0);
#endif
TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469", -0.10046949999999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.999999);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.29497e+09", -4294967295.9999995);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100);
#endif
}
@@ -4930,10 +5274,10 @@ void testDoublePrintingInfinityAndNaN(void)
#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)
TEST_IGNORE();
#else
TEST_ASSERT_EQUAL_PRINT_FLOATING("Inf", 1.0 / d_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-Inf", -1.0 / d_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0 / d_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0 / d_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("NaN", 0.0 / d_zero);
TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0 / d_zero);
#endif
}

6
valgrind.supp Normal file
View File

@@ -0,0 +1,6 @@
{
suppress_ld_on_armv7
Memcheck:Cond
...
obj:*/ld-*.so
}