/* * Copyright (c) 2014 Vojtech Horky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file * Predefined asserts. * * @defgroup asserts Asserts * Predefined asserts you can use with PCUT. * @{ */ #ifndef PCUT_ASSERTS_H_GUARD #define PCUT_ASSERTS_H_GUARD #include <errno.h> /** @def PCUT_CURRENT_FILENAME * Overwrite contents of __FILE__ when printing assertion errors. */ #ifndef PCUT_CURRENT_FILENAME #define PCUT_CURRENT_FILENAME __FILE__ #endif /** @cond devel */ /** Raise assertion error. * * This function immediately terminates current test and executes a tear-down * (if registered). * * @param filename File where the assertion occurred. * @param line Line where the assertion occurred. * @param fmt Printf-like format string. * @param ... Extra arguments. */ void pcut_failed_assertion_fmt(const char *filename, int line, const char *fmt, ...); /** OS-agnostic string comparison. * * @param a First string to compare. * @param b Second string to compare. * @return Whether the strings are equal. */ int pcut_str_equals(const char *a, const char *b); /** OS-agnostic conversion from error code to error description. * * This function ensures that the description stored in @p buffer is * always a nul-terminated string. * * @param error Error code. * @param buffer Where to store the error description. * @param size Size of the buffer. */ void pcut_str_error(int error, char *buffer, int size); /** Raise assertion error (internal version). * * We expect to be always called from PCUT_ASSERTION_FAILED() where * the last argument is empty string to conform to strict ISO C99 * ("ISO C99 requires rest arguments to be used"). * * @param fmt Printf-like format string. * @param ... Extra arguments. */ #define PCUT_ASSERTION_FAILED_INTERNAL(fmt, ...) \ pcut_failed_assertion_fmt(PCUT_CURRENT_FILENAME, __LINE__, fmt, __VA_ARGS__) /** @endcond */ /** Raise assertion error. * * This macro adds current file and line and triggers immediate test * abort (tear-down function of the test suite is run when available). * * @param ... Printf-like arguments. */ #define PCUT_ASSERTION_FAILED(...) \ PCUT_ASSERTION_FAILED_INTERNAL(__VA_ARGS__, "") /** Generic assertion for a boolean expression. * * @param actual Actually obtained (computed) value we wish to test to true. */ #define PCUT_ASSERT_TRUE(actual) \ do { \ if (!(actual)) { \ PCUT_ASSERTION_FAILED("Expected true but got <%s>", \ #actual); \ } \ } while (0) /** Generic assertion for a boolean expression. * * @param actual Actually obtained (computed) value we wish to test to false. */ #define PCUT_ASSERT_FALSE(actual) \ do { \ if ((actual)) { \ PCUT_ASSERTION_FAILED("Expected false but got <%s>", \ #actual); \ } \ } while (0) /** Generic assertion for types where == is defined. * * @param expected Expected (correct) value. * @param actual Actually obtained (computed) value we wish to test. */ #define PCUT_ASSERT_EQUALS(expected, actual) \ do {\ if (!((expected) == (actual))) { \ PCUT_ASSERTION_FAILED("Expected <"#expected "> but got <" #actual ">"); \ } \ } while (0) /** Asserts that given pointer is NULL. * * @param pointer The pointer to be tested. */ #define PCUT_ASSERT_NULL(pointer) \ do { \ const void *pcut_ptr_eval = (pointer); \ if (pcut_ptr_eval != (NULL)) { \ PCUT_ASSERTION_FAILED("Expected <" #pointer "> to be NULL, " \ "instead it points to %p", pcut_ptr_eval); \ } \ } while (0) /** Asserts that given pointer is not NULL. * * Use this function when directly quoting the original pointer variable * does not provide sufficient information. * * @param pointer The pointer to be tested. * @param pointer_name Name of the pointer. */ #define PCUT_ASSERT_NOT_NULL_WITH_NAME(pointer, pointer_name) \ do { \ const void *pcut_ptr_eval = (pointer); \ if (pcut_ptr_eval == (NULL)) { \ PCUT_ASSERTION_FAILED("Pointer <" pointer_name "> ought not to be NULL"); \ } \ } while (0) /** Asserts that given pointer is not NULL. * * @param pointer The pointer to be tested. */ #define PCUT_ASSERT_NOT_NULL(pointer) \ PCUT_ASSERT_NOT_NULL_WITH_NAME(pointer, #pointer) /** Assertion for checking that two integers are equal. * * @param expected Expected (correct) value. * @param actual Actually obtained (computed) value we wish to test. */ #define PCUT_ASSERT_INT_EQUALS(expected, actual) \ do {\ long long pcut_expected_eval = (expected); \ long long pcut_actual_eval = (actual); \ if (pcut_expected_eval != pcut_actual_eval) { \ PCUT_ASSERTION_FAILED("Expected <%lld> but got <%lld> (%s != %s)", \ pcut_expected_eval, pcut_actual_eval, \ #expected, #actual); \ } \ } while (0) /** Assertion for checking that two integers are equal. * * @param expected Expected (correct) value. * @param actual Actually obtained (computed) value we wish to test. */ #define PCUT_ASSERT_UINT_EQUALS(expected, actual) \ do {\ unsigned long long pcut_expected_eval = (expected); \ unsigned long long pcut_actual_eval = (actual); \ if (pcut_expected_eval != pcut_actual_eval) { \ PCUT_ASSERTION_FAILED("Expected <%llu> but got <%llu> (%s != %s)", \ pcut_expected_eval, pcut_actual_eval, \ #expected, #actual); \ } \ } while (0) /** Assertion for checking that two pointers are equal. * * @param expected Expected (correct) value. * @param actual Actually obtained (computed) value we wish to test. */ #define PCUT_ASSERT_PTR_EQUALS(expected, actual) \ do {\ const void *pcut_expected_eval = (expected); \ const void *pcut_actual_eval = (actual); \ if (pcut_expected_eval != pcut_actual_eval) { \ PCUT_ASSERTION_FAILED("Expected '" #actual "' = '" #expected "' = <%p> but got '" #actual "' = <%p>", \ pcut_expected_eval, pcut_actual_eval); \ } \ } while (0) /** Assertion for checking that two doubles are close enough. * * @param expected Expected (correct) value. * @param actual Actually obtained (computed) value we wish to test. * @param epsilon How much the actual value can differ from the expected one. */ #define PCUT_ASSERT_DOUBLE_EQUALS(expected, actual, epsilon) \ do {\ double pcut_expected_eval = (expected); \ double pcut_actual_eval = (actual); \ double pcut_epsilon_eval = (epsilon); \ double pcut_double_diff = pcut_expected_eval - pcut_actual_eval; \ if ((pcut_double_diff < -pcut_epsilon_eval) | (pcut_double_diff > pcut_epsilon_eval)) { \ PCUT_ASSERTION_FAILED("Expected <%lf+-%lf> but got <%lf> (%s != %s)", \ pcut_expected_eval, pcut_epsilon_eval, pcut_actual_eval, \ #expected, #actual); \ } \ } while (0) /** Assertion for checking that two strings (`const char *`) are equal. * * @param expected Expected (correct) value. * @param actual Actually obtained (computed) value we wish to test. */ #define PCUT_ASSERT_STR_EQUALS(expected, actual) \ do {\ const char *pcut_expected_eval = (expected); \ const char *pcut_actual_eval = (actual); \ PCUT_ASSERT_NOT_NULL_WITH_NAME(pcut_expected_eval, #expected); \ PCUT_ASSERT_NOT_NULL_WITH_NAME(pcut_actual_eval, #actual); \ if (!pcut_str_equals(pcut_expected_eval, pcut_actual_eval)) { \ PCUT_ASSERTION_FAILED("Expected <%s> but got <%s> (%s != %s)", \ pcut_expected_eval, pcut_actual_eval, \ #expected, #actual); \ } \ } while (0) /** Assertion for checking that two strings (`const char *`) are equal or both NULL. * * @param expected Expected (correct) value. * @param actual Actually obtained (computed) value we wish to test. */ #define PCUT_ASSERT_STR_EQUALS_OR_NULL(expected, actual) \ do {\ const char *pcut_expected_eval = (expected); \ const char *pcut_actual_eval = (actual); \ int pcut_both_null = (pcut_expected_eval == NULL) && (pcut_actual_eval == NULL); \ int pcut_some_null = (pcut_expected_eval == NULL) || (pcut_actual_eval == NULL); \ if (!pcut_both_null && (pcut_some_null || !pcut_str_equals(pcut_expected_eval, pcut_actual_eval))) { \ PCUT_ASSERTION_FAILED("Expected <%s> but got <%s> (%s != %s)", \ pcut_expected_eval == NULL ? "NULL" : pcut_expected_eval, \ pcut_actual_eval == NULL ? "NULL" : pcut_actual_eval, \ #expected, #actual); \ } \ } while (0) /** Assertion for checking errno-style variables for errors. * * Use this function when directly quoting the original error code does * not provide sufficient information. * * @param expected_value Expected errno error code. * @param expected_quoted Expected error code as a string. * @param actual_value Actual value of the error code. */ #define PCUT_ASSERT_ERRNO_VAL_WITH_NAME(expected_value, expected_quoted, actual_value) \ do {\ int pcut_expected_eval = (expected_value); \ int pcut_actual_eval = (actual_value); \ if (pcut_expected_eval != pcut_actual_eval) { \ char pcut_expected_description[100]; \ char pcut_actual_description[100]; \ pcut_str_error(pcut_expected_eval, pcut_expected_description, 100); \ pcut_str_error(pcut_actual_eval, pcut_actual_description, 100); \ PCUT_ASSERTION_FAILED("Expected error %d (%s, %s) but got error %d (%s)", \ pcut_expected_eval, expected_quoted, \ pcut_expected_description, \ pcut_actual_eval, pcut_actual_description); \ } \ } while (0) /** Assertion for checking errno-style variables for errors. * * @param expected Expected errno error code. * @param actual Actual value of the error code. */ #define PCUT_ASSERT_ERRNO_VAL(expected, actual) \ PCUT_ASSERT_ERRNO_VAL_WITH_NAME(expected, #expected, actual) /** Assertion for checking errno variable for errors. * * @param expected Expected errno error code. */ #define PCUT_ASSERT_ERRNO(expected) \ PCUT_ASSERT_ERRNO_VAL_WITH_NAME(expected, #expected, (errno)) /** * @} */ #endif