Replace Criterion by CUnit

Signed-off-by: Jeroen Koekkoek <jeroen@koekkoek.nl>
This commit is contained in:
Jeroen Koekkoek 2018-12-04 23:01:46 +01:00
parent 60752b3fd8
commit 74a48c5731
47 changed files with 4486 additions and 5388 deletions

View file

@ -174,20 +174,22 @@ function(process_cunit_source_file SOURCE_FILE HEADER_FILE SUITES TESTS)
endforeach()
# Propagate suites, tests and theories extracted from the source file.
list(REMOVE_DUPLICATES suites_wo_init_n_clean)
list(SORT suites_wo_init_n_clean)
foreach(suite ${suites_wo_init_n_clean})
set(init "FALSE")
set(clean "FALSE")
if(${suite} IN_LIST suites_w_init)
set(init "TRUE")
endif()
if(${suite} IN_LIST suites_w_deinit)
set(clean "TRUE")
endif()
if(suites_wo_init_n_clean)
list(REMOVE_DUPLICATES suites_wo_init_n_clean)
list(SORT suites_wo_init_n_clean)
foreach(suite ${suites_wo_init_n_clean})
set(init "FALSE")
set(clean "FALSE")
if(${suite} IN_LIST suites_w_init)
set(init "TRUE")
endif()
if(${suite} IN_LIST suites_w_deinit)
set(clean "TRUE")
endif()
list(APPEND suites "${suite}:${init}:${clean}")
endforeach()
list(APPEND suites "${suite}:${init}:${clean}")
endforeach()
endif()
if(theories)
set(${HEADER_FILE} "${header}" PARENT_SCOPE)

View file

@ -1,96 +0,0 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
find_package(Criterion REQUIRED)
include(Glob)
set(_criterion_dir "${CMAKE_CURRENT_LIST_DIR}/Criterion")
function(add_criterion_executable _target)
# Retrieve location of shared libary, which is need to extend the PATH
# environment variable on Microsoft Windows, so that the operating
# system can locate the .dll that it was linked against.
get_target_property(CRITERION_LIBRARY_TYPE Criterion TYPE)
get_target_property(CRITERION_IMPORTED_LOCATION Criterion IMPORTED_LOCATION)
get_filename_component(CRITERION_LIBRARY_DIR "${CRITERION_IMPORTED_LOCATION}" PATH)
set(s "[ \t\r\n]") # space
set(w "[0-9a-zA-Z_]") # word
set(b "[^0-9a-zA-Z_]") # boundary
set(arg "${s}*(${w}+)${s}*")
set(test "(^|${b})Test${s}*\\(${arg},${arg}(,[^\\)]+)?\\)") # Test
set(params "${s}*\\([^\\)]*\\)${s}*")
set(theory "(^|${b})Theory${s}*\\(${params},${arg},${arg}(,[^\\)]+)?\\)") # Theory
set(paramtest "(^|${b})ParameterizedTest${s}*\\([^,]+,${arg},${arg}(,[^\\)]+)?\\)") # ParameterizedTest
glob(_files "c" ${ARGN})
foreach(_file ${_files})
file(READ "${_file}" _contents)
string(REGEX MATCHALL "${test}" _matches "${_contents}")
list(APPEND _sources "${_file}")
list(LENGTH _matches _length)
if(_length)
foreach(_match ${_matches})
string(REGEX REPLACE "${test}" "\\2" _suite "${_match}")
string(REGEX REPLACE "${test}" "\\3" _name "${_match}")
list(APPEND _tests "${_suite}:${_name}")
endforeach()
endif()
string(REGEX MATCHALL "${theory}" _matches "${_contents}")
list(LENGTH _matches _length)
if(_length)
foreach(_match ${_matches})
string(REGEX REPLACE "${theory}" "\\2" _suite "${_match}")
string(REGEX REPLACE "${theory}" "\\3" _name "${_match}")
list(APPEND _tests "${_suite}:${_name}")
endforeach()
endif()
string(REGEX MATCHALL "${paramtest}" _matches "${_contents}")
list(LENGTH _matches _length)
if(_length)
foreach(_match ${_matches})
string(REGEX REPLACE "${paramtest}" "\\2" _suite "${_match}")
string(REGEX REPLACE "${paramtest}" "\\3" _name "${_match}")
list(APPEND _tests "${_suite}:${_name}")
endforeach()
endif()
endforeach()
add_executable(${_target} "${_criterion_dir}/src/runner.c" ${_sources})
target_link_libraries(${_target} Criterion)
foreach(_entry ${_tests})
string(REPLACE ":" ";" _entry ${_entry})
list(GET _entry 0 _suite)
list(GET _entry 1 _name)
add_test(
NAME "Criterion_${_suite}_${_name}"
COMMAND ${_target} -j1 --suite ${_suite} --test ${_name} --cunit=${_suite}-${_name} --quiet)
set_tests_properties("Criterion_${_suite}_${_name}" PROPERTIES TIMEOUT 10)
if(APPLE)
set_property(
TEST "Criterion_${_suite}_${_name}"
PROPERTY ENVIRONMENT "DYLD_LIBRARY_PATH=${CRITERION_LIBRARY_DIR}:$ENV{DYLD_LIBRARY_PATH}")
endif()
if(WIN32 AND ${CRITERION_LIBRARY_TYPE} STREQUAL "SHARED_LIBRARY")
set_property(
TEST "Criterion_${_suite}_${_name}"
PROPERTY ENVIRONMENT "PATH=${CRITERION_LIBRARY_DIR};$ENV{PATH}")
endif()
endforeach()
endfunction()

