From 5a1049ce2cdee2485c6bba4811cd8c23ad030390 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 4 Oct 2015 10:49:44 +0200 Subject: [PATCH] Added Objective-C language support --- .../CMakeDetermineObjectiveCCompiler.cmake | 54 +++++ .../Modules/CMakeObjectiveCCompiler.cmake.in | 10 + .../Modules/CMakeObjectiveCInformation.cmake | 187 ++++++++++++++++++ .../Modules/CMakeTestObjectiveCCompiler.cmake | 62 ++++++ .gitignore | 2 + CMakeLists.txt | 9 + src/config.h.in | 6 +- src/core/wrappers/wrap.m | 96 +++++++++ 8 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 .cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake create mode 100644 .cmake/Modules/CMakeObjectiveCCompiler.cmake.in create mode 100644 .cmake/Modules/CMakeObjectiveCInformation.cmake create mode 100644 .cmake/Modules/CMakeTestObjectiveCCompiler.cmake create mode 100644 src/core/wrappers/wrap.m diff --git a/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake new file mode 100644 index 0000000..613cd38 --- /dev/null +++ b/.cmake/Modules/CMakeDetermineObjectiveCCompiler.cmake @@ -0,0 +1,54 @@ +# Copyright (C) 2015 Franklin "Snaipe" Mathieu. +# Redistribution and use of this file is allowed according to the terms of the MIT license. +# For details see the LICENSE file distributed with Criterion. + +include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) + +if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") +elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") + set(CMAKE_ObjectiveC_COMPILER_XCODE_TYPE sourcecode.m) + _cmake_find_compiler_path(ObjectiveC) +else() + if(NOT CMAKE_ObjectiveC_COMPILER) + set(CMAKE_ObjectiveC_COMPILER_INIT NOTFOUND) + + if(NOT CMAKE_ObjectiveC_COMPILER_INIT) + set(CMAKE_ObjectiveC_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}gcc clang) + endif() + + _cmake_find_compiler(ObjectiveC) + else() + _cmake_find_compiler_path(ObjectiveC) + endif() + mark_as_advanced(CMAKE_ObjectiveC_COMPILER) + + set(CMAKE_ObjectiveC_COMPILER_ID_TEST_FLAGS_FIRST) + set(CMAKE_ObjectiveC_COMPILER_ID_TEST_FLAGS "-c") + +endif() + +if(NOT CMAKE_ObjectiveC_COMPILER_ID_RUN) + set(CMAKE_ObjectiveC_COMPILER_ID_RUN 1) + + # Try to identify the compiler. + set(CMAKE_ObjectiveC_COMPILER_ID) + set(CMAKE_ObjectiveC_PLATFORM_ID) + file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in + CMAKE_ObjectiveC_COMPILER_ID_PLATFORM_CONTENT) + + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) + + # we use the same compiler id source than C + CMAKE_DETERMINE_COMPILER_ID(ObjectiveC CFLAGS CMakeCCompilerId.c) + +endif() + +include(CMakeFindBinUtils) + +# configure variables set in this file for fast reload later on +configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeObjectiveCCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake + @ONLY + ) + +set(CMAKE_ObjectiveC_COMPILER_ENV_VAR "OBJCC") diff --git a/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in b/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in new file mode 100644 index 0000000..ab19736 --- /dev/null +++ b/.cmake/Modules/CMakeObjectiveCCompiler.cmake.in @@ -0,0 +1,10 @@ +set(CMAKE_ObjectiveC_COMPILER "@CMAKE_ObjectiveC_COMPILER@") +set(CMAKE_ObjectiveC_COMPILER_ID "@CMAKE_ObjectiveC_COMPILER_ID@") + +set(CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES "@CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES@") + +set(CMAKE_ObjectiveC_COMPILER_LOADED 1) +set(CMAKE_ObjectiveC_COMPILER_WORKS @CMAKE_ObjectiveC_COMPILER_WORKS@) + +set(CMAKE_ObjectiveC_COMPILER_ID_RUN 1) +set(CMAKE_ObjectiveC_SOURCE_FILE_EXTENSIONS m) diff --git a/.cmake/Modules/CMakeObjectiveCInformation.cmake b/.cmake/Modules/CMakeObjectiveCInformation.cmake new file mode 100644 index 0000000..ba3f47c --- /dev/null +++ b/.cmake/Modules/CMakeObjectiveCInformation.cmake @@ -0,0 +1,187 @@ +if(UNIX) + set(CMAKE_ObjectiveC_OUTPUT_EXTENSION .o) +else() + set(CMAKE_ObjectiveC_OUTPUT_EXTENSION .obj) +endif() + +set(_INCLUDED_FILE 0) +set(_INCLUDED_FILE_2 0) + +# Load compiler-specific information. +if(CMAKE_ObjectiveC_COMPILER_ID) + include(Compiler/${CMAKE_ObjectiveC_COMPILER_ID}-C OPTIONAL) +endif() + +set(CMAKE_BASE_NAME) +get_filename_component(CMAKE_BASE_NAME "${CMAKE_ObjectiveC_COMPILER}" NAME_WE) + +# load a hardware specific file, mostly useful for embedded compilers +if(CMAKE_SYSTEM_PROCESSOR) + if(CMAKE_ObjectiveC_COMPILER_ID) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-C-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-ObjectiveC-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE_2) + endif() + if (NOT _INCLUDED_FILE AND NOT _INCLUDED_FILE_2) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL) + endif () +endif() + +# load the system- and compiler specific files +if(CMAKE_ObjectiveC_COMPILER_ID) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-C + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_ObjectiveC_COMPILER_ID}-ObjectiveC + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE_2) +endif() +if (NOT _INCLUDED_FILE AND _INCLUDED_FILE_2) + include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} + OPTIONAL RESULT_VARIABLE _INCLUDED_FILE) +endif () + +# We specify the compiler information in the system file for some +# platforms, but this language may not have been enabled when the file +# was first included. Include it again to get the language info. +# Remove this when all compiler info is removed from system files. +if (NOT _INCLUDED_FILE) + include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) +endif () + +if(CMAKE_ObjectiveC_COMPILER_LINKS_STATICALLY) + set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) +endif() + +# This should be included before the _INIT variables are +# used to initialize the cache. Since the rule variables +# have if blocks on them, users can still define them here. +# But, it should still be after the platform file so changes can +# be made to those values. + +if(CMAKE_USER_MAKE_RULES_OVERRIDE) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}") +endif() + +if(CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE_ObjectiveC "${_override}") +endif() + + +# for most systems a module is the same as a shared library +# so unless the variable CMAKE_MODULE_EXISTS is set just +# copy the values from the LIBRARY variables +if(NOT CMAKE_MODULE_EXISTS) + set(CMAKE_SHARED_MODULE_ObjectiveC_FLAGS ${CMAKE_SHARED_LIBRARY_ObjectiveC_FLAGS}) + set(CMAKE_SHARED_MODULE_CREATE_ObjectiveC_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_ObjectiveC_FLAGS}) +endif() + +if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) +# default build type is none + if(NOT CMAKE_NO_BUILD_TYPE) + set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING + "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") + endif() + set (CMAKE_ObjectiveC_FLAGS_DEBUG "${CMAKE_ObjectiveC_FLAGS_DEBUG_INIT}" CACHE STRING + "Flags used by the compiler during debug builds.") + set (CMAKE_ObjectiveC_FLAGS_MINSIZEREL "${CMAKE_ObjectiveC_FLAGS_MINSIZEREL_INIT}" CACHE STRING + "Flags used by the compiler during release builds for minimum size.") + set (CMAKE_ObjectiveC_FLAGS_RELEASE "${CMAKE_ObjectiveC_FLAGS_RELEASE_INIT}" CACHE STRING + "Flags used by the compiler during release builds.") + set (CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO "${CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING + "Flags used by the compiler during release builds with debug info.") +endif() + +if(CMAKE_ObjectiveC_STANDARD_LIBRARIES_INIT) + set(CMAKE_ObjectiveC_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES_INIT}" + CACHE STRING "Libraries linked by default with all C applications.") + mark_as_advanced(CMAKE_ObjectiveC_STANDARD_LIBRARIES) +endif() + +include(CMakeCommonLanguageInclude) + +# now define the following rule variables + +# CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY +# CMAKE_ObjectiveC_CREATE_SHARED_MODULE +# CMAKE_ObjectiveC_COMPILE_OBJECT +# CMAKE_ObjectiveC_LINK_EXECUTABLE + +# variables supplied by the generator at use time +# +# the target without the suffix +# +# +# +# +# + +# C compiler information +# +# +# +# + +# Static library tools +# +# + + +# create a C shared library +if(NOT CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY) + set(CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY + " -o ") +endif() + +# create a C shared module just copy the shared library rule +if(NOT CMAKE_ObjectiveC_CREATE_SHARED_MODULE) + set(CMAKE_ObjectiveC_CREATE_SHARED_MODULE ${CMAKE_ObjectiveC_CREATE_SHARED_LIBRARY}) +endif() + +# Create a static archive incrementally for large object file counts. +# If CMAKE_ObjectiveC_CREATE_STATIObjectiveC_LIBRARY is set it will override these. +if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_CREATE) + set(CMAKE_ObjectiveC_ARCHIVE_CREATE " qc ") +endif() +if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_APPEND) + set(CMAKE_ObjectiveC_ARCHIVE_APPEND " q ") +endif() +if(NOT DEFINED CMAKE_ObjectiveC_ARCHIVE_FINISH) + set(CMAKE_ObjectiveC_ARCHIVE_FINISH " ") +endif() + +set(CMAKE_INCLUDE_FLAG_ObjectiveC "-I") +set(CMAKE_ObjectiveC_IMPLICIT_LINK_LIBRARIES objc) + +# compile a C file into an object file +if(NOT CMAKE_ObjectiveC_COMPILE_OBJECT) + set(CMAKE_ObjectiveC_COMPILE_OBJECT + " -o -c ") +endif() + +if(NOT CMAKE_ObjectiveC_LINK_EXECUTABLE) + set(CMAKE_ObjectiveC_LINK_EXECUTABLE + " -o ") +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG) + set(CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_ObjectiveC_FLAG}) +endif() + +if(NOT CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG_SEP) + set(CMAKE_EXECUTABLE_RUNTIME_ObjectiveC_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_ObjectiveC_FLAG_SEP}) +endif() + +if(NOT CMAKE_EXECUTABLE_RPATH_LINK_ObjectiveC_FLAG) + set(CMAKE_EXECUTABLE_RPATH_LINK_ObjectiveC_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_ObjectiveC_FLAG}) +endif() + +mark_as_advanced( + CMAKE_ObjectiveC_FLAGS + CMAKE_ObjectiveC_FLAGS_DEBUG + CMAKE_ObjectiveC_FLAGS_MINSIZEREL + CMAKE_ObjectiveC_FLAGS_RELEASE + CMAKE_ObjectiveC_FLAGS_RELWITHDEBINFO +) +set(CMAKE_ObjectiveC_INFORMATION_LOADED 1) diff --git a/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake b/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake new file mode 100644 index 0000000..e6d5ff1 --- /dev/null +++ b/.cmake/Modules/CMakeTestObjectiveCCompiler.cmake @@ -0,0 +1,62 @@ +if(CMAKE_ObjectiveC_COMPILER_FORCED) + # The compiler configuration was forced by the user. + # Assume the user has configured all compiler information. + set(CMAKE_ObjectiveC_COMPILER_WORKS TRUE) + return() +endif() + +include(CMakeTestCompilerCommon) + +# Remove any cached result from an older CMake version. +# We now store this in CMakeCCompiler.cmake. +unset(CMAKE_ObjectiveC_COMPILER_WORKS CACHE) + +# This file is used by EnableLanguage in cmGlobalGenerator to +# determine that that selected C compiler can actually compile +# and link the most basic of programs. If not, a fatal error +# is set and cmake stops processing commands and will not generate +# any makefiles or projects. +if(NOT CMAKE_ObjectiveC_COMPILER_WORKS) + PrintTestCompilerStatus("ObjectiveC" "") + file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testObjectiveCCompiler.m + "#ifdef __cplusplus\n" + "# error \"The CMAKE_ObjectiveC_COMPILER is set to an ObjectiveC++ compiler\"\n" + "#endif\n" + "int main(int argc, char* argv[])\n" + "{ (void)argv; return argc-1;}\n") +try_compile(CMAKE_ObjectiveC_COMPILER_WORKS ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testObjectiveCCompiler.m + OUTPUT_VARIABLE __CMAKE_ObjectiveC_COMPILER_OUTPUT) + # Move result from cache to normal variable. + set(CMAKE_ObjectiveC_COMPILER_WORKS ${CMAKE_ObjectiveC_COMPILER_WORKS}) + unset(CMAKE_ObjectiveC_COMPILER_WORKS CACHE) + set(ObjectiveC_TEST_WAS_RUN 1) +endif() + +if(NOT CMAKE_ObjectiveC_COMPILER_WORKS) + PrintTestCompilerStatus("ObjectiveC" " -- broken") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the ObjectiveC compiler works failed with " + "the following output:\n${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n") +message(FATAL_ERROR "The ObjectiveC compiler \"${CMAKE_ObjectiveC_COMPILER}\" " + "is not able to compile a simple test program.\nIt fails " + "with the following output:\n ${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n" + "CMake will not be able to correctly generate this project.") +else() + if(ObjectiveC_TEST_WAS_RUN) + PrintTestCompilerStatus("ObjectiveC" " -- works") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the ObjectiveC compiler works passed with " + "the following output:\n${__CMAKE_ObjectiveC_COMPILER_OUTPUT}\n\n") + endif() + + # Re-configure file + configure_file( + ${CMAKE_CURRENT_LIST_DIR}/CMakeObjectiveCCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake + @ONLY + ) + include(${CMAKE_PLATFORM_INFO_DIR}/CMakeObjectiveCCompiler.cmake) +endif() + +unset(__CMAKE_ObjectiveC_COMPILER_OUTPUT) diff --git a/.gitignore b/.gitignore index e28ebbf..55e2d53 100644 --- a/.gitignore +++ b/.gitignore @@ -10,11 +10,13 @@ !doc/* !*.c +!*.m !*.cc !*.h !*.rst !*.po !*.in +!.cmake/*.cmake !samples/tests/*.sh !samples/*.expected diff --git a/CMakeLists.txt b/CMakeLists.txt index 969a77c..e0313d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ if (NOT MSVC) endif () endif () + if (MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") endif () @@ -156,6 +157,14 @@ if (CMAKE_CXX_COMPILER_WORKS) set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.cc) endif () +if (CMAKE_ObjectiveC_COMPILER_WORKS) + set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} ${CMAKE_C_FLAGS} -fobjc-exceptions") + if (NOT WIN32) + set(CMAKE_ObjectiveC_FLAGS "${CMAKE_ObjectiveC_FLAGS} -fPIC") + endif () + set(SOURCE_FILES ${SOURCE_FILES} src/core/wrappers/wrap.m) +endif () + set(INTERFACE_FILES include/criterion/assert.h include/criterion/abort.h diff --git a/src/config.h.in b/src/config.h.in index 4bc9f70..fc91197 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -6,7 +6,11 @@ #cmakedefine ENABLE_VALGRIND_ERRORS @ENABLE_VALGRIND_ERRORS@ #cmakedefine CXX_BRIDGE @CXX_BRIDGE@ -#cmakedefine OBJC_BRIDGE @OBJC_BRIDGE@ +#cmakedefine OBJECTIVEC_BRIDGE @OBJECTIVEC_BRIDGE@ + +# ifdef OBJECTIVEC_BRIDGE +# define OBJC_BRIDGE OBJECTIVEC_BRIDGE +# endif # define LOCALEDIR "${LOCALEDIR}" # define PACKAGE "${PROJECT_NAME}" diff --git a/src/core/wrappers/wrap.m b/src/core/wrappers/wrap.m new file mode 100644 index 0000000..db3f75b --- /dev/null +++ b/src/core/wrappers/wrap.m @@ -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. + */ +#import + +#include "criterion/assert.h" +#include "criterion/event.h" + +#include "core/abort.h" +#include "core/report.h" +#include "core/worker.h" +#include "compat/time.h" +#include "wrap.h" +#include "common.h" + +static INLINE void nothing(void) {} + +void objc_wrap(struct criterion_test *test, struct criterion_suite *suite) { + + criterion_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 (NSException *e) { + NSString *reason = [e reason]; + criterion_test_die("Caught an unexpected exception during the test initialization: %s.", [reason UTF8String]); + } + @catch (...) { + criterion_test_die("Caught some unexpected exception during the test initialization."); + } + criterion_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 (NSException *e) { + NSString *reason = [e reason]; + criterion_test_die("Caught an unexpected exception during the test execution: %s.", [reason UTF8String]); + } + @catch (...) { + criterion_test_die("Caught some unexpected exception during the test execution."); + } + } + } + + double elapsed_time; + if (!timer_end(&elapsed_time, &ts)) + elapsed_time = -1; + + criterion_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 (NSException *e) { + NSString *reason = [e reason]; + criterion_test_die("Caught an unexpected exception during the test finalization: %s.", [reason UTF8String]); + } + @catch (...) { + criterion_test_die("Caught some unexpected exception during the test finalization."); + } + criterion_send_event(POST_FINI, NULL, 0); + +}