Skip to content

Instantly share code, notes, and snippets.

@McMartin
Last active May 9, 2018 22:09
Show Gist options
  • Save McMartin/dd593c9ad3e9680a14255c54cefd713d to your computer and use it in GitHub Desktop.
Save McMartin/dd593c9ad3e9680a14255c54cefd713d to your computer and use it in GitHub Desktop.
A CMake test framework heavily inspired by doctest (https://github.com/onqtam/doctest)
function(get_fizzbuzz in out)
math(EXPR off3 "${in} % 3")
math(EXPR off5 "${in} % 5")
if(NOT off3 AND NOT off5)
set(${out} FizzBuzz PARENT_SCOPE)
elseif(NOT off3)
set(${out} Fizz PARENT_SCOPE)
elseif(NOT off5)
set(${out} Buzz PARENT_SCOPE)
else()
set(${out} ${in} PARENT_SCOPE)
endif()
endfunction()
function(fizzbuzz)
foreach(i RANGE 1 100)
get_fizzbuzz(${i} msg)
message("${msg}")
endforeach(i)
endfunction()
if(CMAKE_SCRIPT_MODE_FILE STREQUAL CMAKE_CURRENT_LIST_FILE)
fizzbuzz()
endif()
function(eval _eval_code)
set(_eval_tmp_file "${CMAKE_CURRENT_LIST_FILE}.eval")
file(WRITE "${_eval_tmp_file}" "${_eval_code}")
include("${_eval_tmp_file}")
file(REMOVE "${_eval_tmp_file}")
endfunction()
function(rjust out int length)
string(LENGTH "${int}" int_length)
if(int_length LESS length)
math(EXPR length "${length} - 1")
foreach(i RANGE ${int_length} ${length})
set(int " ${int}")
endforeach()
endif()
set(${out} "${int}" PARENT_SCOPE)
endfunction()
function(TEST_MAIN)
cmake_policy(SET CMP0057 NEW)
set(separator
"==============================================================================="
)
message(STATUS "[mcmtest] mcmtest version is \"0.1.0\"")
math(EXPR argc "${CMAKE_ARGC} - 1")
unset(argv)
foreach(i RANGE 0 ${argc})
list(APPEND argv "${CMAKE_ARGV${i}}")
endforeach()
if("-ltc" IN_LIST argv)
set(list_test_cases TRUE)
endif()
if(list_test_cases)
message(STATUS "[mcmtest] listing all test case names")
message(STATUS "${separator}")
endif()
set(num_tests 0)
set(num_tests_passed 0)
set(num_tests_failed 0)
set(num_tests_skipped 0)
set(num_assertions 0)
set(num_assertions_passed 0)
set(num_assertions_failed 0)
list(LENGTH DOCTEST_REGISTERED_TESTS length)
if(length GREATER 0)
math(EXPR length "${length} - 1")
foreach(id RANGE 0 ${length})
math(EXPR num_tests "${num_tests} + 1")
if(list_test_cases)
message(STATUS "${DOCTEST_TEST_${id}_NAME}")
continue()
endif()
set(has_current_test_failed FALSE)
eval("cmake_policy(SET CMP0011 NEW)
# Begin test code
${DOCTEST_TEST_${id}_CODE}
# End test code
set(num_assertions \${num_assertions} PARENT_SCOPE)
set(num_assertions_passed \${num_assertions_passed} PARENT_SCOPE)
set(num_assertions_failed \${num_assertions_failed} PARENT_SCOPE)
set(has_current_test_failed \${has_current_test_failed} PARENT_SCOPE)
")
if(has_current_test_failed)
math(EXPR num_tests_failed "${num_tests_failed} + 1")
else()
math(EXPR num_tests_passed "${num_tests_passed} + 1")
endif()
endforeach()
endif()
message(STATUS "${separator}")
if(list_test_cases)
message(STATUS "[mcmtest] unskipped test cases passing the current filters: ${num_tests}")
else()
rjust(r_num_tests ${num_tests} 6)
rjust(r_num_tests_passed ${num_tests_passed} 6)
rjust(r_num_tests_failed ${num_tests_failed} 6)
rjust(r_num_tests_skipped ${num_tests_skipped} 6)
message(STATUS "[mcmtest] test cases: ${r_num_tests} | ${r_num_tests_passed} passed | ${r_num_tests_failed} failed | ${r_num_tests_skipped} skipped")
rjust(r_num_assertions ${num_assertions} 6)
rjust(r_num_assertions_passed ${num_assertions_passed} 6)
rjust(r_num_assertions_failed ${num_assertions_failed} 6)
message(STATUS "[mcmtest] assertions: ${r_num_assertions} | ${r_num_assertions_passed} passed | ${r_num_assertions_failed} failed |")
if(num_tests_failed GREATER 0)
message(FATAL_ERROR "[mcmtest] Status: FAILURE!")
else()
message(STATUS "[mcmtest] Status: SUCCESS!")
endif()
endif()
endfunction()
function(TEST_CASE name code)
list(LENGTH DOCTEST_REGISTERED_TESTS id)
set(DOCTEST_TEST_${id}_NAME "${name}" PARENT_SCOPE)
set(DOCTEST_TEST_${id}_CODE "${code}" PARENT_SCOPE)
list(APPEND DOCTEST_REGISTERED_TESTS "${name}")
set(DOCTEST_REGISTERED_TESTS ${DOCTEST_REGISTERED_TESTS} PARENT_SCOPE)
endfunction()
function(CHECK)
cmake_policy(SET CMP0012 NEW)
math(EXPR num_assertions "${num_assertions} + 1")
if(${ARGN})
math(EXPR num_assertions_passed "${num_assertions_passed} + 1")
else()
set(has_current_test_failed TRUE)
math(EXPR num_assertions_failed "${num_assertions_failed} + 1")
endif()
set(num_assertions ${num_assertions} PARENT_SCOPE)
set(num_assertions_passed ${num_assertions_passed} PARENT_SCOPE)
set(num_assertions_failed ${num_assertions_failed} PARENT_SCOPE)
set(has_current_test_failed ${has_current_test_failed} PARENT_SCOPE)
endfunction()
$ cmake -P tst_fizzbuzz.cmake
-- [mcmtest] mcmtest version is "0.1.0"
-- ===============================================================================
-- [mcmtest] test cases: 1 | 1 passed | 0 failed | 0 skipped
-- [mcmtest] assertions: 4 | 4 passed | 0 failed |
-- [mcmtest] Status: SUCCESS!
include("${CMAKE_CURRENT_LIST_DIR}/fizzbuzz.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/mcmtest.cmake")
TEST_CASE("get_fizzbuzz"
[[
get_fizzbuzz(1 one)
CHECK(one STREQUAL "1" AND TRUE)
get_fizzbuzz(3 three)
CHECK(three STREQUAL "Fizz")
get_fizzbuzz(5 five)
CHECK(five STREQUAL "Buzz")
get_fizzbuzz(15 fifteen)
CHECK(fifteen STREQUAL "FizzBuzz")
]])
TEST_MAIN()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment