diff --git a/.gitignore b/.gitignore index 211683a8..6da0ca6a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ Makefile CMakeFiles CMakeCache.txt !unityConfig.cmake +*~ diff --git a/docs/UnityAssertionsReference.md b/docs/UnityAssertionsReference.md index 0a0e51b6..767fc66b 100644 --- a/docs/UnityAssertionsReference.md +++ b/docs/UnityAssertionsReference.md @@ -222,6 +222,50 @@ This can be useful for outputting `INFO` messages into the Unity output stream without actually ending the test. Like pass and fail messages, it will be output with the filename and line number. +#### `TEST_PROTECT_NORETURN()` + +This macro prepares an environment to test a function that is declared `noreturn`. + +``` + if(TEST_PROTECT_NORETURN()){ + } +``` + +The function `mock_go_elsewhere()` would use `TEST_DO_NOT_RETURN()` +instead of returning. + +#### `TEST_NOT_RETURNING(call)` + +Calls a function, and the test fails if the function returns. +Instead, the called function should use `TEST_DO_NOT_RETURN()`. + +``` + /* prepare the test here */ + TEST_NOT_RETURNING(go_elsewhere(42)); +``` + +Note: this can be used to call a mock function (that uses +`TEST_NOT_RETURNING()` instead of returning), or an actual function +that effectively does not return. In the later case, the control +won't resume to the caller test (unless there's a failure), so the +test should expect that and have set up things accordingly. + +This cannot be used if `UNITY_EXCLUDE_SETJMP_H` is defined. + +#### `TEST_DO_NOT_RETURN()` + +Aborts the execution, and resume after the current +`TEST_NOT_RETURNING()`, successfully. + +This should be used in mock functions declared `noreturn` instead of +returning (explicitely or implicitely). + +Note: actual functions that don't return will go wherever they shoud +go and it's assumed this is handled in the test. These macros are +intended to be used by mock functions. + +This cannot be used if `UNITY_EXCLUDE_SETJMP_H` is defined. + ### Boolean #### `TEST_ASSERT (condition)` diff --git a/src/unity_internals.h b/src/unity_internals.h index 65938ff7..093e23da 100644 --- a/src/unity_internals.h +++ b/src/unity_internals.h @@ -518,6 +518,7 @@ struct UNITY_STORAGE_T #endif #ifndef UNITY_EXCLUDE_SETJMP_H jmp_buf AbortFrame; + jmp_buf NoReturnFrame; #endif }; @@ -788,6 +789,28 @@ extern const char UnityStrErrShorthand[]; #endif #endif +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT_NORETURN() (setjmp(Unity.NoReturnFrame) == 0) +#define TEST_DO_NOT_RETURN() longjmp(Unity.NoReturnFrame, 1) + +/* +TEST_NOT_RETURNING(call) +This macro uses TEST_PROTECT_NORETURN to protect the call. +If the call returns, then the test fails. +*/ +#define TEST_NOT_RETURNING(call) \ + if (TEST_PROTECT_NORETURN()) \ + { \ + call; \ + UnityFail("Call Was Expected Not To Return: " #call, __LINE__); \ + } + +#else +#define TEST_PROTECT_NORETURN() _Static_assert(false, "TEST_PROTECT_NORETURN() cannot be used when UNITY_EXCLUDE_SETJMP_H is defined" +#define TEST_DO_NOT_RETURN() _Static_assert(false, "TEST_DO_NOT_RETURN() cannot be used when UNITY_EXCLUDE_SETJMP_H is defined" +#define TEST_NOT_RETURNING(call) _Static_assert(false, "TEST_NOT_RETURNING(call) cannot be used when UNITY_EXCLUDE_SETJMP_H is defined" +#endif + /* Automatically enable variadic macros support, if it not enabled before */ #ifndef UNITY_SUPPORT_VARIADIC_MACROS #ifdef __STDC_VERSION__