Cloned SEACAS for EXODUS library with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

503 lines
16 KiB

# @HEADER
# ************************************************************************
#
# TriBITS: Tribal Build, Integrate, and Test System
# Copyright 2013 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ************************************************************************
# @HEADER
include(CMakeParseArguments)
include(GlobalSet)
# Set policy here instead of including TribitCTestPolicis.cmake since we want
# this to be a standalone module
cmake_policy(SET CMP0007 NEW) # Don't ignore empty list items
# @MACRO: unittest_initialize_vars()
#
# Call to initialize the unit test variables before running unit tests.
#
# Usage::
#
# unittest_initialize_vars()
#
macro(unittest_initialize_vars)
# Assume that all unit tests will pass by default
global_set(UNITTEST_OVERALL_PASS TRUE)
global_set(UNITTEST_OVERALL_NUMPASSED 0)
global_set(UNITTEST_OVERALL_NUMRUN 0)
endmacro()
# @FUNCTION: unittest_compare_const()
#
# Perform a single unit test equality check and update overall test statistics
#
# Usage::
#
# unittest_compare_const(<varName> <expectedValue>)
#
# If ``${<varName>} == <expectedValue>``, then the check passes, otherwise it
# fails. This prints the variable name and values and shows the test result.
#
# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``,
# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used
# by the unit test harness system to assess overall pass/fail.
#
function(unittest_compare_const VAR_NAME CONST_VAL)
math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 )
global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN})
message(
"\nCheck:\n"
" ${VAR_NAME} =\n"
" [${${VAR_NAME}}]\n"
" EQUALS:\n"
" [${CONST_VAL}]"
)
if ("${${VAR_NAME}}" STREQUAL "${CONST_VAL}")
message(" [PASSED]\n")
math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 )
global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED})
else()
message(" [FAILED]\n")
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
endif()
endfunction()
# @FUNCTION: unittest_compare_list_ele_const()
#
# Perform a single unit test equality check for a single list element
#
# Usage::
#
# unittest_compare_list_ele_const(<listName> <idx> <expectedConstValue>)
#
# If ``${<listName>[<idx>]} == <expectedValue>``, then the check passes, otherwise it
# fails. This prints the variable name and values and shows the test result.
#
# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``,
# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used
# by the unit test harness system to assess overall pass/fail.
#
function(unittest_compare_list_ele_const listName idx expectedConstValue)
math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 )
global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN})
list(GET "${listName}" ${idx} listEleIdx)
set(listNameAndIdx "${listName}[${idx}]")
message(
"\nCheck:\n"
" ${listNameAndIdx} =\n"
" [${listEleIdx}]\n"
" EQUALS:\n"
" [${expectedConstValue}]"
)
if ("${listEleIdx}" STREQUAL "${expectedConstValue}")
message(" [PASSED]\n")
math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 )
global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED})
else()
message(" [FAILED]\n")
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
endif()
endfunction()
# @FUNCTION: unittest_string_block_compare()
#
# Compare two string blocks (with multiple newlines '\n') line-by-line and
# print the first line that fails the comparison.
#
# Usage::
#
# unittest_string_block_compare(
# <stringVar> "<stringExpected>"
# )
#
# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``,
# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used
# by the unit test harness system to assess overall pass/fail.
#
function(unittest_string_block_compare stringVar stringExpected)
message("\nCheck: ${stringVar} equals expected string:")
math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 )
global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN})
string(REPLACE "\n" ";" stringList "${${stringVar}}")
string(REPLACE "\n" ";" stringExpectedList "${stringExpected}")
list(LENGTH stringList stringLen)
list(LENGTH stringExpectedList stringExpectedLen)
# minLen = min(stringLen, stringExpectedLen)
set(minLen ${stringLen})
if (stringExpectedLen LESS minLen)
set(minLen ${stringExpectedLen})
endif()
set(allMatched TRUE)
set(idx 0)
while (idx LESS minLen)
list(GET stringList ${idx} stringEle)
list(GET stringExpectedList ${idx} stringExpectedEle)
if (NOT stringEle STREQUAL stringExpectedEle)
message(
" Error: Line ${idx} of ${stringVar}:\n"
" '${stringEle}'\n"
" !=\n"
" '${stringExpectedEle}'\n"
" [FAILED]\n"
)
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
set(allMatched FALSED)
break()
endif()
math(EXPR idx "${idx}+1")
endwhile()
if (NOT allMatched)
# The error handling was already handled above
elseif (NOT stringLen EQUAL stringExpectedLen)
# The lines of the strings matched but one of the strings had more lines
# than the other
if (stringLen GREATER stringExpectedLen)
list(GET stringList ${stringExpectedLen} nextLine)
message(
" Error: ${stringVar} has ${stringLen} lines where expected string has"
" only ${stringExpectedLen} lines and the next extra line is:\n"
" '${nextLine}'\n"
" [FAILED]\n"
)
elseif (stringExpectedLen GREATER stringLen)
list(GET stringExpectedList ${stringLen} nextLine)
message(
" Error: Expected string has ${stringExpectedLen} lines where ${stringVar} has"
"only ${stringLen} lines and the next extra line is:\n"
" '${nextLine}'\n"
" [FAILED]\n"
)
endif()
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
else()
# The strings matched exactly!
message(" [PASSED]\n")
math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 )
global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED})
endif()
endfunction()
# @FUNCTION: unittest_string_regex()
#
# Perform a series of regexes on a given string and update overall test
# statistics.
#
# Usage::
#
# unittest_string_regex(
# "<inputString>"
# REGEX_STRINGS "<str0>" "<str1>" ...
# )
#
# If the ``<inputString>`` matches all of the of the regexs ``"<str0>"``,
# ``"<str1>"``, ..., then the test passes. Otherwise it fails.
#
# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``,
# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used
# by the unit test harness system to assess overall pass/fail.
#
function(unittest_string_regex INPUT_STRING)
cmake_parse_arguments(
#prefix
PARSE
#options
""
#one_value_keywords
""
#multi_value_keywords
"REGEX_STRINGS"
${ARGN}
)
tribits_check_for_unparsed_arguments()
foreach(REGEX ${PARSE_REGEX_STRINGS})
math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 )
global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN})
string(REGEX MATCH "${REGEX}" REGEX_MATCH_RESULT "${INPUT_STRING}")
message(" Searching string:")
message(" '${INPUT_STRING}'")
if (REGEX_MATCH_RESULT)
message(" for REGEX {${REGEX}}: [PASSED]\n")
math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 )
global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED})
else()
message(" for REGEX {${REGEX}}: [FAILED]\n")
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
endif()
endforeach()
endfunction()
# @FUNCTION: unittest_string_var_regex()
#
# Perform a series of regexes on a given string variable and update overall
# test statistics.
#
# Usage::
#
# unittest_string_var_regex(
# <inputStringVar>
# REGEX_STRINGS "<str0>" "<str1>" ...
# )
#
# If the ``"${<inputStringVar>}"`` matches all of the of the regexs
# ``"<str0>"``, ``"<str1>"``, ..., then the test passes. Otherwise it fails.
#
# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``,
# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used
# by the unit test harness system to assess overall pass/fail.
#
function(unittest_string_var_regex inputStringVar)
cmake_parse_arguments(PARSE_ARGV 1
PARSE "" "" # prefix, options, one_value_keywords
"REGEX_STRINGS" #multi_value_keywords
)
tribits_check_for_unparsed_arguments(PARSE)
foreach(REGEX ${PARSE_REGEX_STRINGS})
math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 )
global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN})
string(REGEX MATCH "${REGEX}" REGEX_MATCH_RESULT "${${inputStringVar}}")
message("Searching string variable value '${inputStringVar}':")
message(" '${${inputStringVar}}'")
if (REGEX_MATCH_RESULT)
message(" for REGEX {${REGEX}}: [PASSED]\n")
math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 )
global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED})
else()
message(" for REGEX {${REGEX}}: [FAILED]\n")
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
endif()
endforeach()
endfunction()
# @FUNCTION: unittest_has_substr_const()
#
# Check that a given string var contains the given substring and update
# overall test statistics
#
# Usage::
#
# unittest_has_substr_const(<varName> <substr>)
#
# If ``${<varName>}`` contains the substring ``<substr>``, then the check
# passes, otherwise it fails. This prints the variable name and values and
# shows the test result.
#
# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``,
# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used
# by the unit test harness system to assess overall pass/fail.
#
function(unittest_has_substr_const VAR_NAME SUBSTR_VAL)
math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 )
global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN})
message(
"\nCheck:\n"
" ${VAR_NAME} =\n"
" [${${VAR_NAME}}]\n"
" Contains:\n"
" [${SUBSTR_VAL}]"
)
string(FIND "${${VAR_NAME}}" "${SUBSTR_VAL}" SUBSTR_START_IDX)
#print_var(SUBSTR_START_IDX)
if (${SUBSTR_START_IDX} GREATER -1)
message(" [PASSED]\n")
math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 )
global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED})
else()
message(" [FAILED]\n")
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
endif()
endfunction()
# @FUNCTION: unittest_not_has_substr_const()
#
# Check that a given string var does **NOT** contains the given substring and
# update overall test statistics
#
# Usage::
#
# unittest_not_has_substr_const(<varName> <substr>)
#
# If ``${<varName>}`` contains the substring ``<substr>``, then the check
# failed, otherwise it passes. This prints the variable name and values and
# shows the test result.
#
# This updates the global variables ``UNITTEST_OVERALL_NUMRUN``,
# ``UNITTEST_OVERALL_NUMPASSED``, and ``UNITTEST_OVERALL_PASS`` which are used
# by the unit test harness system to assess overall pass/fail.
#
function(unittest_not_has_substr_const VAR_NAME SUBSTR_VAL)
math( EXPR NUMRUN ${UNITTEST_OVERALL_NUMRUN}+1 )
global_set(UNITTEST_OVERALL_NUMRUN ${NUMRUN})
message(
"\nCheck:\n"
" ${VAR_NAME} =\n"
" [${${VAR_NAME}}]\n"
" Does NOT contain:\n"
" [${SUBSTR_VAL}]"
)
string(FIND "${${VAR_NAME}}" "${SUBSTR_VAL}" SUBSTR_START_IDX)
#print_var(SUBSTR_START_IDX)
if (${SUBSTR_START_IDX} GREATER -1)
message(" [FAILED]\n")
global_set(UNITTEST_OVERALL_PASS FALSE)
message(WARNING "Stack trace for failed unit test")
else()
message(" [PASSED]\n")
math( EXPR NUMPASSED ${UNITTEST_OVERALL_NUMPASSED}+1 )
global_set(UNITTEST_OVERALL_NUMPASSED ${NUMPASSED})
endif()
endfunction()
# @FUNCTION: unittest_file_regex()
#
# Perform a series regexes of given strings and update overall test statistics.
#
# Usage::
#
# unittest_file_regex(
# <inputFileName>
# REGEX_STRINGS "<str1>" "<str2>" ...
# )
#
# The contents of ``<inputFileName>`` are read into a string and then passed
# to `unittest_string_regex()`_ to assess pass/fail.
#
function(unittest_file_regex INPUT_FILE)
message("\nRegexing for strings in the file '${INPUT_FILE}':\n")
file(READ "${INPUT_FILE}" INPUT_FILE_STRING)
unittest_string_regex("${INPUT_FILE_STRING}" ${ARGN})
endfunction()
# @FUNCTION: unittest_final_result()
#
# Print final statistics from all tests and assert final pass/fail
#
# Usage::
#
# unittest_final_result(<expectedNumPassed>)
#
# If ``${UNITTEST_OVERALL_PASS}==TRUE`` and ``${UNITTEST_OVERALL_NUMPASSED} ==
# <expectedNumPassed>``, then the overall test program is determined to have
# passed and string::
#
# "Final UnitTests Result: PASSED"
#
# is printed. Otherwise, the overall test program is determined to have
# failed, the string::
#
# "Final UnitTests Result: FAILED"
#
# is printed, and ``message(SEND_ERROR "FAIL")`` is called.
#
# The reason that we require passing in the expected number of passed tests is
# as an extra precaution to make sure that important unit tests are not left
# out. CMake is a very loosely typed language and it pays to be a little
# paranoid.
#
function(unittest_final_result EXPECTED_NUMPASSED)
message("\nFinal UnitTests Result: num_run = ${UNITTEST_OVERALL_NUMRUN}\n")
if (UNITTEST_OVERALL_PASS)
if (UNITTEST_OVERALL_NUMPASSED EQUAL ${EXPECTED_NUMPASSED})
message("Final UnitTests Result: PASSED"
" (num_passed = ${UNITTEST_OVERALL_NUMPASSED})")
else()
message("\nError: num_passed = ${UNITTEST_OVERALL_NUMPASSED}"
" != num_expected = ${EXPECTED_NUMPASSED}")
message("\nFinal UnitTests Result: FAILED\n")
message(SEND_ERROR "FAIL")
endif()
else()
message("\nFinal UnitTests Result: FAILED\n")
endif()
endfunction()