/* See LICENSE file for copyright and license details. */ #include "liblog.h" #include #include #include #include #include #include #include #include #define DEFAULT_PREFIXFMT "%[argv0] [%[pid]] [%{utime:%F %T%}.%[milli]Z] [%level]: %[file]:%[line] (%[function]): " #if defined(__GNUC__) # define WEAK_LINKING __attribute__((__weak__)) #else # define WEAK_LINKING # define WEAK_LINKING_FAILED #endif #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MAX(A, B) ((A) > (B) ? (A) : (B)) #define NEXT_LOGLEVEL(LVL) ((enum liblog_level)(LVL) + (enum liblog_level)100) #define XLOG_NOT_INLINE 0x0100 struct messagebuf { char *prefix; /* TODO for each output channel; also get arguments for each channel */ char *text; size_t len; size_t size; }; #define MESSAGEBUF_INIT ((struct messagebuf){NULL, NULL, 0, 0}) struct liblog_context_internal_state { struct messagebuf msg; }; extern const char *argv0; int liblog_flush__(struct liblog_context *ctx, const struct messagebuf *msg); WEAK_LINKING int liblog_trace__(char **textp, size_t *offsetp, size_t *allocsizep, size_t skip, void *saved_trace); WEAK_LINKING int liblog_whence__(char **file_out, off_t *line_out, char **function_out, size_t skip, void **trace_savep); #ifdef TEST # if defined(__GNUC__) # if defined(__clang__) # pragma clang diagnostic ignored "-Wdisabled-macro-expansion" # endif # define main __attribute__((__const__)) main # endif #endif #ifdef TEST # define TESTED_ELSEWHERE LIBEXEC_CONST__ int main(void) { return 0; } enum assert_type { ASSERT_ENUM, ASSERT_UINT, ASSERT_INT, ASSERT_NULL, ASSERT_PTR, ASSERT_STR, ASSERT_STR_REV }; enum assert_how { ASSERT_EQ, ASSERT_NE, ASSERT_LT, ASSERT_LE, ASSERT_GT, ASSERT_GE, ASSERT_CONTAINS_ALL, ASSERT_CONTAINS_ANY, ASSERT_CONTAINS_NOT_ALL, ASSERT_CONTAINS_NOT_ANY, ASSERT_IS_IN, ASSERT_NOT_IN, ASSERT_NOT_LT, ASSERT_NOT_LE, ASSERT_NOT_GT, ASSERT_NOT_GE }; void test_assert(const char *file, int line, enum assert_type type, enum assert_how how, const char *have_string, const char *expect_string, const void *have, const void *expect); #define ASSERT_EQ_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_EQ, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_NE_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_NE, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_LT_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_LT, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_GT_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_GT, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_LE_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_LE, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_GE_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_GE, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_ALL_OF_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_CONTAINS_ALL, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_SOME_OF_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_CONTAINS_ANY, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_NONE_OF_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_CONTAINS_NOT_ANY, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_NOT_ALL_OF_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_CONTAINS_NOT_ALL, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_IS_IN_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_IS_IN, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_NOT_IN_ENUM(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_ENUM, ASSERT_NOT_IN, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_EQ_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_EQ, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_NE_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_NE, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_LT_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_LT, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_GT_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_GT, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_LE_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_LE, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_GE_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_GE, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_ALL_OF_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_CONTAINS_ALL, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_SOME_OF_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_CONTAINS_ANY, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_NONE_OF_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_CONTAINS_NOT_ANY, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_CONTAINS_NOT_ALL_OF_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_CONTAINS_NOT_ALL, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_IS_IN_UINT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_UINT, ASSERT_IS_IN, #HAVE, #EXPECT,\ &(uintmax_t){(uintmax_t)(HAVE)}, &(uintmax_t){(uintmax_t)(EXPECT)}) #define ASSERT_EQ_INT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_INT, ASSERT_EQ, #HAVE, #EXPECT,\ &(intmax_t){(intmax_t)(HAVE)}, &(intmax_t){(intmax_t)(EXPECT)}) #define ASSERT_NE_INT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_INT, ASSERT_NE, #HAVE, #EXPECT,\ &(intmax_t){(intmax_t)(HAVE)}, &(intmax_t){(intmax_t)(EXPECT)}) #define ASSERT_LT_INT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_INT, ASSERT_LT, #HAVE, #EXPECT,\ &(intmax_t){(intmax_t)(HAVE)}, &(intmax_t){(intmax_t)(EXPECT)}) #define ASSERT_GT_INT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_INT, ASSERT_GT, #HAVE, #EXPECT,\ &(intmax_t){(intmax_t)(HAVE)}, &(intmax_t){(intmax_t)(EXPECT)}) #define ASSERT_LE_INT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_INT, ASSERT_LE, #HAVE, #EXPECT,\ &(intmax_t){(intmax_t)(HAVE)}, &(intmax_t){(intmax_t)(EXPECT)}) #define ASSERT_GE_INT(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_INT, ASSERT_GE, #HAVE, #EXPECT,\ &(intmax_t){(intmax_t)(HAVE)}, &(intmax_t){(intmax_t)(EXPECT)}) #define ASSERT_EQ_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_EQ, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_NE_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_NE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_STARTS_WITH_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_GE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_EXTENDS_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_GT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_TRUNCATES_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_LT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_BEGINNING_BOUNDED_TO_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_LE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_ENDS_WITH_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_GE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_EXTENDS_END_OF_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_GT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_TRUNCATES_END_OF_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_LT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_ENDING_BOUNDED_TO_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_LE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_DOES_NOT_STARTS_WITH_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_NOT_GE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_DOES_NOT_EXTENDS_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_NOT_GT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_DOES_NOT_TRUNCATES_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_NOT_LT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_BEGINNING_NOT_BOUNDED_TO_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_NOT_LE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_DOES_NOT_ENDS_WITH_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_NOT_GE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_DOES_NOT_EXTENDS_END_OF_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_NOT_GT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_DOES_NOT_TRUNCATES_END_OF_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_NOT_LT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_ENDING_NOT_BOUNDED_TO_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR_REV, ASSERT_NOT_LE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_CONTAINS_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_CONTAINS_ALL, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_DOES_NOT_CONTAIN_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_CONTAINS_NOT_ALL, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_IS_IN_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_IS_IN, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_NOT_IN_STR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_STR, ASSERT_NOT_IN, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_IS_PTR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_PTR, ASSERT_EQ, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_NOT_PTR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_PTR, ASSERT_NE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_BEFORE_PTR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_PTR, ASSERT_LT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_AFTER_PTR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_PTR, ASSERT_GT, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_BEFORE_OR_IS_PTR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_PTR, ASSERT_LE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_AFTER_OR_IS_PTR(HAVE, EXPECT)\ test_assert(__FILE__, __LINE__, ASSERT_PTR, ASSERT_GE, #HAVE, #EXPECT, (HAVE), (EXPECT)) #define ASSERT_IS_NULL(HAVE)\ test_assert(__FILE__, __LINE__, ASSERT_NULL, ASSERT_EQ, #HAVE, "NULL", (HAVE), NULL) #define ASSERT_NOT_NULL(HAVE)\ test_assert(__FILE__, __LINE__, ASSERT_NULL, ASSERT_NE, #HAVE, "NULL", (HAVE), NULL) #define ASSERT_IS_TRUE(HAVE)\ ASSERT_NE_INT(HAVE, 0) #define ASSERT_IS_FALSE(HAVE)\ ASSERT_EQ_INT(HAVE, 0) #define ASSERT_ZERO(HAVE)\ ASSERT_EQ_INT(HAVE, 0) #endif