CTestUpdateCommon.cmake 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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(REGEX 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. list(REMOVE_ITEM MISSING ${UPDATE_XML_ENTRIES})
  52. if(NOT UPDATE_NOT_GLOBAL)
  53. set(rev_elements Revision PriorRevision ${UPDATE_GLOBAL_ELEMENTS})
  54. string(REPLACE ";" "|" rev_regex "${rev_elements}")
  55. set(rev_regex "^\t<(${rev_regex})>[^<\n]+</(${rev_regex})>$")
  56. file(STRINGS ${TOP}/${UPDATE_XML_FILE} UPDATE_XML_REVISIONS
  57. REGEX "${rev_regex}"
  58. LIMIT_INPUT ${max_update_xml_size}
  59. )
  60. foreach(r IN LISTS UPDATE_XML_REVISIONS)
  61. string(REGEX REPLACE "${rev_regex}" "\\1" element "${r}")
  62. set(element_${element} 1)
  63. endforeach()
  64. foreach(element ${rev_elements})
  65. if(NOT element_${element})
  66. list(APPEND MISSING "global <${element}> element")
  67. endif()
  68. endforeach()
  69. endif()
  70. # Report the result
  71. set(MSG "")
  72. if(MISSING)
  73. # List the missing entries
  74. set(MSG "${MSG}Update.xml is missing expected entries:\n")
  75. foreach(f ${MISSING})
  76. set(MSG "${MSG} ${f}\n")
  77. endforeach()
  78. else()
  79. # Success
  80. message(" no entries missing from Update.xml")
  81. endif()
  82. # Report the result
  83. if(EXTRA)
  84. # List the extra entries
  85. set(MSG "${MSG}Update.xml has extra unexpected entries:\n")
  86. foreach(f ${EXTRA})
  87. set(MSG "${MSG} ${f}\n")
  88. endforeach()
  89. else()
  90. # Success
  91. message(" no extra entries in Update.xml")
  92. endif()
  93. if(MSG)
  94. # Provide the log file
  95. file(GLOB UPDATE_LOG_FILE
  96. ${TOP}/${build}/Testing/Temporary/LastUpdate*.log)
  97. if(UPDATE_LOG_FILE)
  98. file(READ ${UPDATE_LOG_FILE} UPDATE_LOG LIMIT ${max_update_xml_size})
  99. string(REGEX REPLACE "\n" "\n " UPDATE_LOG "${UPDATE_LOG}")
  100. set(MSG "${MSG}Update log:\n ${UPDATE_LOG}")
  101. else()
  102. set(MSG "${MSG}No update log found!")
  103. endif()
  104. # Display the error message
  105. message(FATAL_ERROR "${MSG}")
  106. endif()
  107. endfunction()
  108. #-----------------------------------------------------------------------------
  109. # Function to create initial content.
  110. function(create_content dir)
  111. file(MAKE_DIRECTORY ${TOP}/${dir})
  112. # An example CTest project configuration file.
  113. file(WRITE ${TOP}/${dir}/CTestConfig.cmake
  114. "# CTest Configuration File
  115. set(CTEST_PROJECT_NAME TestProject)
  116. set(CTEST_NIGHTLY_START_TIME \"21:00:00 EDT\")
  117. ")
  118. # Some other files.
  119. file(WRITE ${TOP}/${dir}/foo.txt "foo\n")
  120. file(WRITE ${TOP}/${dir}/bar.txt "bar\n")
  121. endfunction()
  122. #-----------------------------------------------------------------------------
  123. # Function to update content.
  124. function(update_content dir added_var removed_var dirs_var)
  125. file(APPEND ${TOP}/${dir}/foo.txt "foo line 2\n")
  126. file(WRITE ${TOP}/${dir}/zot.txt "zot\n")
  127. file(REMOVE ${TOP}/${dir}/bar.txt)
  128. file(MAKE_DIRECTORY ${TOP}/${dir}/subdir)
  129. file(WRITE ${TOP}/${dir}/subdir/foo.txt "foo\n")
  130. file(WRITE ${TOP}/${dir}/subdir/bar.txt "bar\n")
  131. set(${dirs_var} subdir PARENT_SCOPE)
  132. set(${added_var} zot.txt subdir/foo.txt subdir/bar.txt PARENT_SCOPE)
  133. set(${removed_var} bar.txt PARENT_SCOPE)
  134. endfunction()
  135. #-----------------------------------------------------------------------------
  136. # Function to change existing files
  137. function(change_content dir)
  138. file(APPEND ${TOP}/${dir}/foo.txt "foo line 3\n")
  139. file(APPEND ${TOP}/${dir}/subdir/foo.txt "foo line 2\n")
  140. endfunction()
  141. #-----------------------------------------------------------------------------
  142. # Function to create local modifications before update
  143. function(modify_content dir)
  144. file(APPEND ${TOP}/${dir}/CTestConfig.cmake "# local modification\n")
  145. endfunction()
  146. #-----------------------------------------------------------------------------
  147. # Function to write CTestConfiguration.ini content.
  148. function(create_build_tree src_dir bin_dir)
  149. file(MAKE_DIRECTORY ${TOP}/${bin_dir})
  150. file(WRITE ${TOP}/${bin_dir}/CTestConfiguration.ini
  151. "# CTest Configuration File
  152. SourceDirectory: ${TOP}/${src_dir}
  153. BuildDirectory: ${TOP}/${bin_dir}
  154. Site: test.site
  155. BuildName: user-test
  156. ")
  157. endfunction()
  158. #-----------------------------------------------------------------------------
  159. # Function to write the dashboard test script.
  160. function(create_dashboard_script bin_dir custom_text)
  161. # Write the dashboard script.
  162. file(WRITE ${TOP}/${bin_dir}.cmake
  163. "# CTest Dashboard Script
  164. set(CTEST_DASHBOARD_ROOT \"${TOP}\")
  165. set(CTEST_SITE test.site)
  166. set(CTEST_BUILD_NAME dash-test)
  167. set(CTEST_SOURCE_DIRECTORY \${CTEST_DASHBOARD_ROOT}/dash-source)
  168. set(CTEST_BINARY_DIRECTORY \${CTEST_DASHBOARD_ROOT}/${bin_dir})
  169. ${custom_text}
  170. # Start a dashboard and run the update step
  171. ctest_start(Experimental)
  172. ctest_update(SOURCE \${CTEST_SOURCE_DIRECTORY})
  173. ")
  174. endfunction()
  175. #-----------------------------------------------------------------------------
  176. # Function to run the dashboard through the command line
  177. function(run_dashboard_command_line bin_dir)
  178. run_child(
  179. WORKING_DIRECTORY ${TOP}/${bin_dir}
  180. COMMAND ${CMAKE_CTEST_COMMAND} -M Experimental -T Start -T Update
  181. )
  182. # Verify the updates reported by CTest.
  183. list(APPEND UPDATE_MAYBE Updated{subdir})
  184. set(_modified Modified{CTestConfig.cmake})
  185. if(UPDATE_NO_MODIFIED)
  186. set(_modified "")
  187. endif()
  188. check_updates(${bin_dir}
  189. Updated{foo.txt}
  190. Updated{bar.txt}
  191. Updated{zot.txt}
  192. Updated{subdir/foo.txt}
  193. Updated{subdir/bar.txt}
  194. ${_modified}
  195. )
  196. endfunction()
  197. #-----------------------------------------------------------------------------
  198. # Function to run the dashboard through a script
  199. function(run_dashboard_script bin_dir)
  200. run_child(
  201. WORKING_DIRECTORY ${TOP}
  202. COMMAND ${CMAKE_CTEST_COMMAND} -S ${bin_dir}.cmake -V
  203. )
  204. # Verify the updates reported by CTest.
  205. list(APPEND UPDATE_MAYBE Updated{subdir} Updated{CTestConfig.cmake})
  206. check_updates(${bin_dir}
  207. Updated{foo.txt}
  208. Updated{bar.txt}
  209. Updated{zot.txt}
  210. Updated{subdir/foo.txt}
  211. Updated{subdir/bar.txt}
  212. )
  213. endfunction()
  214. #-----------------------------------------------------------------------------
  215. # Function to initialize the testing directory.
  216. function(init_testing)
  217. file(REMOVE_RECURSE ${TOP})
  218. file(MAKE_DIRECTORY ${TOP})
  219. endfunction()