From 4dcde5259cd241791f288da8c6864b2673c71ab7 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 1 Oct 2015 15:05:22 +0200 Subject: [PATCH] Added C/C++ language isolation wrappers --- CMakeLists.txt | 3 ++ include/criterion/criterion.h | 3 ++ include/criterion/types.h | 6 +++ src/core/runner.c | 35 +++---------- src/core/wrappers/wrap.c | 65 ++++++++++++++++++++++++ src/core/wrappers/wrap.cc | 96 +++++++++++++++++++++++++++++++++++ src/core/wrappers/wrap.h | 36 +++++++++++++ 7 files changed, 216 insertions(+), 28 deletions(-) create mode 100644 src/core/wrappers/wrap.c create mode 100644 src/core/wrappers/wrap.cc create mode 100644 src/core/wrappers/wrap.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 71ae77d..8a9e1bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ add_definitions(-DCRITERION_BUILDING_DLL=1) if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -g -std=gnu99") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -std=c++11") endif () if (MSVC) @@ -84,6 +85,8 @@ find_package(PCRE) # List sources and headers set(SOURCE_FILES + src/core/wrappers/wrap.c + src/core/wrappers/wrap.cc src/core/abort.c src/core/abort.h src/core/report.c diff --git a/include/criterion/criterion.h b/include/criterion/criterion.h index db9dfdc..6182434 100644 --- a/include/criterion/criterion.h +++ b/include/criterion/criterion.h @@ -36,9 +36,11 @@ # ifdef __cplusplus # define TEST_PROTOTYPE_(Category, Name) \ extern "C" void IDENTIFIER_(Category, Name, impl)(void) +# define CR_LANG CR_LANG_CPP # else # define TEST_PROTOTYPE_(Category, Name) \ void IDENTIFIER_(Category, Name, impl)(void) +# define CR_LANG CR_LANG_C # endif # define SUITE_IDENTIFIER_(Name, Suffix) \ @@ -49,6 +51,7 @@ TEST_PROTOTYPE_(Category, Name); \ struct criterion_test_extra_data IDENTIFIER_(Category, Name, extra) = \ CR_EXPAND(CRITERION_MAKE_STRUCT(struct criterion_test_extra_data, \ + .lang_ = CR_LANG, \ .kind_ = CR_TEST_NORMAL, \ .param_ = (struct criterion_test_params(*)(void)) NULL, \ .identifier_ = #Category "/" #Name, \ diff --git a/include/criterion/types.h b/include/criterion/types.h index a28d833..3354098 100644 --- a/include/criterion/types.h +++ b/include/criterion/types.h @@ -35,6 +35,11 @@ using std::size_t; # endif # include "common.h" +enum criterion_language { + CR_LANG_C, + CR_LANG_CPP, +}; + enum criterion_test_kind { CR_TEST_NORMAL, CR_TEST_PARAMETERIZED, @@ -84,6 +89,7 @@ struct criterion_test_params { struct criterion_test_extra_data { int sentinel_; + enum criterion_language lang_; enum criterion_test_kind kind_; struct criterion_test_params (*param_)(void); const char *identifier_; diff --git a/src/core/runner.c b/src/core/runner.c index ca72f17..9e2d08e 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -34,6 +34,7 @@ #include "compat/time.h" #include "compat/posix.h" #include "compat/processor.h" +#include "wrappers/wrap.h" #include "string/i18n.h" #include "io/event.h" #include "runner_coroutine.h" @@ -156,6 +157,11 @@ struct criterion_test_set *criterion_init(void) { return set; } +f_wrapper *g_wrappers[] = { + [CR_LANG_C] = c_wrap, + [CR_LANG_CPP] = cpp_wrap, +}; + void run_test_child(struct criterion_test *test, struct criterion_suite *suite) { @@ -168,34 +174,7 @@ void run_test_child(struct criterion_test *test, else if (test->data->timeout != 0) setup_timeout((uint64_t) (test->data->timeout * 1e9)); - send_event(PRE_INIT, NULL, 0); - if (suite->data) - (suite->data->init ? suite->data->init : nothing)(); - (test->data->init ? test->data->init : nothing)(); - send_event(PRE_TEST, NULL, 0); - - struct timespec_compat ts; - if (!setjmp(g_pre_test)) { - timer_start(&ts); - if (test->test) { - if (!test->data->param_) { - test->test(); - } else { - void(*param_test_func)(void *) = (void(*)(void*)) test->test; - param_test_func(g_worker_context.param->ptr); - } - } - } - - double elapsed_time; - if (!timer_end(&elapsed_time, &ts)) - elapsed_time = -1; - - send_event(POST_TEST, &elapsed_time, sizeof (double)); - (test->data->fini ? test->data->fini : nothing)(); - if (suite->data) - (suite->data->fini ? suite->data->fini : nothing)(); - send_event(POST_FINI, NULL, 0); + g_wrappers[test->data->lang_](test, suite); } #define push_event(Kind, ...) \ diff --git a/src/core/wrappers/wrap.c b/src/core/wrappers/wrap.c new file mode 100644 index 0000000..01acf62 --- /dev/null +++ b/src/core/wrappers/wrap.c @@ -0,0 +1,65 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 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. + */ +#include "core/abort.h" +#include "core/stats.h" +#include "core/worker.h" +#include "core/report.h" +#include "compat/time.h" +#include "io/event.h" +#include "wrap.h" + +static INLINE void nothing(void) {} + +void c_wrap(struct criterion_test *test, struct criterion_suite *suite) { + + send_event(PRE_INIT, NULL, 0); + if (suite->data) + (suite->data->init ? suite->data->init : nothing)(); + (test->data->init ? test->data->init : nothing)(); + send_event(PRE_TEST, NULL, 0); + + struct timespec_compat ts; + if (!setjmp(g_pre_test)) { + timer_start(&ts); + if (test->test) { + if (!test->data->param_) { + test->test(); + } else { + void(*param_test_func)(void *) = (void(*)(void*)) test->test; + param_test_func(g_worker_context.param->ptr); + } + } + } + + double elapsed_time; + if (!timer_end(&elapsed_time, &ts)) + elapsed_time = -1; + + send_event(POST_TEST, &elapsed_time, sizeof (double)); + (test->data->fini ? test->data->fini : nothing)(); + if (suite->data) + (suite->data->fini ? suite->data->fini : nothing)(); + send_event(POST_FINI, NULL, 0); + +} diff --git a/src/core/wrappers/wrap.cc b/src/core/wrappers/wrap.cc new file mode 100644 index 0000000..386e3eb --- /dev/null +++ b/src/core/wrappers/wrap.cc @@ -0,0 +1,96 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 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. + */ +#include +#include "criterion/assert.h" + +extern "C" { + +#include "core/abort.h" +#include "core/stats.h" +#include "core/worker.h" +#include "core/report.h" +#include "compat/time.h" +#include "io/event.h" +#include "wrap.h" + +static INLINE void nothing(void) {} + +void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite) { + + send_event(PRE_INIT, NULL, 0); + try { + if (suite->data) + (suite->data->init ? suite->data->init : nothing)(); + (test->data->init ? test->data->init : nothing)(); + } catch (const std::exception &e) { + cr_assert_fail("Caught an unexpected exception during the test initialization: %s.", e.what()); + std::exit(1); + } catch (...) { + cr_assert_fail("Caught some unexpected exception during the test initialization."); + std::exit(1); + } + send_event(PRE_TEST, NULL, 0); + + struct timespec_compat ts; + if (!setjmp(g_pre_test)) { + timer_start(&ts); + if (test->test) { + try { + if (!test->data->param_) { + test->test(); + } else { + void(*param_test_func)(void *) = (void(*)(void*)) test->test; + param_test_func(g_worker_context.param->ptr); + } + } catch (const std::exception &e) { + cr_assert_fail("Caught an unexpected exception during the test execution: %s.", e.what()); + std::exit(1); + } catch (...) { + cr_assert_fail("Caught some unexpected exception during the test execution."); + std::exit(1); + } + } + } + + double elapsed_time; + if (!timer_end(&elapsed_time, &ts)) + elapsed_time = -1; + + send_event(POST_TEST, &elapsed_time, sizeof (double)); + try { + (test->data->fini ? test->data->fini : nothing)(); + if (suite->data) + (suite->data->fini ? suite->data->fini : nothing)(); + } catch (const std::exception &e) { + cr_assert_fail("Caught an unexpected exception during the test finalization: %s.", e.what()); + std::exit(1); + } catch (...) { + cr_assert_fail("Caught some unexpected exception during the test finalization."); + std::exit(1); + } + send_event(POST_FINI, NULL, 0); + +} + +} diff --git a/src/core/wrappers/wrap.h b/src/core/wrappers/wrap.h new file mode 100644 index 0000000..b7d518f --- /dev/null +++ b/src/core/wrappers/wrap.h @@ -0,0 +1,36 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2015 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 WRAP_H_ +# define WRAP_H_ + +# include "criterion/types.h" + +typedef void (f_wrapper)(struct criterion_test *, struct criterion_suite *); + +void c_wrap(struct criterion_test *test, struct criterion_suite *suite); +void cpp_wrap(struct criterion_test *test, struct criterion_suite *suite); + +extern f_wrapper *g_wrappers[]; + +#endif /* !WRAP_H_ */