From b8bfa34c22687a920945351df718204084b1080e Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 21 Jan 2016 00:53:18 +0100 Subject: [PATCH 1/7] Added simple message logging from a test worker --- include/criterion/logging.h | 74 ++++---------------------- samples/CMakeLists.txt | 2 +- samples/log.c | 15 ++++++ src/CMakeLists.txt | 1 + src/compat/alloc.c | 2 +- src/compat/kill.c | 2 +- src/compat/pipe.h | 2 +- src/core/client.c | 6 ++- src/core/report.c | 2 +- src/core/runner.c | 2 +- src/core/runner_coroutine.c | 2 +- src/io/json.c | 2 +- src/io/output.c | 2 +- src/io/xml.c | 2 +- src/log/logging.c | 69 ++++++++++++++++++++++++- src/log/logging.h | 100 ++++++++++++++++++++++++++++++++++++ src/log/normal.c | 7 ++- src/protocol/messages.c | 2 +- 18 files changed, 216 insertions(+), 78 deletions(-) create mode 100644 samples/log.c create mode 100644 src/log/logging.h diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 6764876..fff5724 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -24,17 +24,12 @@ #ifndef CRITERION_LOGGING_H_ # define CRITERION_LOGGING_H_ -# ifdef __cplusplus -# include -using std::va_list; -# else -# include -# include -# endif # include "internal/common.h" # include "internal/ordered-set.h" # include "stats.h" +CR_BEGIN_C_API + enum criterion_logging_level { CRITERION_INFO = 1, CRITERION_IMPORTANT, @@ -42,66 +37,18 @@ enum criterion_logging_level { CRITERION_LOG_LEVEL_QUIET = 1 << 30, }; -enum criterion_logging_prefix { - CRITERION_LOGGING_PREFIX_DASHES, - CRITERION_LOGGING_PREFIX_EQUALS, - CRITERION_LOGGING_PREFIX_RUN, - CRITERION_LOGGING_PREFIX_SKIP, - CRITERION_LOGGING_PREFIX_PASS, - CRITERION_LOGGING_PREFIX_FAIL, - CRITERION_LOGGING_PREFIX_ERR, +enum criterion_severity { + CR_LOG_INFO, + CR_LOG_WARNING, + CR_LOG_ERROR, }; -struct criterion_prefix_data { - const char *prefix; - const char *color; -}; - -# ifdef CRITERION_LOGGING_COLORS -# define CRIT_COLOR_NORMALIZE(Str) (criterion_options.use_ascii ? "" : Str) - -# define CRIT_FG_BOLD "\33[0;1m" -# define CRIT_FG_RED "\33[0;31m" -# define CRIT_FG_GREEN "\33[0;32m" -# define CRIT_FG_GOLD "\33[0;33m" -# define CRIT_FG_BLUE "\33[0;34m" -# define CRIT_RESET "\33[0m" - -# define CR_FG_BOLD CRIT_COLOR_NORMALIZE(CRIT_FG_BOLD) -# define CR_FG_RED CRIT_COLOR_NORMALIZE(CRIT_FG_RED) -# define CR_FG_GREEN CRIT_COLOR_NORMALIZE(CRIT_FG_GREEN) -# define CR_FG_GOLD CRIT_COLOR_NORMALIZE(CRIT_FG_GOLD) -# define CR_FG_BLUE CRIT_COLOR_NORMALIZE(CRIT_FG_BLUE) -# define CR_RESET CRIT_COLOR_NORMALIZE(CRIT_RESET) -# endif - -CR_BEGIN_C_API - -extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; - -# define CRITERION_PREFIX_DASHES (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_DASHES]) -# define CRITERION_PREFIX_EQUALS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_EQUALS]) -# define CRITERION_PREFIX_RUN (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_RUN ]) -# define CRITERION_PREFIX_SKIP (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_SKIP ]) -# define CRITERION_PREFIX_PASS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_PASS ]) -# define CRITERION_PREFIX_FAIL (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_FAIL ]) -# define CRITERION_PREFIX_ERR (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_ERR ]) - -CR_API void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); - -CR_FORMAT(printf, 3, 4) -CR_API void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...); - CR_FORMAT(printf, 2, 3) -CR_API void criterion_log(enum criterion_logging_level level, const char *msg, ...); +CR_API void cr_log(enum criterion_severity severity, const char *msg, ...); -# define criterion_info(...) criterion_log(CRITERION_INFO, __VA_ARGS__) -# define criterion_important(...) criterion_log(CRITERION_IMPORTANT, __VA_ARGS__) - -# define criterion_pinfo(...) criterion_plog(CRITERION_INFO, __VA_ARGS__) -# define criterion_pimportant(...) criterion_plog(CRITERION_IMPORTANT, __VA_ARGS__) - -# define criterion_perror(...) criterion_plog(CRITERION_IMPORTANT, CRITERION_PREFIX_ERR, __VA_ARGS__) +# define cr_log_info(...) cr_log(CR_LOG_INFO, __VA_ARGS__) +# define cr_log_warn(...) cr_log(CR_LOG_WARNING, __VA_ARGS__) +# define cr_log_error(...) cr_log(CR_LOG_ERROR, __VA_ARGS__) struct criterion_logger { void (*log_pre_all )(struct criterion_test_set *set); @@ -119,6 +66,7 @@ struct criterion_logger { void (*log_post_fini )(struct criterion_test_stats *stats); void (*log_post_suite )(struct criterion_suite_stats *stats); void (*log_post_all )(struct criterion_global_stats *stats); + void (*log_message )(enum criterion_severity, const char *msg); }; extern struct criterion_logger normal_logging; diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 0d77cf1..3be58d4 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -22,7 +22,7 @@ set(SAMPLES timeout.c redirect.c parameterized.c - + log.c ) if (CMAKE_CXX_COMPILER_WORKS) diff --git a/samples/log.c b/samples/log.c new file mode 100644 index 0000000..61657a7 --- /dev/null +++ b/samples/log.c @@ -0,0 +1,15 @@ +#include +#include + +Test(logging, simple) { + cr_log_info("This is an informational message. They are not displayed " + "by default."); + cr_log_warn("This is a warning. They indicate some possible malfunction " + "or misconfiguration in the test."); + cr_log_error("This is an error. They indicate serious problems and " + "are usually shown before the test is aborted."); +} + +Test(logging, format) { + cr_log_info("Log messages are %s.", "printf-formatted strings"); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c479354..0b9773b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,7 @@ set(SOURCE_FILES src/io/xml.c src/io/json.c src/log/logging.c + src/log/logging.h src/log/normal.c src/string/i18n.c src/string/i18n.h diff --git a/src/compat/alloc.c b/src/compat/alloc.c index c712692..e2737df 100644 --- a/src/compat/alloc.c +++ b/src/compat/alloc.c @@ -23,7 +23,7 @@ */ #include "alloc.h" #include "internal.h" -#include "criterion/logging.h" +#include "log/logging.h" #include #ifdef VANILLA_WIN32 diff --git a/src/compat/kill.c b/src/compat/kill.c index 962091c..726fb19 100644 --- a/src/compat/kill.c +++ b/src/compat/kill.c @@ -23,7 +23,7 @@ */ #include "kill.h" #include "internal.h" -#include "criterion/logging.h" +#include "log/logging.h" #include "core/report.h" #include "core/stats.h" #include "io/event.h" diff --git a/src/compat/pipe.h b/src/compat/pipe.h index 0591feb..59c955f 100644 --- a/src/compat/pipe.h +++ b/src/compat/pipe.h @@ -27,7 +27,7 @@ # include # include # include "common.h" -# include "criterion/logging.h" +# include "log/logging.h" struct pipe_handle; typedef struct pipe_handle s_pipe_handle; diff --git a/src/core/client.c b/src/core/client.c index d4fe7d0..ae370eb 100644 --- a/src/core/client.c +++ b/src/core/client.c @@ -27,8 +27,8 @@ #include "compat/strtok.h" #include "protocol/protocol.h" #include "protocol/messages.h" -#include "criterion/logging.h" #include "criterion/options.h" +#include "log/logging.h" #include "io/event.h" #include "report.h" #include "stats.h" @@ -481,6 +481,8 @@ bool handle_assert(struct server_ctx *sctx, struct client_ctx *ctx, const criter bool handle_message(struct server_ctx *sctx, struct client_ctx *ctx, const criterion_protocol_msg *msg) { (void) sctx; (void) ctx; - (void) msg; + const criterion_protocol_log *lg = &msg->data.value.message; + + log(message, (enum criterion_severity) lg->severity, lg->message); return false; } diff --git a/src/core/report.c b/src/core/report.c index afee441..6bbdf0e 100644 --- a/src/core/report.c +++ b/src/core/report.c @@ -26,9 +26,9 @@ #include #include "criterion/types.h" #include "criterion/stats.h" -#include "criterion/logging.h" #include "criterion/options.h" #include "criterion/internal/ordered-set.h" +#include "log/logging.h" #include "report.h" #include "config.h" #include "compat/posix.h" diff --git a/src/core/runner.c b/src/core/runner.c index 58f245f..e299801 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -31,7 +31,6 @@ #include "criterion/internal/test.h" #include "criterion/options.h" #include "criterion/internal/ordered-set.h" -#include "criterion/logging.h" #include "criterion/internal/preprocess.h" #include "criterion/redirect.h" #include "protocol/protocol.h" @@ -44,6 +43,7 @@ #include "string/i18n.h" #include "io/event.h" #include "io/output.h" +#include "log/logging.h" #include "runner_coroutine.h" #include "stats.h" #include "runner.h" diff --git a/src/core/runner_coroutine.c b/src/core/runner_coroutine.c index f80873d..8e1649a 100644 --- a/src/core/runner_coroutine.c +++ b/src/core/runner_coroutine.c @@ -24,8 +24,8 @@ #include #include #include -#include "criterion/logging.h" #include "criterion/internal/parameterized.h" +#include "log/logging.h" #include "runner_coroutine.h" #include "worker.h" #include "stats.h" diff --git a/src/io/json.c b/src/io/json.c index 5b1b78f..c15902d 100644 --- a/src/io/json.c +++ b/src/io/json.c @@ -26,9 +26,9 @@ #include #include #include "criterion/stats.h" -#include "criterion/logging.h" #include "criterion/options.h" #include "criterion/internal/ordered-set.h" +#include "log/logging.h" #include "compat/posix.h" #include "compat/strtok.h" #include "compat/time.h" diff --git a/src/io/output.c b/src/io/output.c index d3fd05d..1408920 100644 --- a/src/io/output.c +++ b/src/io/output.c @@ -4,7 +4,7 @@ #include #include #include "criterion/output.h" -#include "criterion/logging.h" +#include "log/logging.h" #include "string/i18n.h" typedef const char *const msg_t; diff --git a/src/io/xml.c b/src/io/xml.c index ca5664b..a0960f5 100644 --- a/src/io/xml.c +++ b/src/io/xml.c @@ -26,9 +26,9 @@ #include #include #include "criterion/stats.h" -#include "criterion/logging.h" #include "criterion/options.h" #include "criterion/internal/ordered-set.h" +#include "log/logging.h" #include "compat/posix.h" #include "compat/strtok.h" #include "compat/time.h" diff --git a/src/log/logging.c b/src/log/logging.c index cf4ad12..e17cc47 100644 --- a/src/log/logging.c +++ b/src/log/logging.c @@ -25,8 +25,13 @@ #include #include #include -#include "criterion/logging.h" +#include "criterion/criterion.h" #include "criterion/options.h" +#include "compat/process.h" +#include "log/logging.h" +#include "io/asprintf.h" +#include "protocol/protocol.h" +#include "protocol/messages.h" #include "string/i18n.h" #ifdef ENABLE_NLS @@ -45,9 +50,46 @@ const struct criterion_prefix_data g_criterion_logging_prefixes[] = { [CRITERION_LOGGING_PREFIX_PASS] = { "PASS", CRIT_FG_GREEN }, [CRITERION_LOGGING_PREFIX_FAIL] = { "FAIL", CRIT_FG_RED }, [CRITERION_LOGGING_PREFIX_ERR] = { "ERR ", CRIT_FG_RED }, + [CRITERION_LOGGING_PREFIX_WARN] = { "WARN", CRIT_FG_GOLD }, { NULL, NULL } }; +void criterion_log_noformat(enum criterion_severity severity, const char *msg) { + static const struct criterion_prefix_data *prefixes[] = { + [CR_LOG_INFO] = CRITERION_PREFIX_DASHES, + [CR_LOG_WARNING] = CRITERION_PREFIX_WARN, + [CR_LOG_ERROR] = CRITERION_PREFIX_ERR, + }; + + static enum criterion_logging_level severity_to_level[] = { + [CR_LOG_INFO] = CRITERION_INFO, + [CR_LOG_WARNING] = CRITERION_IMPORTANT, + [CR_LOG_ERROR] = CRITERION_IMPORTANT, + }; + + if (severity_to_level[severity] < criterion_options.logging_threshold) + return; + + const struct criterion_prefix_data *prefix = prefixes[severity]; + if (severity == CR_LOG_ERROR) { + fprintf(stderr, _(ERROR_FORMAT), + CRIT_COLOR_NORMALIZE(prefix->color), + prefix->prefix, + CR_RESET, + CR_FG_RED, + CR_FG_BOLD, + msg, + CR_RESET); + } else { + fprintf(stderr, _(LOG_FORMAT), + CRIT_COLOR_NORMALIZE(prefix->color), + prefix->prefix, + CR_RESET, + msg); + } + fprintf(stderr, "\n"); +} + void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...) { va_list args; @@ -91,3 +133,28 @@ void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list vfprintf(stderr, msg, args); } + +void cr_log_noformat(enum criterion_severity severity, const char *out) { + criterion_protocol_msg msg = criterion_message(message, + .severity = (criterion_protocol_log_level) severity, + .message = (char *) out); + criterion_message_set_id(msg); + cr_send_to_runner(&msg); +} + +void cr_log(enum criterion_severity severity, const char *msg, ...) { + va_list args; + char *out = NULL; + + va_start(args, msg); + int res = cr_vasprintf(&out, msg, args); + va_end(args); + + if (res == -1) { + cr_log_noformat(CR_LOG_ERROR, "Could not format log message"); + abort(); + } + + cr_log_noformat(severity, out); + free(out); +} diff --git a/src/log/logging.h b/src/log/logging.h new file mode 100644 index 0000000..7e03de5 --- /dev/null +++ b/src/log/logging.h @@ -0,0 +1,100 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015-2016 Franklin "Snaipe" Mathieu + * + * 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. + */ +#ifndef LOGGING_H_ +# define LOGGING_H_ + +# ifdef __cplusplus +# include +using std::va_list; +# else +# include +# include +# endif +# include "criterion/logging.h" + +enum criterion_logging_prefix { + CRITERION_LOGGING_PREFIX_DASHES, + CRITERION_LOGGING_PREFIX_EQUALS, + CRITERION_LOGGING_PREFIX_RUN, + CRITERION_LOGGING_PREFIX_SKIP, + CRITERION_LOGGING_PREFIX_PASS, + CRITERION_LOGGING_PREFIX_FAIL, + CRITERION_LOGGING_PREFIX_ERR, + CRITERION_LOGGING_PREFIX_WARN, +}; + +struct criterion_prefix_data { + const char *prefix; + const char *color; +}; + +# ifdef CRITERION_LOGGING_COLORS +# define CRIT_COLOR_NORMALIZE(Str) (criterion_options.use_ascii ? "" : Str) + +# define CRIT_FG_BOLD "\33[0;1m" +# define CRIT_FG_RED "\33[0;31m" +# define CRIT_FG_GREEN "\33[0;32m" +# define CRIT_FG_GOLD "\33[0;33m" +# define CRIT_FG_BLUE "\33[0;34m" +# define CRIT_RESET "\33[0m" + +# define CR_FG_BOLD CRIT_COLOR_NORMALIZE(CRIT_FG_BOLD) +# define CR_FG_RED CRIT_COLOR_NORMALIZE(CRIT_FG_RED) +# define CR_FG_GREEN CRIT_COLOR_NORMALIZE(CRIT_FG_GREEN) +# define CR_FG_GOLD CRIT_COLOR_NORMALIZE(CRIT_FG_GOLD) +# define CR_FG_BLUE CRIT_COLOR_NORMALIZE(CRIT_FG_BLUE) +# define CR_RESET CRIT_COLOR_NORMALIZE(CRIT_RESET) +# endif + +extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; + +# define CRITERION_PREFIX_DASHES (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_DASHES]) +# define CRITERION_PREFIX_EQUALS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_EQUALS]) +# define CRITERION_PREFIX_RUN (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_RUN ]) +# define CRITERION_PREFIX_SKIP (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_SKIP ]) +# define CRITERION_PREFIX_PASS (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_PASS ]) +# define CRITERION_PREFIX_FAIL (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_FAIL ]) +# define CRITERION_PREFIX_ERR (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_ERR ]) +# define CRITERION_PREFIX_WARN (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_WARN ]) + +CR_API void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); + +CR_FORMAT(printf, 3, 4) +CR_API void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...); + +CR_FORMAT(printf, 2, 3) +CR_API void criterion_log(enum criterion_logging_level level, const char *msg, ...); + +# define criterion_info(...) criterion_log(CRITERION_INFO, __VA_ARGS__) +# define criterion_important(...) criterion_log(CRITERION_IMPORTANT, __VA_ARGS__) + +# define criterion_pinfo(...) criterion_plog(CRITERION_INFO, __VA_ARGS__) +# define criterion_pimportant(...) criterion_plog(CRITERION_IMPORTANT, __VA_ARGS__) + +# define criterion_perror(...) criterion_plog(CRITERION_IMPORTANT, CRITERION_PREFIX_ERR, __VA_ARGS__) + +void cr_log_noformat(enum criterion_severity severity, const char *out); +void criterion_log_noformat(enum criterion_severity severity, const char *msg); + +#endif /* !LOGGING_H_ */ diff --git a/src/log/normal.c b/src/log/normal.c index 300266e..95dffb2 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -27,9 +27,9 @@ #include #include #include "criterion/stats.h" -#include "criterion/logging.h" #include "criterion/options.h" #include "criterion/internal/ordered-set.h" +#include "log/logging.h" #include "compat/posix.h" #include "compat/strtok.h" #include "compat/time.h" @@ -233,6 +233,10 @@ void normal_log_test_abort(CR_UNUSED struct criterion_test_stats *stats, const c free(dup); } +void normal_log_message(enum criterion_severity severity, const char *msg) { + criterion_log_noformat(severity, msg); +} + struct criterion_logger normal_logging = { .log_pre_all = normal_log_pre_all, .log_pre_init = normal_log_pre_init, @@ -247,4 +251,5 @@ struct criterion_logger normal_logging = { .log_post_test = normal_log_post_test, .log_post_suite = normal_log_post_suite, .log_post_all = normal_log_post_all, + .log_message = normal_log_message, }; diff --git a/src/protocol/messages.c b/src/protocol/messages.c index 6a03697..788d66e 100644 --- a/src/protocol/messages.c +++ b/src/protocol/messages.c @@ -24,7 +24,7 @@ #include #include #include "protocol/protocol.h" -#include "criterion/logging.h" +#include "log/logging.h" #include "io/event.h" #include "io/asprintf.h" From 8ab938d06d5d0af302e150662c5185f17327bf87 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 21 Jan 2016 11:39:51 +0100 Subject: [PATCH 2/7] Added deprecation for old criterion logging macros --- include/criterion/internal/deprecation.h | 35 ++++++++++++++++++++++++ include/criterion/logging.h | 15 +++++++++- src/CMakeLists.txt | 1 + src/log/logging.h | 7 +++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 include/criterion/internal/deprecation.h diff --git a/include/criterion/internal/deprecation.h b/include/criterion/internal/deprecation.h new file mode 100644 index 0000000..30c9477 --- /dev/null +++ b/include/criterion/internal/deprecation.h @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015-2016 Franklin "Snaipe" Mathieu + * + * 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. + */ +#ifndef CRITERION_INTERNAL_DEPRECATION_H_ +# define CRITERION_INTERNAL_DEPRECATION_H_ + +# define CR_DEPRECATED(Msg) CR_DEPRECATED__(message (Msg)) + +# ifdef _MSC_VER +# define CR_DEPRECATED_(Msg) __pragma(Msg) +# else +# define CR_DEPRECATED_(Msg) _Pragma(#Msg) +# endif + +#endif /* !CRITERION_INTERNAL_DEPRECATION_H_ */ diff --git a/include/criterion/logging.h b/include/criterion/logging.h index fff5724..0ff6cb9 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -26,6 +26,7 @@ # include "internal/common.h" # include "internal/ordered-set.h" +# include "internal/deprecation.h" # include "stats.h" CR_BEGIN_C_API @@ -73,6 +74,18 @@ extern struct criterion_logger normal_logging; CR_END_C_API -#define CR_NORMAL_LOGGING (&normal_logging) +# define CR_NORMAL_LOGGING (&normal_logging) + +// Deprecated old logging system, schedule removal for 3.0 +# ifndef CRITERION_NO_COMPAT + +# define criterion_log(_, ...) CR_DEPRECATED("criterion_log is deprecated, please use cr_log instead.") cr_log_info(__VA_ARGS__) +# define criterion_info(...) CR_DEPRECATED("criterion_info is deprecated, please use cr_log_info instead.") cr_log_info(__VA_ARGS__) +# define criterion_pinfo(_, ...) CR_DEPRECATED("criterion_pinfo is deprecated, please use cr_log_info instead.") cr_log_info(__VA_ARGS__) +# define criterion_important(...) CR_DEPRECATED("criterion_important is deprecated, please use cr_log_info instead.") cr_log_info(__VA_ARGS__) +# define criterion_pimportant(_, ...) CR_DEPRECATED("criterion_pimportant is deprecated, please use cr_log_info instead.") cr_log_info(__VA_ARGS__) +# define criterion_perror(...) CR_DEPRECATED("criterion_perror is deprecated, please use cr_log_error instead.") cr_log_error(__VA_ARGS__) + +# endif /* !CRITERION_NO_COMPAT */ #endif /* !CRITERION_LOGGING_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0b9773b..b907189 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -118,6 +118,7 @@ set(INTERFACE_FILES include/criterion/internal/hooks.h include/criterion/internal/redirect.h include/criterion/internal/stdio_filebuf.hxx + include/criterion/internal/deprecation.h ) if (THEORIES) diff --git a/src/log/logging.h b/src/log/logging.h index 7e03de5..3e366c5 100644 --- a/src/log/logging.h +++ b/src/log/logging.h @@ -78,6 +78,13 @@ extern const struct criterion_prefix_data g_criterion_logging_prefixes[]; # define CRITERION_PREFIX_ERR (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_ERR ]) # define CRITERION_PREFIX_WARN (&g_criterion_logging_prefixes[CRITERION_LOGGING_PREFIX_WARN ]) +# undef criterion_log +# undef criterion_info +# undef criterion_pinfo +# undef criterion_important +# undef criterion_pimportant +# undef criterion_perror + CR_API void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); CR_FORMAT(printf, 3, 4) From 9e0a746a2ed35ed9938442fe16d74a5c4b14c808 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 21 Jan 2016 12:31:25 +0100 Subject: [PATCH 3/7] Fixed typo in deprecation macro --- include/criterion/internal/deprecation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/criterion/internal/deprecation.h b/include/criterion/internal/deprecation.h index 30c9477..72b217c 100644 --- a/include/criterion/internal/deprecation.h +++ b/include/criterion/internal/deprecation.h @@ -24,7 +24,7 @@ #ifndef CRITERION_INTERNAL_DEPRECATION_H_ # define CRITERION_INTERNAL_DEPRECATION_H_ -# define CR_DEPRECATED(Msg) CR_DEPRECATED__(message (Msg)) +# define CR_DEPRECATED(Msg) CR_DEPRECATED_(message (Msg)) # ifdef _MSC_VER # define CR_DEPRECATED_(Msg) __pragma(Msg) From 4241b4e517f08e4bfe9b4620f148122f2824b828 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 21 Jan 2016 14:30:40 +0100 Subject: [PATCH 4/7] Added cram test for log.c --- test/cram/log.t | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/cram/log.t diff --git a/test/cram/log.t b/test/cram/log.t new file mode 100644 index 0000000..b49dda7 --- /dev/null +++ b/test/cram/log.t @@ -0,0 +1,21 @@ +Testing log messages + + $ log.c.bin --verbose + [\x1b[0;34m----\x1b[0m] Criterion v2.2.0 (esc) + [\x1b[0;34m====\x1b[0m] Running \x1b[0;34m2\x1b[0m tests from \x1b[0;33mlogging\x1b[0m: (esc) + [\x1b[0;34mRUN \x1b[0m] logging::format (esc) + [\x1b[0;34m----\x1b[0m] Log messages are printf-formatted strings. (esc) + [\x1b[0;32mPASS\x1b[0m] logging::format (esc) + [\x1b[0;34mRUN \x1b[0m] logging::simple (esc) + [\x1b[0;34m----\x1b[0m] This is an informational message. They are not displayed by default. (esc) + [\x1b[0;33mWARN\x1b[0m] This is a warning. They indicate some possible malfunction or misconfiguration in the test. (esc) + [\x1b[0;31mERR \x1b[0m] \x1b[0;31m\x1b[0;1mThis is an error. They indicate serious problems and are usually shown before the test is aborted.\x1b[0m (esc) + [\x1b[0;32mPASS\x1b[0m] logging::simple (esc) + [\x1b[0;34m====\x1b[0m] \x1b[0;1mSynthesis: Tested: \x1b[0;34m2\x1b[0;1m | Passing: \x1b[0;32m2\x1b[0;1m | Failing: \x1b[0;31m0\x1b[0;1m | Crashing: \x1b[0;31m0\x1b[0;1m \x1b[0m (esc) + +Testing log severity + + $ log.c.bin + [\x1b[0;33mWARN\x1b[0m] This is a warning. They indicate some possible malfunction or misconfiguration in the test. (esc) + [\x1b[0;31mERR \x1b[0m] \x1b[0;31m\x1b[0;1mThis is an error. They indicate serious problems and are usually shown before the test is aborted.\x1b[0m (esc) + [\x1b[0;34m====\x1b[0m] \x1b[0;1mSynthesis: Tested: \x1b[0;34m2\x1b[0;1m | Passing: \x1b[0;32m2\x1b[0;1m | Failing: \x1b[0;31m0\x1b[0;1m | Crashing: \x1b[0;31m0\x1b[0;1m \x1b[0m (esc) From 9bc0da9e83ec996f28e3277064798133ee8597c0 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 17 Feb 2016 22:56:23 +0100 Subject: [PATCH 5/7] Added C++ stream interface for logging --- include/criterion/logging.h | 38 +++++++++++++++++++++++++++++++++++++ samples/CMakeLists.txt | 1 + samples/log.cc | 18 ++++++++++++++++++ test/cram/log.t | 10 ++++++++++ 4 files changed, 67 insertions(+) create mode 100644 samples/log.cc diff --git a/include/criterion/logging.h b/include/criterion/logging.h index 0ff6cb9..b90a051 100644 --- a/include/criterion/logging.h +++ b/include/criterion/logging.h @@ -76,6 +76,44 @@ CR_END_C_API # define CR_NORMAL_LOGGING (&normal_logging) +# ifdef __cplusplus +# include + +namespace criterion { namespace logging { + +static void (*const log)(enum criterion_severity, const char *, ...) = cr_log; + +class streambuf : public std::stringbuf { +public: + streambuf(enum criterion_severity severity__) + : std::stringbuf(), severity__(severity__) + {} + + virtual int sync() override { + criterion::logging::log(severity__, "%s", str().c_str()); + str(std::string()); + return 0; + } +private: + enum criterion_severity severity__; +}; + +class stream : public std::ostream { +public: + stream(enum criterion_severity severity__) + : std::ostream(&buf), buf(severity__) + {} +private: + streambuf buf; +}; + +stream info { CR_LOG_INFO }; +stream warn { CR_LOG_WARNING }; +stream error { CR_LOG_ERROR }; + +}} +# endif + // Deprecated old logging system, schedule removal for 3.0 # ifndef CRITERION_NO_COMPAT diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 3be58d4..728c6e6 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -37,6 +37,7 @@ if (CMAKE_CXX_COMPILER_WORKS) simple.cc redirect.cc parameterized.cc + log.cc ) endif () diff --git a/samples/log.cc b/samples/log.cc new file mode 100644 index 0000000..89eeed1 --- /dev/null +++ b/samples/log.cc @@ -0,0 +1,18 @@ +#include +#include + +using criterion::logging::info; +using criterion::logging::warn; +using criterion::logging::error; + +Test(logging, stream) { + info << "This is an informational message. They are not displayed " + "by default." + << std::endl; + warn << "This is a warning. They indicate some possible malfunction " + "or misconfiguration in the test." + << std::endl; + error << "This is an error. They indicate serious problems and " + "are usually shown before the test is aborted." + << std::endl; +} diff --git a/test/cram/log.t b/test/cram/log.t index b49dda7..32d687f 100644 --- a/test/cram/log.t +++ b/test/cram/log.t @@ -13,6 +13,16 @@ Testing log messages [\x1b[0;32mPASS\x1b[0m] logging::simple (esc) [\x1b[0;34m====\x1b[0m] \x1b[0;1mSynthesis: Tested: \x1b[0;34m2\x1b[0;1m | Passing: \x1b[0;32m2\x1b[0;1m | Failing: \x1b[0;31m0\x1b[0;1m | Crashing: \x1b[0;31m0\x1b[0;1m \x1b[0m (esc) + $ log.cc.bin --verbose + [\x1b[0;34m----\x1b[0m] Criterion v2.2.0 (esc) + [\x1b[0;34m====\x1b[0m] Running \x1b[0;34m1\x1b[0m test from \x1b[0;33mlogging\x1b[0m: (esc) + [\x1b[0;34mRUN \x1b[0m] logging::stream (esc) + [\x1b[0;34m----\x1b[0m] This is an informational message. They are not displayed by default. (esc) + [\x1b[0;33mWARN\x1b[0m] This is a warning. They indicate some possible malfunction or misconfiguration in the test. (esc) + [\x1b[0;31mERR \x1b[0m] \x1b[0;31m\x1b[0;1mThis is an error. They indicate serious problems and are usually shown before the test is aborted.\x1b[0m (esc) + [\x1b[0;32mPASS\x1b[0m] logging::stream (esc) + [\x1b[0;34m====\x1b[0m] \x1b[0;1mSynthesis: Tested: \x1b[0;34m1\x1b[0;1m | Passing: \x1b[0;32m1\x1b[0;1m | Failing: \x1b[0;31m0\x1b[0;1m | Crashing: \x1b[0;31m0\x1b[0;1m \x1b[0m (esc) + Testing log severity $ log.c.bin From 99b10d443c47f8d9dd25406c4ebefbb444d411b2 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 17 Feb 2016 23:25:26 +0100 Subject: [PATCH 6/7] Added message splitting on line feed --- src/log/normal.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/log/normal.c b/src/log/normal.c index 95dffb2..edfeb5f 100644 --- a/src/log/normal.c +++ b/src/log/normal.c @@ -234,7 +234,15 @@ void normal_log_test_abort(CR_UNUSED struct criterion_test_stats *stats, const c } void normal_log_message(enum criterion_severity severity, const char *msg) { - criterion_log_noformat(severity, msg); + char *dup = strdup(msg); + char *saveptr = NULL; + char *line = strtok_r(dup, "\n", &saveptr); + + do { + if (*line != '\0') + criterion_log_noformat(severity, line); + } while ((line = strtok_r(NULL, "\n", &saveptr))); + free (dup); } struct criterion_logger normal_logging = { From 4b093d2a3ea4537d3e338c661f06b6789c1bc252 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Wed, 17 Feb 2016 23:33:52 +0100 Subject: [PATCH 7/7] Added documentation on logging functions --- doc/index.rst | 1 + doc/logging.rst | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 doc/logging.rst diff --git a/doc/index.rst b/doc/index.rst index edb8e4c..b36d413 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,6 +9,7 @@ Criterion starter assert hooks + logging env output parameterized diff --git a/doc/logging.rst b/doc/logging.rst new file mode 100644 index 0000000..a97117d --- /dev/null +++ b/doc/logging.rst @@ -0,0 +1,61 @@ +Logging messages +================ + +Sometimes, it might be useful to print some output from within a test +or fixture -- and while this can be done trivially with a ``printf``, +it doesn't integrate well with the current output, nor does it work +*at all* when the process is testing a redirected stdout. + +For these cases, Criterion exposes a logging facility: + +.. code-block:: c + + #include + #include + + Test(suite_name, test_name) { + cr_log_info("This is an informational message. They are not displayed " + "by default."); + cr_log_warn("This is a warning. They indicate some possible malfunction " + "or misconfiguration in the test."); + cr_log_error("This is an error. They indicate serious problems and " + "are usually shown before the test is aborted."); + } + +``cr_log_info``, ``cr_log_warn`` and ``cr_log_error`` are all macros expanding +to a call to the ``cr_log`` function. All of them take a mandatory format string, +followed by optional parameters; for instance: + +.. code-block:: c + + cr_log_info("%d + %d = %d", 1, 2, 3); + +If using C++, the output stream objects ``info``, ``warn`` and ``error`` are +defined within the ``criterion::logging`` namespace, and can be used in +conjunction with ``operator<<``: + +.. code-block:: c++ + + #include + #include + + using criterion::logging::info; + using criterion::logging::warn; + using criterion::logging::error; + + Test(suite_name, test_name) { + info << "This is an informational message. " + << "They are not displayed by default." + << std::flush; + warn << "This is a warning. " + << "They indicate some possible malfunction " + << "or misconfiguration in the test." + << std::flush; + error << "This is an error. " + << "They indicate serious problems and " + << "are usually shown before the test is aborted." + << std::flush; + } + +Note that empty messages are ignored, and newlines in the log message splits +the passed string into as many messages are there are lines.