Added C/C++ language isolation wrappers

This commit is contained in:
Snaipe 2015-10-01 15:05:22 +02:00
parent fb6b0a6eaf
commit 4dcde5259c
7 changed files with 216 additions and 28 deletions

View file

@ -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

View file

@ -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, \

View file

@ -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_;

View file

@ -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, ...) \

65
src/core/wrappers/wrap.c Normal file
View file

@ -0,0 +1,65 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 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.
*/
#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);
}

96
src/core/wrappers/wrap.cc Normal file
View file

@ -0,0 +1,96 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 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.
*/
#include <exception>
#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);
}
}

36
src/core/wrappers/wrap.h Normal file
View file

@ -0,0 +1,36 @@
/*
* The MIT License (MIT)
*
* Copyright © 2015 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 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_ */