diff --git a/.gitmodules b/.gitmodules index 0b20d78..7f31cf0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "dependencies/nanomsg-patched"] path = dependencies/nanomsg-patched url = https://github.com/Snaipe/nanomsg.git +[submodule "dependencies/debugbreak"] + path = dependencies/debugbreak + url = https://github.com/scottt/debugbreak diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dbe90f..5e2c555 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ include_directories( dependencies/valgrind/include/ dependencies/klib/ dependencies/nanopb/ + dependencies/debugbreak/ ) # Coverage diff --git a/dependencies/debugbreak b/dependencies/debugbreak new file mode 160000 index 0000000..6b79ec8 --- /dev/null +++ b/dependencies/debugbreak @@ -0,0 +1 @@ +Subproject commit 6b79ec8d8f8d4603111f580a0537f8f31c484c32 diff --git a/include/criterion/options.h b/include/criterion/options.h index 2b45ed7..8b5a1a6 100644 --- a/include/criterion/options.h +++ b/include/criterion/options.h @@ -116,6 +116,14 @@ struct criterion_options { * default: false */ bool wait_for_clients; + + /** + * Raise a debug trap to crash the test if an assert fails so that a + * debugger can gain control. + * + * default: false + */ + bool crash; }; CR_BEGIN_C_API diff --git a/src/core/abort.c b/src/core/abort.c index b803101..76a4a6c 100644 --- a/src/core/abort.c +++ b/src/core/abort.c @@ -27,11 +27,16 @@ #include "protocol/messages.h" #include "criterion/internal/asprintf-compat.h" #include "criterion/criterion.h" +#include "criterion/options.h" #include "io/event.h" +#include "debugbreak.h" jmp_buf g_pre_test; void criterion_abort_test(void) { + if (criterion_options.crash) + debug_break(); + longjmp(g_pre_test, 1); } diff --git a/src/entry/params.c b/src/entry/params.c index b011956..7c15cd6 100644 --- a/src/entry/params.c +++ b/src/entry/params.c @@ -68,6 +68,8 @@ "prematurely after the test\n" \ " --verbose[=level]: sets verbosity to level " \ "(1 by default)\n" \ + " --crash: crash failing assertions rather than " \ + "aborting (for debugging purposes)\n" \ " -OP:F or --output=PROVIDER=FILE: write test " \ "report to FILE using the specified provider\n" @@ -148,6 +150,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { {"no-early-exit", no_argument, 0, 'z'}, {"output", required_argument, 0, 'O'}, {"wait", no_argument, 0, 'w'}, + {"crash", no_argument, 0, 'c'}, {0, 0, 0, 0 } }; @@ -271,6 +274,7 @@ int criterion_handle_args(int argc, char *argv[], bool handle_unknown_arg) { } break; case 'w': criterion_options.wait_for_clients = true; break; case '?': + case 'c': criterion_options.crash = true; break; default : do_print_usage = handle_unknown_arg; break; } } diff --git a/test/cram/help.t b/test/cram/help.t index 82cb722..f676e94 100644 --- a/test/cram/help.t +++ b/test/cram/help.t @@ -19,6 +19,7 @@ Display the help message --always-succeed: always exit with 0 --no-early-exit: do not exit the test worker prematurely after the test --verbose[=level]: sets verbosity to level (1 by default) + --crash: crash failing assertions rather than aborting (for debugging purposes) -OP:F or --output=PROVIDER=FILE: write test report to FILE using the specified provider $ simple.cc.bin --help @@ -40,6 +41,7 @@ Display the help message --always-succeed: always exit with 0 --no-early-exit: do not exit the test worker prematurely after the test --verbose[=level]: sets verbosity to level (1 by default) + --crash: crash failing assertions rather than aborting (for debugging purposes) -OP:F or --output=PROVIDER=FILE: write test report to FILE using the specified provider