From aa9b2aa9155f5e73a59d12767d350d82c3c6473c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 23 Aug 2016 21:46:14 +0200 Subject: [PATCH] cli: Added --debug. Fixes #85. --- include/criterion/internal/parameterized.h | 1 + include/criterion/internal/test.h | 11 ++++++ include/criterion/options.h | 46 ++++++++++++++++++++++ include/criterion/types.h | 8 ++++ src/core/runner.c | 5 +++ src/core/runner_coroutine.c | 22 +++++++++-- src/entry/options.c | 1 + src/entry/params.c | 32 ++++++++++++++- 8 files changed, 121 insertions(+), 5 deletions(-) diff --git a/include/criterion/internal/parameterized.h b/include/criterion/internal/parameterized.h index f99d409..5ef6d95 100644 --- a/include/criterion/internal/parameterized.h +++ b/include/criterion/internal/parameterized.h @@ -82,6 +82,7 @@ struct criterion_test_params { CR_TEST_TRAMPOLINE_(Category, Name) \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \ + .compiler_ = CR_COMPILER_, \ .lang_ = CR_LANG, \ .kind_ = CR_TEST_PARAMETERIZED, \ .param_ = CR_IDENTIFIER_(Category, Name, param), \ diff --git a/include/criterion/internal/test.h b/include/criterion/internal/test.h index 5a6742d..6010a2c 100644 --- a/include/criterion/internal/test.h +++ b/include/criterion/internal/test.h @@ -142,11 +142,22 @@ static const char *const cr_msg_test_fini_other_exception = "Caught some unexpec # endif # endif +# if defined(_MSC_VER) +# define CR_COMPILER_ CR_COMP_MSVC +# elif defined(__clang__) +# define CR_COMPILER_ CR_COMP_CLANG +# elif defined(__GNUC__) +# define CR_COMPILER_ CR_COMP_GCC +# else +# define CR_COMPILER_ CR_COMP_UNKNOWN +# endif + # define CR_TEST_BASE(Category, Name, ...) \ CR_TEST_PROTOTYPE_(Category, Name); \ CR_TEST_TRAMPOLINE_(Category, Name) \ struct criterion_test_extra_data CR_IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(criterion_test_extra_data, \ + .compiler_ = CR_COMPILER_, \ .lang_ = CR_LANG, \ .kind_ = CR_TEST_NORMAL, \ .param_ = (struct criterion_test_params(*)(void)) NULL, \ diff --git a/include/criterion/options.h b/include/criterion/options.h index 793d8c1..d8e3a0f 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -32,6 +32,34 @@ # include "logging.h" # include "internal/common.h" +enum criterion_debugger { + /** + * Do not run the underlying test in a debugger + */ + CR_DBG_NONE, + + /** + * Run the test with a debugging server compatible with the compiler + * it was built with. + */ + CR_DBG_NATIVE, + + /** + * Run the test with gdbserver + */ + CR_DBG_GDB, + + /** + * Run the test with lldb-server + */ + CR_DBG_LLDB, + + /** + * Run the test with windbg in server mode + */ + CR_DBG_WINDBG, +}; + struct criterion_options { /** @@ -125,6 +153,24 @@ struct criterion_options { * default: false */ bool crash; + + /** + * Whether criterion should run its tests in a debugging server. + * + * The server hangs until a connection from a debugger gets accepted. + * + * This forces jobs = 1 and crash = true. + * + * default: CR_DBG_NONE; + */ + enum criterion_debugger debug; + + /** + * The TCP port of the debugging server. + * + * default: 1234 + */ + unsigned debug_port; }; CR_BEGIN_C_API diff --git a/include/criterion/types.h b/include/criterion/types.h index 876f126..525d24c 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -59,6 +59,13 @@ enum criterion_test_kind { CR_TEST_PARAMETERIZED, }; +enum criterion_compiler { + CR_COMP_UNKNOWN, + CR_COMP_GCC, + CR_COMP_CLANG, + CR_COMP_MSVC, +}; + /** * Represents a set of parameters for a parameterized test. */ @@ -78,6 +85,7 @@ struct criterion_test_extra_data { * You've been warned. */ int sentinel_; + enum criterion_compiler compiler_; enum criterion_language lang_; enum criterion_test_kind kind_; struct criterion_test_params (*param_)(void); diff --git a/src/core/runner.c b/src/core/runner.c index 1feb226..e63d149 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -344,6 +344,11 @@ CR_API int criterion_run_all_tests(struct criterion_test_set *set) disable_unmatching(set); } + if (criterion_options.debug) { + criterion_options.jobs = 1; + criterion_options.crash = true; + } + int res = criterion_run_all_tests_impl(set); #ifndef ENABLE_VALGRIND_ERRORS diff --git a/src/core/runner_coroutine.c b/src/core/runner_coroutine.c index 0a264e2..0312874 100644 --- a/src/core/runner_coroutine.c +++ b/src/core/runner_coroutine.c @@ -271,10 +271,24 @@ static bxf_instance *run_test(struct run_next_context *ctx, .inherit.context = inst_ctx, }; -#if 0 - sp.debug.debugger = BXF_DBG_NATIVE; - sp.debug.tcp = 1234; -#endif + if (criterion_options.debug) { + enum bxf_debugger debugger = BXF_DBG_NONE; + if (criterion_options.debug == CR_DBG_NATIVE) { + switch (ctx->test->data->compiler_) { + case CR_COMP_GCC: debugger = BXF_DBG_GDB; break; + case CR_COMP_CLANG: debugger = BXF_DBG_LLDB; break; + case CR_COMP_MSVC: debugger = BXF_DBG_WINDBG; break; + default: break; + } + } else { + debugger = (enum bxf_debugger)(criterion_options.debug - 1); + } + if (!debugger) + cr_panic("Could not choose the debugger server for an " + "unknown compiler"); + sp.debug.debugger = debugger; + sp.debug.tcp = criterion_options.debug_port; + } if (ctx->suite_set->suite.data && ctx->suite_set->suite.data->timeout != 0) sp.quotas.runtime = ctx->suite_set->suite.data->timeout; diff --git a/src/entry/options.c b/src/entry/options.c index 45f768d..ac68d3d 100644 --- a/src/entry/options.c +++ b/src/entry/options.c @@ -27,4 +27,5 @@ CR_API struct criterion_options criterion_options = { .logging_threshold = CRITERION_IMPORTANT, .logger = &normal_logging, .measure_time = true, + .debug_port = 1234, }; diff --git a/src/entry/params.c b/src/entry/params.c index f642ab0..e710573 100644 --- a/src/entry/params.c +++ b/src/entry/params.c @@ -35,6 +35,7 @@ #include "io/output.h" #include "config.h" #include "common.h" +#include "err.h" #if ENABLE_NLS # include @@ -130,7 +131,31 @@ int atou(const char *str) { return res < 0 ? 0 : res; } -CR_API int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { +static enum criterion_debugger get_dbg(const char *arg) +{ + if (!arg) + return CR_DBG_NATIVE; + + static struct { char *name; enum criterion_debugger dbg; } values[] = { + { "gdb", CR_DBG_GDB }, + { "lldb", CR_DBG_LLDB }, + { "windbg", CR_DBG_WINDBG }, + }; + + for (size_t i = 0; i < 3; ++i) { + printf("arg = { %s, %d }\n", values[i].name, values[i].dbg); + if (!strcmp(values[i].name, arg)) { + printf("OK\n"); + return values[i].dbg; + } + } + + cr_panic("Invalid argument for --debug: %s.\n", arg); +} + +CR_API int criterion_handle_args(int argc, char *argv[], + bool handle_unknown_arg) +{ static struct option opts[] = { {"verbose", optional_argument, 0, 'b'}, {"quiet", no_argument, 0, 'q'}, @@ -151,6 +176,8 @@ CR_API int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg {"output", required_argument, 0, 'O'}, {"wait", no_argument, 0, 'w'}, {"crash", no_argument, 0, 'c'}, + {"debug", optional_argument, 0, 'd'}, + {"debug-transport", required_argument, 0, 'D'}, {0, 0, 0, 0 } }; @@ -242,6 +269,9 @@ CR_API int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg case 'p': criterion_options.pattern = optarg; break; case 'q': quiet = true; break; + case 'd': criterion_options.debug = get_dbg(optarg); break; + case 'D': criterion_options.debug_port = atou(optarg); break; + { const char *provider; case 't': provider = "tap"; goto provider_def;