View file

@ -1,475 +0,0 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <criterion/criterion.h>
#include <criterion/hooks.h>
#include <criterion/internal/ordered-set.h>
#ifdef _WIN32
#include <stdlib.h>
#define LF "\r\n"
#define NAME_MAX _MAX_FNAME
#else
#define LF "\n"
#endif
static const char *suitepat = "*";
static const char *testpat = "*";
static char runfn[NAME_MAX + 1] = { 0 };
static char listfn[NAME_MAX + 1] = { 0 };
static char stamp[64] = { 0 };
static const char
run_hdr[] =
"<?xml version=\"1.0\" ?>" LF
"<?xml-stylesheet type=\"text/xsl\" href=\"CUnit-Run.xsl\" ?>" LF
"<!DOCTYPE CUNIT_TEST_RUN_REPORT SYSTEM \"CUnit-Run.dtd\">" LF
"<CUNIT_TEST_RUN_REPORT>" LF
" <CUNIT_HEADER/>" LF;
/* TODO: Criterion version number is not available in any of the header files,
but print_version() is. The function prints a message along the lines
of: Tests compiled with Criterion v2.3.2. The version number therefore
can be retrieved by temporarily swapping out stdout for a FILE handle
opened by open_memstream. However, I don't consider the version number
important enough to go through all that trouble. */
static const char
run_ftr[] =
" <CUNIT_FOOTER> File Generated By Criterion - %s </CUNIT_FOOTER>" LF
"</CUNIT_TEST_RUN_REPORT>";
static const char
run_result_hdr[] =
" <CUNIT_RESULT_LISTING>" LF;
static const char
run_result_ftr[] =
" </CUNIT_RESULT_LISTING>" LF;
static const char
run_suite_hdr[] =
" <CUNIT_RUN_SUITE>" LF
" <CUNIT_RUN_SUITE_SUCCESS>" LF
" <SUITE_NAME> %s </SUITE_NAME>" LF;
static const char
run_suite_ftr[] =
" </CUNIT_RUN_SUITE_SUCCESS>" LF
" </CUNIT_RUN_SUITE>" LF;
static const char
run_test_hdr[] =
" <CUNIT_RUN_TEST_RECORD>" LF;
static const char
run_test_ftr[] =
" </CUNIT_RUN_TEST_RECORD>" LF;
static const char
run_test_ok[] =
" <CUNIT_RUN_TEST_SUCCESS>" LF
" <TEST_NAME> %s </TEST_NAME>" LF
" </CUNIT_RUN_TEST_SUCCESS>" LF;
static const char
run_test_nok[] =
" <CUNIT_RUN_TEST_FAILURE>" LF
" <TEST_NAME> %s </TEST_NAME>" LF
" <FILE_NAME> %s </FILE_NAME>" LF
" <LINE_NUMBER> %u </LINE_NUMBER>" LF
" <CONDITION> %s </CONDITION>" LF
" </CUNIT_RUN_TEST_FAILURE>" LF;
static const char
run_stats[] =
" <CUNIT_RUN_SUMMARY>" LF
" <CUNIT_RUN_SUMMARY_RECORD>" LF
" <TYPE> Suites </TYPE>" LF
" <TOTAL> %zu </TOTAL>" LF
" <RUN> %zu </RUN>" LF
" <SUCCEEDED> - NA - </SUCCEEDED>" LF
" <FAILED> %zu </FAILED>" LF
" <INACTIVE> %zu </INACTIVE>" LF
" </CUNIT_RUN_SUMMARY_RECORD>" LF
" <CUNIT_RUN_SUMMARY_RECORD>" LF
" <TYPE> Test Cases </TYPE>" LF
" <TOTAL> %zu </TOTAL>" LF
" <RUN> %zu </RUN>" LF
" <SUCCEEDED> %zu </SUCCEEDED>" LF
" <FAILED> %zu </FAILED>" LF
" <INACTIVE> %zu </INACTIVE>" LF
" </CUNIT_RUN_SUMMARY_RECORD>" LF
" <CUNIT_RUN_SUMMARY_RECORD>" LF
" <TYPE> Assertions </TYPE>" LF
" <TOTAL> %zu </TOTAL>" LF
" <RUN> %zu </RUN>" LF
" <SUCCEEDED> %zu </SUCCEEDED>" LF
" <FAILED> %zu </FAILED>" LF
" <INACTIVE> n/a </INACTIVE>" LF
" </CUNIT_RUN_SUMMARY_RECORD>" LF
" </CUNIT_RUN_SUMMARY>" LF;
static const char
list_hdr[] =
"<?xml version=\"1.0\" ?>" LF
"<?xml-stylesheet type=\"text/xsl\" href=\"CUnit-List.xsl\" ?>" LF
"<!DOCTYPE CUNIT_TEST_LIST_REPORT SYSTEM \"CUnit-List.dtd\">" LF
"<CUNIT_TEST_LIST_REPORT>" LF
" <CUNIT_HEADER/>" LF;
/* TODO: Criterion version number not available. See previous comment. */
static const char
list_ftr[] =
" <CUNIT_FOOTER> File Generated By Criterion - %s </CUNIT_FOOTER>" LF
"</CUNIT_TEST_LIST_REPORT>";
static const char
list_stats[] =
" <CUNIT_LIST_TOTAL_SUMMARY>" LF
" <CUNIT_LIST_TOTAL_SUMMARY_RECORD>" LF
" <CUNIT_LIST_TOTAL_SUMMARY_RECORD_TEXT> Total Number of Suites </CUNIT_LIST_TOTAL_SUMMARY_RECORD_TEXT>" LF
" <CUNIT_LIST_TOTAL_SUMMARY_RECORD_VALUE> %zu </CUNIT_LIST_TOTAL_SUMMARY_RECORD_VALUE>" LF
" </CUNIT_LIST_TOTAL_SUMMARY_RECORD>" LF
" <CUNIT_LIST_TOTAL_SUMMARY_RECORD>" LF
" <CUNIT_LIST_TOTAL_SUMMARY_RECORD_TEXT> Total Number of Test Cases </CUNIT_LIST_TOTAL_SUMMARY_RECORD_TEXT>" LF
" <CUNIT_LIST_TOTAL_SUMMARY_RECORD_VALUE> %zu </CUNIT_LIST_TOTAL_SUMMARY_RECORD_VALUE>" LF
" </CUNIT_LIST_TOTAL_SUMMARY_RECORD>" LF
" </CUNIT_LIST_TOTAL_SUMMARY>" LF;
static const char
list_suites_hdr[] =
" <CUNIT_ALL_TEST_LISTING_SUITE>" LF;
static const char
list_suites_ftr[] =
" </CUNIT_ALL_TEST_LISTING_SUITE>" LF;
static const char
list_suite_hdr[] =
" <CUNIT_ALL_TEST_LISTING_SUITE>" LF
" <CUNIT_ALL_TEST_LISTING_SUITE_DEFINITION>" LF
" <SUITE_NAME> %s </SUITE_NAME>" LF
" <INITIALIZE_VALUE> %s </INITIALIZE_VALUE>" LF
" <CLEANUP_VALUE> %s </CLEANUP_VALUE>" LF
" <ACTIVE_VALUE> %s </ACTIVE_VALUE>" LF
" <TEST_COUNT_VALUE> %zu </TEST_COUNT_VALUE>" LF
" </CUNIT_ALL_TEST_LISTING_SUITE_DEFINITION>" LF
" <CUNIT_ALL_TEST_LISTING_SUITE_TESTS>" LF;
static const char
list_suite_ftr[] =
" </CUNIT_ALL_TEST_LISTING_SUITE_TESTS>" LF
" </CUNIT_ALL_TEST_LISTING_SUITE>" LF;
static const char
list_test[] =
" <TEST_CASE_DEFINITION>" LF
" <TEST_CASE_NAME> %s </TEST_CASE_NAME>" LF
" <TEST_ACTIVE_VALUE> %s </TEST_ACTIVE_VALUE>" LF
" </TEST_CASE_DEFINITION>" LF;
static void
print_run_test_stats(FILE *file, struct criterion_test_stats *stats)
{
struct criterion_assert_stats *itr;
(void)fprintf(file, run_test_hdr);
if (stats->test_status == CR_STATUS_PASSED) {
(void)fprintf(file, run_test_ok, stats->test->name);
} else if (stats->test_status == CR_STATUS_FAILED) {
for (itr = stats->asserts; itr != NULL; itr = itr->next) {
if (!itr->passed) {
(void)fprintf(
file,
run_test_nok,
stats->test->name,
itr->file,
itr->line,
itr->message);
break;
}
}
}
(void)fprintf(file, run_test_ftr);
}
static void
print_run_suite_stats(FILE *file, struct criterion_suite_stats *stats)
{
struct criterion_test_stats *itr;
(void)fprintf(file, run_suite_hdr, stats->suite->name);
for (itr = stats->tests; itr != NULL; itr = itr->next) {
if (itr->test_status != CR_STATUS_SKIPPED) {
print_run_test_stats(file, itr);
}
}
(void)fprintf(file, run_suite_ftr);
}
static void
print_run_stats(FILE *file, struct criterion_global_stats *stats)
{
size_t suites_failed = 0;
size_t suites_passed = 0;
struct criterion_suite_stats *itr;
(void)fprintf(file, run_hdr);
(void)fprintf(file, run_result_hdr);
for (itr = stats->suites; itr != NULL; itr = itr->next) {
if (itr->tests_skipped != itr->nb_tests) {
print_run_suite_stats(file, itr);
if (itr->tests_failed == itr->nb_tests) {
suites_failed++;
} else {
suites_passed++;
}
}
}
(void)fprintf(file, run_result_ftr);
(void)fprintf(
file,
run_stats,
stats->nb_suites,
suites_passed,
suites_failed,
(stats->nb_suites - (suites_passed - suites_failed)),
stats->nb_tests,
(stats->tests_passed + stats->tests_failed + stats->tests_crashed),
stats->tests_passed,
(stats->tests_failed + stats->tests_crashed),
stats->tests_skipped,
stats->nb_asserts,
(stats->asserts_passed + stats->asserts_failed),
stats->asserts_passed,
stats->asserts_failed);
(void)fprintf(file, run_ftr, stamp);
}
static void
print_list_test_stats(FILE *file, struct criterion_test_stats *stats)
{
(void)fprintf(
file,
list_test,
stats->test->name,
(stats->test_status == CR_STATUS_SKIPPED ? "No" : "Yes"));
}
static void
print_list_suite_stats(FILE *file, struct criterion_suite_stats *stats)
{
struct criterion_test_stats *itr;
(void)fprintf(
file,
list_suite_hdr,
stats->suite->name,
"No", // <INITIALIZE_VALUE />
"No", // <CLEANUP_VALUE />
(stats->nb_tests == stats->tests_skipped ? "No" : "Yes"),
stats->nb_tests);
for (itr = stats->tests; itr != NULL; itr = itr->next) {
print_list_test_stats(file, itr);
}
(void)fprintf(file, list_suite_ftr);
}
static void
print_list_stats(FILE *file, struct criterion_global_stats *stats)
{
struct criterion_suite_stats *itr;
(void)fprintf(file, list_hdr);
(void)fprintf(file, list_stats, stats->nb_suites, stats->nb_tests);
(void)fprintf(file, list_suites_hdr);
for (itr = stats->suites; itr != NULL; itr = itr->next) {
print_list_suite_stats(file, itr);
}
(void)fprintf(file, list_suites_ftr);
(void)fprintf(file, list_ftr, stamp);
}
static int
patmatch(
const char *pat,
const char *str)
{
while (*pat) {
if (*pat == '?') {
/* any character will do */
if (*str++ == 0) {
return 0;
}
pat++;
} else if (*pat == '*') {
/* collapse a sequence of wildcards, requiring as many
characters in str as there are ?s in the sequence */
while (*pat == '*' || *pat == '?') {
if (*pat == '?' && *str++ == 0) {
return 0;
}
pat++;
}
/* try matching on all positions where str matches pat */
while (*str) {
if (*str == *pat && patmatch(pat+1, str+1)) {
return 1;
}
str++;
}
return *pat == 0;
} else {
/* only an exact match */
if (*str++ != *pat++) {
return 0;
}
}
}
return *str == 0;
}
/* Criterion actually prescribes */
ReportHook(POST_ALL)(struct criterion_global_stats *stats)
{
FILE *runfh, *listfh;
if (listfn[0] != '\0' && runfn[0] != '\0') {
runfh = NULL;
listfh = NULL;
if ((runfh = fopen(runfn, "w")) != NULL &&
(listfh = fopen(listfn, "w")) != NULL)
{
print_run_stats(runfh, stats);
print_list_stats(listfh, stats);
} else {
(void)fprintf(stderr, "Cannot write results in CUnit format\n");
}
if (runfh != NULL) {
(void)fclose(runfh);
}
if (listfh != NULL) {
(void)fclose(listfh);
}
}
}
#if defined(_WIN32)
__declspec(dllexport)
#endif
int
main(int argc, char *argv[])
{
int result = 0;
int argno, cr_argc, sz;
char *pfx, **cr_argv;
const char runfmt[] = "%s-Results.xml";
const char listfmt[] = "%s-Listing.xml";
const char stampfmt[] = "%a %b %e %H:%M:%S %Y";
time_t now;
/* Before handing over argc and argv over to criterion, go over the list to
extract the custom options. Note that these are meant to be "hidden" */
cr_argc = 0;
if ((cr_argv = calloc((unsigned)argc, sizeof(*cr_argv))) == NULL) {
result = 1;
} else {
for (argno = 0; argno < argc; argno++) {
/* FIXME:
Eventually CUnit output format should be supported through an
actual logger implementation, but it will do for now.
See: http://criterion.readthedocs.io/en/master/output.html */
if (strncmp(argv[argno], "--cunit", 7) == 0) {
if ((pfx = strchr(argv[argno], '=')) != NULL) {
pfx++;
} else {
pfx = "CriterionAutomated";
}
sz = snprintf(runfn, sizeof(runfn), runfmt, pfx);
assert(sz > 0 && sz < (int)sizeof(runfn));
sz = snprintf(listfn, sizeof(listfn), listfmt, pfx);
assert(sz > 0 && sz < (int)sizeof(listfn));
now = time(NULL);
sz = (int)strftime(
stamp, sizeof(stamp), stampfmt, localtime(&now));
assert(sz != 0);
(void)sz;
} else if (strncmp(argv[argno], "--suite", 7) == 0) {
if ((argno + 1) == argc) {
fprintf(stderr, "--suite requires an argument\n");
result = 1;
goto bail;
}
suitepat = (const char *)argv[++argno];
} else if (strncmp(argv[argno], "--test", 6) == 0) {
if ((argno + 1) == argc) {
fprintf(stderr, "--test requires an argument\n");
result = 1;
goto bail;
}
testpat = (const char *)argv[++argno];
} else {
cr_argv[cr_argc++] = argv[argno];
}
}
/* FIXME: Depending on internal knowledge is not very pretty, but it is
the only way to provide a filter that will work on both *nix
and non-*nix platforms. */
struct criterion_test_set *tests = criterion_initialize();
struct criterion_ordered_set_node *suite_itr, *test_itr;
struct criterion_suite_set *suite;
struct criterion_test *test;
for (suite_itr = tests->suites->first;
suite_itr != NULL;
suite_itr = suite_itr->next)
{
suite = (struct criterion_suite_set *)(suite_itr + 1);
for (test_itr = suite->tests->first;
test_itr != NULL;
test_itr = test_itr->next)
{
test = (struct criterion_test *)(test_itr + 1);
if (!patmatch(suitepat, test->category) ||
!patmatch(testpat, test->name))
{
test->data->disabled = true;
}
}
}
if (criterion_handle_args(cr_argc, cr_argv, true)) {
result = !criterion_run_all_tests(tests);
}
criterion_finalize(tests);
bail:
free(cr_argv);
}
return result;
}

