Skip to content

Commit

Permalink
Merge branch 'features/new-logging' into bleeding
Browse files Browse the repository at this point in the history
  • Loading branch information
Snaipe committed Feb 17, 2016
2 parents 41bfaa1 + 4b093d2 commit e53f389
Show file tree
Hide file tree
Showing 23 changed files with 431 additions and 79 deletions.
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Criterion
starter
assert
hooks
logging
env
output
parameterized
Expand Down
61 changes: 61 additions & 0 deletions doc/logging.rst
Original file line number Diff line number Diff line change
@@ -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 <criterion/criterion.h>
#include <criterion/logging.h>
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 <criterion/criterion.h>
#include <criterion/logging.h>

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.
35 changes: 35 additions & 0 deletions include/criterion/internal/deprecation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015-2016 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* 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_ */
127 changes: 63 additions & 64 deletions include/criterion/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,84 +24,32 @@
#ifndef CRITERION_LOGGING_H_
# define CRITERION_LOGGING_H_

# ifdef __cplusplus
# include <cstdarg>
using std::va_list;
# else
# include <stdbool.h>
# include <stdarg.h>
# endif
# include "internal/common.h"
# include "internal/ordered-set.h"
# include "internal/deprecation.h"
# include "stats.h"

CR_BEGIN_C_API

enum criterion_logging_level {
CRITERION_INFO = 1,
CRITERION_IMPORTANT,

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, ...);

# 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__)
CR_API void cr_log(enum criterion_severity severity, const char *msg, ...);

# 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);
Expand All @@ -119,12 +67,63 @@ 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;

CR_END_C_API

#define CR_NORMAL_LOGGING (&normal_logging)
# define CR_NORMAL_LOGGING (&normal_logging)

# ifdef __cplusplus
# include <sstream>

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

# 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_ */
3 changes: 2 additions & 1 deletion samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ set(SAMPLES
timeout.c
redirect.c
parameterized.c

log.c
)

if (CMAKE_CXX_COMPILER_WORKS)
Expand All @@ -37,6 +37,7 @@ if (CMAKE_CXX_COMPILER_WORKS)
simple.cc
redirect.cc
parameterized.cc
log.cc
)
endif ()

Expand Down
15 changes: 15 additions & 0 deletions samples/log.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <criterion/criterion.h>
#include <criterion/logging.h>

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");
}
18 changes: 18 additions & 0 deletions samples/log.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <criterion/criterion.h>
#include <criterion/logging.h>

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;
}
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -117,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)
Expand Down
2 changes: 1 addition & 1 deletion src/compat/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/
#include "alloc.h"
#include "internal.h"
#include "criterion/logging.h"
#include "log/logging.h"
#include <stdlib.h>

#ifdef VANILLA_WIN32
Expand Down
2 changes: 1 addition & 1 deletion src/compat/kill.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion src/compat/pipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
# include <stdio.h>
# include <stdlib.h>
# include "common.h"
# include "criterion/logging.h"
# include "log/logging.h"

struct pipe_handle;
typedef struct pipe_handle s_pipe_handle;
Expand Down
6 changes: 4 additions & 2 deletions src/core/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -483,6 +483,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;
}
2 changes: 1 addition & 1 deletion src/core/report.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
#include <stdlib.h>
#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"
Expand Down
Loading

0 comments on commit e53f389

Please sign in to comment.