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_ */