CMakeLists.txt 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. # Determine if we should print to the output
  2. if (CIVETWEB_ENABLE_THIRD_PARTY_OUTPUT)
  3. set(THIRD_PARTY_LOGGING 0)
  4. else()
  5. set(THIRD_PARTY_LOGGING 1)
  6. endif()
  7. # We use the check unit testing framework for our C unit tests
  8. include(ExternalProject)
  9. if(NOT WIN32)
  10. # Apply the patch to check to fix CMake building on OS X
  11. set(CHECK_PATCH_COMMAND patch
  12. ${CIVETWEB_THIRD_PARTY_DIR}/src/check-unit-test-framework/src/check_run.c
  13. ${CMAKE_SOURCE_DIR}/cmake/check/check_run.patch
  14. )
  15. else()
  16. set(CHECK_PATCH_COMMAND "")
  17. endif()
  18. IF (DEFINED ENV{CHECK_URL})
  19. SET (CHECK_URL $ENV{CHECK_URL})
  20. ELSE()
  21. SET (CHECK_URL "https://github.com/civetweb/check/archive/master.zip")
  22. ENDIF()
  23. ExternalProject_Add(check-unit-test-framework
  24. DEPENDS civetweb-c-library
  25. ## Use an official, released check version:
  26. # URL "https://codeload.github.com/libcheck/check/zip/${CIVETWEB_CHECK_VERSION}"
  27. # DOWNLOAD_NAME "${CIVETWEB_CHECK_VERSION}.zip"
  28. # URL_MD5 ${CIVETWEB_CHECK_MD5_HASH}
  29. ## Use a civetweb specific patched version
  30. URL ${CHECK_URL}
  31. DOWNLOAD_NAME "master.zip"
  32. PREFIX "${CIVETWEB_THIRD_PARTY_DIR}"
  33. BUILD_IN_SOURCE 1
  34. PATCH_COMMAND ${CHECK_PATCH_COMMAND}
  35. CMAKE_ARGS
  36. "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
  37. "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
  38. "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>"
  39. LOG_DOWNLOAD ${THIRD_PARTY_LOGGING}
  40. LOG_UPDATE ${THIRD_PARTY_LOGGING}
  41. LOG_CONFIGURE ${THIRD_PARTY_LOGGING}
  42. LOG_BUILD ${THIRD_PARTY_LOGGING}
  43. LOG_TEST ${THIRD_PARTY_LOGGING}
  44. LOG_INSTALL ${THIRD_PARTY_LOGGING})
  45. ExternalProject_Get_Property(check-unit-test-framework INSTALL_DIR)
  46. set(CHECK_INSTALL_DIR ${INSTALL_DIR})
  47. unset(INSTALL_DIR)
  48. link_directories("${CHECK_INSTALL_DIR}/lib")
  49. include_directories("${CHECK_INSTALL_DIR}/include")
  50. if ((WIN32 AND MINGW) OR APPLE)
  51. set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/libcheck.a")
  52. set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/libcompat.a")
  53. elseif (WIN32)
  54. set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/check.lib")
  55. set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/compat.lib")
  56. else()
  57. set(CHECK_LIBRARIES "${CHECK_INSTALL_DIR}/lib/libcheck.a")
  58. endif()
  59. find_package(LibM)
  60. if (LIBM_FOUND)
  61. set(CHECK_LIBRARIES "${CHECK_LIBRARIES};LIBM::LIBM")
  62. endif()
  63. find_package(LibRt)
  64. if (LIBRT_FOUND)
  65. set(CHECK_LIBRARIES "${CHECK_LIBRARIES};LIBRT::LIBRT")
  66. endif()
  67. # Build the C unit tests
  68. add_library(shared-c-unit-tests STATIC shared.c)
  69. target_include_directories(
  70. shared-c-unit-tests PUBLIC
  71. ${PROJECT_SOURCE_DIR}/include)
  72. add_library(public-func-c-unit-tests STATIC public_func.c)
  73. if (BUILD_SHARED_LIBS)
  74. target_compile_definitions(public-func-c-unit-tests PRIVATE CIVETWEB_DLL_IMPORTS)
  75. endif()
  76. target_include_directories(
  77. public-func-c-unit-tests PUBLIC
  78. ${PROJECT_SOURCE_DIR}/include)
  79. target_link_libraries(public-func-c-unit-tests civetweb-c-library ${CHECK_LIBRARIES})
  80. add_dependencies(public-func-c-unit-tests check-unit-test-framework)
  81. add_library(public-server-c-unit-tests STATIC public_server.c)
  82. if (BUILD_SHARED_LIBS)
  83. target_compile_definitions(public-server-c-unit-tests PRIVATE CIVETWEB_DLL_IMPORTS)
  84. endif()
  85. target_include_directories(
  86. public-server-c-unit-tests PUBLIC
  87. ${PROJECT_SOURCE_DIR}/include)
  88. target_link_libraries(public-server-c-unit-tests civetweb-c-library ${CHECK_LIBRARIES})
  89. add_dependencies(public-server-c-unit-tests check-unit-test-framework)
  90. add_library(private-c-unit-tests STATIC private.c)
  91. target_include_directories(
  92. private-c-unit-tests PUBLIC
  93. ${PROJECT_SOURCE_DIR}/include)
  94. target_link_libraries(private-c-unit-tests ${CHECK_LIBRARIES})
  95. add_dependencies(private-c-unit-tests check-unit-test-framework)
  96. add_library(timer-c-unit-tests STATIC timertest.c)
  97. target_include_directories(
  98. timer-c-unit-tests PUBLIC
  99. ${PROJECT_SOURCE_DIR}/include)
  100. target_link_libraries(timer-c-unit-tests ${CHECK_LIBRARIES})
  101. add_dependencies(timer-c-unit-tests check-unit-test-framework)
  102. add_library(exe-c-unit-tests STATIC private_exe.c)
  103. if (BUILD_SHARED_LIBS)
  104. target_compile_definitions(exe-c-unit-tests PRIVATE)
  105. endif()
  106. target_include_directories(
  107. exe-c-unit-tests PUBLIC
  108. ${PROJECT_SOURCE_DIR}/include)
  109. target_link_libraries(exe-c-unit-tests civetweb-c-library ${CHECK_LIBRARIES})
  110. add_dependencies(exe-c-unit-tests check-unit-test-framework)
  111. add_executable(main-c-unit-test main.c)
  112. target_link_libraries(main-c-unit-test
  113. shared-c-unit-tests
  114. public-func-c-unit-tests
  115. public-server-c-unit-tests
  116. private-c-unit-tests
  117. timer-c-unit-tests
  118. exe-c-unit-tests
  119. ${CHECK_LIBRARIES})
  120. add_dependencies(main-c-unit-test check-unit-test-framework)
  121. # Add a check command that builds the dependent test program
  122. add_custom_target(check
  123. COMMAND ${CMAKE_CTEST_COMMAND}
  124. DEPENDS main-c-unit-test)
  125. # A macro for adding tests
  126. macro(civetweb_add_test suite test_case)
  127. set(test "test-${suite}-${test_case}")
  128. string(TOLOWER "${test}" test)
  129. string(REGEX REPLACE "[^-A-Za-z0-9]" "-" test "${test}")
  130. add_test(
  131. NAME ${test}
  132. COMMAND main-c-unit-test "--test-dir=${CMAKE_CURRENT_SOURCE_DIR}" "--suite=${suite}" "--test-case=${test_case}")
  133. if (WIN32)
  134. string(REPLACE ";" "\\;" test_path "$ENV{PATH}")
  135. set_tests_properties(${test} PROPERTIES
  136. ENVIRONMENT "PATH=${test_path}\\;$<TARGET_FILE_DIR:civetweb-c-library>")
  137. endif()
  138. endmacro(civetweb_add_test)
  139. # Tests of private functions
  140. civetweb_add_test(Private "HTTP Message")
  141. civetweb_add_test(Private "HTTP Keep Alive")
  142. civetweb_add_test(Private "URL Parsing 1")
  143. civetweb_add_test(Private "URL Parsing 2")
  144. civetweb_add_test(Private "URL Parsing 3")
  145. civetweb_add_test(Private "Internal Parsing 1")
  146. civetweb_add_test(Private "Internal Parsing 2")
  147. civetweb_add_test(Private "Internal Parsing 3")
  148. civetweb_add_test(Private "Internal Parsing 4")
  149. civetweb_add_test(Private "Internal Parsing 5")
  150. civetweb_add_test(Private "Internal Parsing 6")
  151. civetweb_add_test(Private "Internal Parsing 7")
  152. civetweb_add_test(Private "Encode Decode")
  153. civetweb_add_test(Private "Mask Data")
  154. civetweb_add_test(Private "Date Parsing")
  155. civetweb_add_test(Private "SHA1")
  156. civetweb_add_test(Private "Config Options")
  157. # Public API function tests
  158. civetweb_add_test(PublicFunc "Version")
  159. civetweb_add_test(PublicFunc "Options")
  160. civetweb_add_test(PublicFunc "MIME types")
  161. civetweb_add_test(PublicFunc "strcasecmp")
  162. civetweb_add_test(PublicFunc "URL encoding decoding")
  163. civetweb_add_test(PublicFunc "Cookies and variables")
  164. civetweb_add_test(PublicFunc "MD5")
  165. civetweb_add_test(PublicFunc "Aux functions")
  166. # Public API server tests
  167. civetweb_add_test(PublicServer "Check test environment")
  168. civetweb_add_test(PublicServer "Init library")
  169. civetweb_add_test(PublicServer "Start threads")
  170. civetweb_add_test(PublicServer "Minimal HTTP Server")
  171. civetweb_add_test(PublicServer "Minimal HTTPS Server")
  172. civetweb_add_test(PublicServer "Minimal HTTP Client")
  173. civetweb_add_test(PublicServer "Minimal HTTPS Client")
  174. civetweb_add_test(PublicServer "Start Stop HTTP Server")
  175. civetweb_add_test(PublicServer "Start Stop HTTP Server IPv6")
  176. civetweb_add_test(PublicServer "Start Stop HTTPS Server")
  177. civetweb_add_test(PublicServer "TLS Server Client")
  178. civetweb_add_test(PublicServer "Server Requests")
  179. civetweb_add_test(PublicServer "Store Body")
  180. civetweb_add_test(PublicServer "Handle Form")
  181. civetweb_add_test(PublicServer "HTTP Authentication")
  182. civetweb_add_test(PublicServer "HTTP Keep Alive")
  183. civetweb_add_test(PublicServer "Error handling")
  184. civetweb_add_test(PublicServer "Error logging")
  185. civetweb_add_test(PublicServer "Limit speed")
  186. civetweb_add_test(PublicServer "Large file")
  187. civetweb_add_test(PublicServer "File in memory")
  188. # Timer tests
  189. civetweb_add_test(Timer "Timer Single Shot")
  190. civetweb_add_test(Timer "Timer Periodic")
  191. civetweb_add_test(Timer "Timer Mixed")
  192. # Tests with main.c
  193. civetweb_add_test(EXE "Helper funcs")
  194. # Add the coverage command(s)
  195. if (${CMAKE_BUILD_TYPE} MATCHES "[Cc]overage")
  196. find_program(GCOV_EXECUTABLE gcov)
  197. find_program(LCOV_EXECUTABLE lcov)
  198. find_program(GENHTML_EXECUTABLE genhtml)
  199. find_program(CTEST_EXECUTABLE ctest)
  200. if (GCOV_EXECUTABLE AND LCOV_EXECUTABLE AND GENHTML_EXECUTABLE AND CTEST_EXECUTABLE AND HAVE_C_FLAG_COVERAGE)
  201. add_custom_command(
  202. OUTPUT ${CMAKE_BINARY_DIR}/lcov/index.html
  203. COMMAND ${LCOV_EXECUTABLE} -q -z -d .
  204. COMMAND ${LCOV_EXECUTABLE} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o before.lcov -i
  205. COMMAND ${CTEST_EXECUTABLE} --force-new-ctest-process
  206. COMMAND ${LCOV_EXECUTABLE} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o after.lcov
  207. COMMAND ${LCOV_EXECUTABLE} -q -a before.lcov -a after.lcov --output-file final.lcov
  208. COMMAND ${LCOV_EXECUTABLE} -q -r final.lcov "'${CMAKE_SOURCE_DIR}/unittest/*'" -o final.lcov
  209. COMMAND ${GENHTML_EXECUTABLE} final.lcov -o lcov --demangle-cpp --sort -p "${CMAKE_SOURCE_DIR}" -t benchmark
  210. DEPENDS main-c-unit-test
  211. WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
  212. COMMENT "Running LCOV"
  213. )
  214. add_custom_target(coverage
  215. DEPENDS ${CMAKE_BINARY_DIR}/lcov/index.html
  216. COMMENT "LCOV report at lcov/index.html"
  217. )
  218. message(STATUS "Coverage command added")
  219. else()
  220. if (HAVE_C_FLAG_COVERAGE)
  221. set(C_FLAG_COVERAGE_MESSAGE supported)
  222. else()
  223. set(C_FLAG_COVERAGE_MESSAGE unavailable)
  224. endif()
  225. message(WARNING
  226. "Coverage command not available:\n"
  227. " gcov: ${GCOV_EXECUTABLE}\n"
  228. " lcov: ${LCOV_EXECUTABLE}\n"
  229. " genhtml: ${GENHTML_EXECUTABLE}\n"
  230. " ctest: ${CTEST_EXECUTABLE}\n"
  231. " --coverage flag: ${C_FLAG_COVERAGE_MESSAGE}")
  232. endif()
  233. endif()