/* * Copyright (c) 2013, Red Hat Inc. * * 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 names of contributors to this software may not be * used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "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 * COPYRIGHT OWNER OR CONTRIBUTORS 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. * * Author: Stef Walter */ #ifndef TEST_H_ #define TEST_H_ #if !defined(__cplusplus) && (__GNUC__ > 2) #define GNUC_PRINTF(x, y) __attribute__((__format__(__printf__, x, y))) #else #define GNUC_PRINTF(x, y) #endif /* For detecting clang features */ #ifndef __has_feature #define __has_feature(x) 0 #endif #ifndef CLANG_ANALYZER_NORETURN #if __has_feature(attribute_analyzer_noreturn) #define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) #else #define CLANG_ANALYZER_NORETURN #endif #endif #ifndef TEST_SOURCE #include #ifdef assert_not_reached #undef assert_not_reached #endif #ifdef assert #undef assert #endif #define assert(expr) \ assert_true(expr) #define assert_true(expr) \ do { if (expr) ; else \ test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed (%s)", #expr); \ } while (0) #define assert_false(expr) \ do { if (expr) \ test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed (!(%s))", #expr); \ } while (0) #define assert_fail(msg, detail) \ do { const char *__s = (detail); \ test_fail (__FILE__, __LINE__, __FUNCTION__, "%s%s%s", (msg), __s ? ": ": "", __s ? __s : ""); \ } while (0) #define assert_not_reached(msg) \ do { \ test_fail (__FILE__, __LINE__, __FUNCTION__, "code should not be reached"); \ } while (0) #define assert_ptr_not_null(ptr) \ do { if ((ptr) != NULL) ; else \ test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed (%s != NULL)", #ptr); \ } while (0) #define assert_num_cmp(a1, cmp, a2) \ do { unsigned long __n1 = (a1); \ unsigned long __n2 = (a2); \ if (__n1 cmp __n2) ; else \ test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed (%s %s %s): (%lu %s %lu)", \ #a1, #cmp, #a2, __n1, #cmp, __n2); \ } while (0) #define assert_num_eq(a1, a2) \ assert_num_cmp(a1, ==, a2) #define assert_str_cmp(a1, cmp, a2) \ do { const char *__s1 = (a1); \ const char *__s2 = (a2); \ if (__s1 && __s2 && strcmp (__s1, __s2) cmp 0) ; else \ test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed (%s %s %s): (%s %s %s)", \ #a1, #cmp, #a2, __s1 ? __s1 : "(null)", #cmp, __s2 ? __s2 : "(null)"); \ } while (0) #define assert_str_eq(a1, a2) \ assert_str_cmp(a1, ==, a2) #define assert_ptr_eq(a1, a2) \ do { const void *__p1 = (a1); \ const void *__p2 = (a2); \ if (__p1 == __p2) ; else \ test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed (%s == %s): (0x%08lx == 0x%08lx)", \ #a1, #a2, (unsigned long)(size_t)__p1, (unsigned long)(size_t)__p2); \ } while (0) #define assert_str_contains(expr, needle) \ do { const char *__str = (expr); \ if (__str && strstr (__str, needle)) ; else \ test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed (%s): '%s' does not contain '%s'", \ #expr, __str, needle); \ } while (0) #endif /* !TEST_SOURCE */ void test_fail (const char *filename, int line, const char *function, const char *message, ...) GNUC_PRINTF(4, 5) CLANG_ANALYZER_NORETURN; void test_func (void (* function) (void), const char *name, ...) GNUC_PRINTF(2, 3); void test_funcx (void (* function) (void *), void *argument, const char *name, ...) GNUC_PRINTF(3, 4); void test_fixture (void (* setup) (void *), void (* teardown) (void *)); int test_run (int argc, char **argv); #endif /* TEST_H_ */