View file

@ -1,61 +0,0 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
find_path(CRITERION_INCLUDE_DIR criterion/criterion.h)
find_library(CRITERION_LIBRARY criterion)
mark_as_advanced(CRITERION_INCLUDE_DIR)
# Criterion does not define the version number anywhere.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Criterion DEFAULT_MSG CRITERION_LIBRARY CRITERION_INCLUDE_DIR)
if(CRITERION_FOUND)
set(CRITERION_INCLUDE_DIRS ${CRITERION_INCLUDE_DIR})
set(CRITERION_LIBRARIES ${CRITERION_LIBRARY})
if(WIN32)
get_filename_component(CRITERION_LIBRARY_DIR "${CRITERION_LIBRARY}}" PATH)
get_filename_component(CRITERION_BASENAME "${CRITERION_LIBRARY}}" NAME_WE)
get_filename_component(CRITERION_PREFIX "${CRITERION_LIBRARY_DIR}" PATH)
find_program(
CRITERION_DLL
"${CMAKE_SHARED_LIBRARY_PREFIX}${CRITERION_BASENAME}${CMAKE_SHARED_LIBRARY_SUFFIX}"
HINTS
${CRITERION_PREFIX}
PATH_SUFFIXES
bin
NO_DEFAULT_PATH)
mark_as_advanced(CRITERION_DLL)
if(CRITERION_DLL)
add_library(Criterion SHARED IMPORTED)
set_target_properties(
Criterion PROPERTIES IMPORTED_IMPLIB "${CRITERION_LIBRARY}")
set_target_properties(
Criterion PROPERTIES IMPORTED_LOCATION "${CRITERION_DLL}")
else()
add_library(Criterion STATIC IMPORTED)
set_target_properties(
Criterion PROPERTIES IMPORTED_LOCATION "${CRITERION_LIBRARY}")
endif()
else()
add_library(Criterion UNKNOWN IMPORTED)
set_target_properties(
Criterion PROPERTIES IMPORTED_LOCATION "${CRITERION_LIBRARY}")
endif()
set_target_properties(
Criterion PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CRITERION_INCLUDE_DIR}")
endif()