CTestUpdateCommon.cmake 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #-----------------------------------------------------------------------------
  2. # Function to run a child process and report output only on error.
  3. function(run_child)
  4. execute_process(${ARGN}
  5. RESULT_VARIABLE FAILED
  6. OUTPUT_VARIABLE OUTPUT
  7. ERROR_VARIABLE OUTPUT
  8. OUTPUT_STRIP_TRAILING_WHITESPACE
  9. ERROR_STRIP_TRAILING_WHITESPACE
  10. )
  11. if(FAILED)
  12. string(REPLACE "\n" "\n " OUTPUT "${OUTPUT}")
  13. message(FATAL_ERROR "Child failed (${FAILED}), output is\n ${OUTPUT}\n"
  14. "Command = [${ARGN}]\n")
  15. endif()
  16. endfunction()
  17. #-----------------------------------------------------------------------------
  18. # Function to find the Update.xml file and check for expected entries.
  19. function(check_updates build)
  20. # Find the Update.xml file for the given build tree
  21. set(PATTERN ${TOP}/${build}/Testing/*/Update.xml)
  22. file(GLOB UPDATE_XML_FILE RELATIVE ${TOP} ${PATTERN})
  23. string(REGEX REPLACE "//Update.xml$" "/Update.xml"
  24. UPDATE_XML_FILE "${UPDATE_XML_FILE}"
  25. )
  26. if(NOT UPDATE_XML_FILE)
  27. message(FATAL_ERROR "Cannot find Update.xml with pattern\n ${PATTERN}")
  28. endif()
  29. message(" found ${UPDATE_XML_FILE}")
  30. set(max_update_xml_size 16384)
  31. # Read entries from the Update.xml file
  32. set(types "Updated|Modified|Conflicting")
  33. file(STRINGS ${TOP}/${UPDATE_XML_FILE} UPDATE_XML_ENTRIES
  34. REGEX "<(${types}|FullName)>"
  35. LIMIT_INPUT ${max_update_xml_size}
  36. )
  37. string(REGEX REPLACE
  38. "[ \t]*<(${types})>[ \t]*;[ \t]*<FullName>([^<]*)</FullName>"
  39. "\\1{\\2}" UPDATE_XML_ENTRIES "${UPDATE_XML_ENTRIES}")
  40. # If specified, remove the given prefix from the files in Update.xml.
  41. # Some VCS systems, like Perforce, return absolute locations
  42. if(DEFINED REPOSITORY_FILE_PREFIX)
  43. string(REPLACE
  44. "${REPOSITORY_FILE_PREFIX}" ""
  45. UPDATE_XML_ENTRIES "${UPDATE_XML_ENTRIES}")
  46. endif()
  47. # Compare expected and actual entries
  48. set(EXTRA "${UPDATE_XML_ENTRIES}")
  49. list(REMOVE_ITEM EXTRA ${ARGN} ${UPDATE_EXTRA} ${UPDATE_MAYBE})
  50. set(MISSING "${ARGN}" ${UPDATE_EXTRA})
  51. if(NOT "" STREQUAL "${UPDATE_XML_ENTRIES}")
  52. list(REMOVE_ITEM MISSING ${UPDATE_XML_ENTRIES})
  53. endif()
  54. if(NOT UPDATE_NOT_GLOBAL)
  55. set(rev_elements Revision PriorRevision ${UPDATE_GLOBAL_ELEMENTS})
  56. string(REPLACE ";" "|" rev_regex "${rev_elements}")
  57. set(rev_regex "^\t<(${rev_regex})>[^<\n]+</(${rev_regex})>$")
  58. file(STRINGS ${TOP}/${UPDATE_XML_FILE} UPDATE_XML_REVISIONS
  59. REGEX "${rev_regex}"
  60. LIMIT_INPUT ${max_update_xml_size}
  61. )
  62. foreach(r IN LISTS UPDATE_XML_REVISIONS)
  63. string(REGEX REPLACE "${rev_regex}" "\\1" element "${r}")
  64. set(element_${element} 1)
  65. endforeach()
  66. foreach(element ${rev_elements})
  67. if(NOT element_${element})
  68. list(APPEND MISSING "global <${element}> element")
  69. endif()
  70. endforeach()
  71. endif()
  72. # Report the result
  73. set(MSG "")
  74. if(MISSING)
  75. # List the missing entries
  76. set(MSG "${MSG}Update.xml is missing expected entries:\n")
  77. foreach(f ${MISSING})
  78. set(MSG "${MSG} ${f}\n")
  79. endforeach()
  80. else()
  81. # Success
  82. message(" no entries missing from Update.xml")
  83. endif()
  84. # Report the result
  85. if(EXTRA)
  86. # List the extra entries
  87. set(MSG "${MSG}Update.xml has extra unexpected entries:\n")
  88. foreach(f ${EXTRA})
  89. set(MSG "${MSG} ${f}\n")
  90. endforeach()
  91. else()
  92. # Success
  93. message(" no extra entries in Update.xml")
  94. endif()
  95. if(MSG)
  96. # Provide the log file
  97. file(GLOB UPDATE_LOG_FILE
  98. ${TOP}/${build}/Testing/Temporary/LastUpdate*.log)
  99. if(UPDATE_LOG_FILE)
  100. file(READ ${UPDATE_LOG_FILE} UPDATE_LOG LIMIT ${max_update_xml_size})
  101. string(REPLACE "\n" "\n " UPDATE_LOG "${UPDATE_LOG}")
  102. set(MSG "${MSG}Update log:\n ${UPDATE_LOG}")
  103. else()
  104. set(MSG "${MSG}No update log found!")
  105. endif()
  106. # Display the error message
  107. message(FATAL_ERROR "${MSG}")
  108. endif()
  109. endfunction()
  110. #-----------------------------------------------------------------------------
  111. # Function to create initial content.
  112. function(create_content dir)
  113. file(MAKE_DIRECTORY ${TOP}/${dir})
  114. # An example CTest project configuration file.
  115. file(WRITE ${TOP}/${dir}/CTestConfig.cmake
  116. "# CTest Configuration File
  117. set(CTEST_PROJECT_NAME TestProject)
  118. set(CTEST_NIGHTLY_START_TIME \"21:00:00 EDT\")
  119. ")
  120. # Some other files.
  121. file(WRITE ${TOP}/${dir}/foo.txt "foo\n")
  122. file(WRITE ${TOP}/${dir}/bar.txt "bar\n")
  123. endfunction()
  124. #-----------------------------------------------------------------------------
  125. # Function to update content.
  126. function(update_content dir added_var removed_var dirs_var)
  127. file(APPEND ${TOP}/${dir}/foo.txt "foo line 2\n")
  128. file(WRITE ${TOP}/${dir}/zot.txt "zot\n")
  129. file(REMOVE ${TOP}/${dir}/bar.txt)
  130. file(MAKE_DIRECTORY ${TOP}/${dir}/subdir)
  131. file(WRITE ${TOP}/${dir}/subdir/foo.txt "foo\n")
  132. file(WRITE ${TOP}/${dir}/subdir/bar.txt "bar\n")
  133. set(${dirs_var} subdir PARENT_SCOPE)
  134. set(${added_var} zot.txt subdir/foo.txt subdir/bar.txt PARENT_SCOPE)
  135. set(${removed_var} bar.txt PARENT_SCOPE)
  136. endfunction()
  137. #-----------------------------------------------------------------------------
  138. # Function to change existing files
  139. function(change_content dir)
  140. file(APPEND ${TOP}/${dir}/foo.txt "foo line 3\n")
  141. file(APPEND ${TOP}/${dir}/subdir/foo.txt "foo line 2\n")
  142. endfunction()
  143. #-----------------------------------------------------------------------------
  144. # Function to create local modifications before update
  145. function(modify_content dir)
  146. file(APPEND ${TOP}/${dir}/CTestConfig.cmake "# local modification\n")
  147. endfunction()
  148. #-----------------------------------------------------------------------------
  149. # Function to write CTestConfiguration.ini content.
  150. function(create_build_tree src_dir bin_dir)
  151. file(MAKE_DIRECTORY ${TOP}/${bin_dir})
  152. file(WRITE ${TOP}/${bin_dir}/CTestConfiguration.ini
  153. "# CTest Configuration File
  154. SourceDirectory: ${TOP}/${src_dir}
  155. BuildDirectory: ${TOP}/${bin_dir}
  156. Site: test.site
  157. BuildName: user-test
  158. ")
  159. endfunction()
  160. #-----------------------------------------------------------------------------
  161. # Function to write the dashboard test script.
  162. function(create_dashboard_script bin_dir custom_text)
  163. # Write the dashboard script.
  164. file(WRITE ${TOP}/${bin_dir}.cmake
  165. "# CTest Dashboard Script
  166. set(CTEST_DASHBOARD_ROOT \"${TOP}\")
  167. set(CTEST_SITE test.site)
  168. set(CTEST_BUILD_NAME dash-test)
  169. set(CTEST_SOURCE_DIRECTORY \${CTEST_DASHBOARD_ROOT}/dash-source)
  170. set(CTEST_BINARY_DIRECTORY \${CTEST_DASHBOARD_ROOT}/${bin_dir})
  171. ${custom_text}
  172. # Start a dashboard and run the update step
  173. ctest_start(Experimental)
  174. ctest_update(SOURCE \${CTEST_SOURCE_DIRECTORY})
  175. ")
  176. endfunction()
  177. #-----------------------------------------------------------------------------
  178. # Function to run the dashboard through the command line
  179. function(run_dashboard_command_line bin_dir)
  180. run_child(
  181. WORKING_DIRECTORY ${TOP}/${bin_dir}
  182. COMMAND ${CMAKE_CTEST_COMMAND} -M Experimental -T Start -T Update
  183. )
  184. # Verify the updates reported by CTest.
  185. list(APPEND UPDATE_MAYBE Updated{subdir})
  186. set(_modified Modified{CTestConfig.cmake})
  187. if(UPDATE_NO_MODIFIED)
  188. set(_modified "")
  189. endif()
  190. check_updates(${bin_dir}
  191. Updated{foo.txt}
  192. Updated{bar.txt}
  193. Updated{zot.txt}
  194. Updated{subdir/foo.txt}
  195. Updated{subdir/bar.txt}
  196. ${_modified}
  197. )
  198. endfunction()
  199. #-----------------------------------------------------------------------------
  200. # Function to find the Update.xml file and make sure
  201. # it only has the Revision in it and no updates
  202. function(check_no_update bin_dir)
  203. set(PATTERN ${TOP}/${bin_dir}/Testing/*/Update.xml)
  204. file(GLOB UPDATE_XML_FILE RELATIVE ${TOP} ${PATTERN})
  205. string(REGEX REPLACE "//Update.xml$" "/Update.xml"
  206. UPDATE_XML_FILE "${UPDATE_XML_FILE}")
  207. message(" found ${UPDATE_XML_FILE}")
  208. set(rev_regex "Revision|PriorRevision")
  209. file(STRINGS ${TOP}/${UPDATE_XML_FILE} UPDATE_XML_REVISIONS
  210. REGEX "^\t<(${rev_regex})>[^<\n]+</(${rev_regex})>$"
  211. )
  212. set(found_revisons FALSE)
  213. foreach(r IN LISTS UPDATE_XML_REVISIONS)
  214. if("${r}" MATCHES "PriorRevision")
  215. message(FATAL_ERROR "Found PriorRevision in no update test")
  216. endif()
  217. if("${r}" MATCHES "<Revision>")
  218. set(found_revisons TRUE)
  219. endif()
  220. endforeach()
  221. if(found_revisons)
  222. message(" found <Revision> in no update test")
  223. else()
  224. message(FATAL_ERROR " missing <Revision> in no update test")
  225. endif()
  226. endfunction()
  227. #-----------------------------------------------------------------------------
  228. # Function to run the dashboard through a script
  229. function(run_dashboard_script bin_dir)
  230. run_child(
  231. WORKING_DIRECTORY ${TOP}
  232. COMMAND ${CMAKE_CTEST_COMMAND} -S ${bin_dir}.cmake -V
  233. )
  234. # Verify the updates reported by CTest.
  235. list(APPEND UPDATE_MAYBE Updated{subdir} Updated{CTestConfig.cmake})
  236. if(NO_UPDATE)
  237. check_no_update(${bin_dir})
  238. else()
  239. check_updates(${bin_dir}
  240. Updated{foo.txt}
  241. Updated{bar.txt}
  242. Updated{zot.txt}
  243. Updated{subdir/foo.txt}
  244. Updated{subdir/bar.txt}
  245. )
  246. endif()
  247. endfunction()
  248. #-----------------------------------------------------------------------------
  249. # Function to initialize the testing directory.
  250. function(init_testing)
  251. file(REMOVE_RECURSE ${TOP})
  252. file(MAKE_DIRECTORY ${TOP})
  253. endfunction()