1#!/usr/bin/python 2 3# Copyright 2002-2005 Dave Abrahams. 4# Copyright 2002-2006 Vladimir Prus. 5# Distributed under the Boost Software License, Version 1.0. 6# (See accompanying file LICENSE_1_0.txt or copy at 7# http://www.boost.org/LICENSE_1_0.txt) 8 9from __future__ import print_function 10 11import BoostBuild 12 13import os 14import os.path 15import sys 16 17xml = "--xml" in sys.argv 18toolset = BoostBuild.get_toolset() 19 20 21# Clear environment for testing. 22# 23for s in ("BOOST_ROOT", "BOOST_BUILD_PATH", "JAM_TOOLSET", "BCCROOT", 24 "MSVCDir", "MSVC", "MSVCNT", "MINGW", "watcom"): 25 try: 26 del os.environ[s] 27 except: 28 pass 29 30BoostBuild.set_defer_annotations(1) 31 32 33def run_tests(critical_tests, other_tests): 34 """ 35 Runs first the critical_tests and then the other_tests. 36 37 Writes the name of the first failed test to test_results.txt. Critical 38 tests are run in the specified order, other tests are run starting with the 39 one that failed first on the last test run. 40 41 """ 42 last_failed = last_failed_test() 43 other_tests = reorder_tests(other_tests, last_failed) 44 all_tests = critical_tests + other_tests 45 46 invocation_dir = os.getcwd() 47 max_test_name_len = 10 48 for x in all_tests: 49 if len(x) > max_test_name_len: 50 max_test_name_len = len(x) 51 52 pass_count = 0 53 failures_count = 0 54 55 for test in all_tests: 56 if not xml: 57 s = "%%-%ds :" % max_test_name_len % test 58 print(s, end='') 59 60 passed = 0 61 try: 62 __import__(test) 63 passed = 1 64 except KeyboardInterrupt: 65 """This allows us to abort the testing manually using Ctrl-C.""" 66 raise 67 except SystemExit: 68 """This is the regular way our test scripts are supposed to report 69 test failures.""" 70 except: 71 exc_type, exc_value, exc_tb = sys.exc_info() 72 try: 73 BoostBuild.annotation("failure - unhandled exception", "%s - " 74 "%s" % (exc_type.__name__, exc_value)) 75 BoostBuild.annotate_stack_trace(exc_tb) 76 finally: 77 # Explicitly clear a hard-to-garbage-collect traceback 78 # related reference cycle as per documented sys.exc_info() 79 # usage suggestion. 80 del exc_tb 81 82 if passed: 83 pass_count += 1 84 else: 85 failures_count += 1 86 if failures_count == 1: 87 f = open(os.path.join(invocation_dir, "test_results.txt"), "w") 88 try: 89 f.write(test) 90 finally: 91 f.close() 92 93 # Restore the current directory, which might have been changed by the 94 # test. 95 os.chdir(invocation_dir) 96 97 if not xml: 98 if passed: 99 print("PASSED") 100 else: 101 print("FAILED") 102 BoostBuild.flush_annotations() 103 else: 104 rs = "succeed" 105 if not passed: 106 rs = "fail" 107 print(''' 108<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s"> 109<run result="%s">''' % (test, toolset, "tools/build/v2/test/" + test + ".py", 110 "boost/bin.v2/boost.build.tests/" + toolset + "/" + test, rs)) 111 if not passed: 112 BoostBuild.flush_annotations(1) 113 print(''' 114</run> 115</test-log> 116''') 117 sys.stdout.flush() # Makes testing under emacs more entertaining. 118 BoostBuild.clear_annotations() 119 120 # Erase the file on success. 121 if failures_count == 0: 122 open("test_results.txt", "w").close() 123 124 if not xml: 125 print(''' 126 === Test summary === 127 PASS: %d 128 FAIL: %d 129 ''' % (pass_count, failures_count)) 130 131 # exit with failure with failures 132 if failures_count > 0: 133 sys.exit(1) 134 135def last_failed_test(): 136 "Returns the name of the last failed test or None." 137 try: 138 f = open("test_results.txt") 139 try: 140 return f.read().strip() 141 finally: 142 f.close() 143 except Exception: 144 return None 145 146 147def reorder_tests(tests, first_test): 148 try: 149 n = tests.index(first_test) 150 return [first_test] + tests[:n] + tests[n + 1:] 151 except ValueError: 152 return tests 153 154 155critical_tests = ["unit_tests", "module_actions", "startup_v2", "core_d12", 156 "core_typecheck", "core_delete_module", "core_language", "core_arguments", 157 "core_varnames", "core_import_module"] 158 159# We want to collect debug information about the test site before running any 160# of the tests, but only when not running the tests interactively. Then the 161# user can easily run this always-failing test directly to see what it would 162# have returned and there is no need to have it spoil a possible 'all tests 163# passed' result. 164if xml: 165 critical_tests.insert(0, "collect_debug_info") 166 167tests = ["absolute_sources", 168 "alias", 169 "alternatives", 170 "always", 171 "bad_dirname", 172 "build_dir", 173 "build_file", 174 "build_hooks", 175 "build_no", 176 "builtin_echo", 177 "builtin_exit", 178 "builtin_glob", 179 "builtin_split_by_characters", 180 "bzip2", 181 "c_file", 182 "chain", 183 "clean", 184 "command_line_properties", 185 "composite", 186 "conditionals", 187 "conditionals2", 188 "conditionals3", 189 "conditionals_multiple", 190 "configuration", 191 "configure", 192 "copy_time", 193 "core_action_output", 194 "core_action_status", 195 "core_actions_quietly", 196 "core_at_file", 197 "core_bindrule", 198 "core_syntax_error_exit_status", 199 "core_fail_expected", 200 "core_jamshell", 201 "core_multifile_actions", 202 "core_nt_cmd_line", 203 "core_option_d2", 204 "core_option_l", 205 "core_option_n", 206 "core_parallel_actions", 207 "core_parallel_multifile_actions_1", 208 "core_parallel_multifile_actions_2", 209 "core_scanner", 210 "core_source_line_tracking", 211 "core_update_now", 212 "core_variables_in_actions", 213 "custom_generator", 214 "debugger", 215 "debugger-mi", 216 "default_build", 217 "default_features", 218# This test is known to be broken itself. 219# "default_toolset", 220 "dependency_property", 221 "dependency_test", 222 "disambiguation", 223 "dll_path", 224 "double_loading", 225 "duplicate", 226 "example_libraries", 227 "example_make", 228 "exit_status", 229 "expansion", 230 "explicit", 231 "feature_cxxflags", 232 "feature_implicit_dependency", 233 "feature_relevant", 234 "feature_suppress_import_lib", 235 "file_types", 236 "flags", 237 "generator_selection", 238 "generators_test", 239 "implicit_dependency", 240 "indirect_conditional", 241 "inherit_toolset", 242 "inherited_dependency", 243 "inline", 244 "libjpeg", 245 "liblzma", 246 "libzstd", 247 "lib_source_property", 248 "lib_zlib", 249 "library_chain", 250 "library_property", 251 "link", 252 "load_order", 253 "loop", 254 "make_rule", 255 "message", 256 "ndebug", 257 "no_type", 258 "notfile", 259 "ordered_include", 260 "out_of_tree", 261 "package", 262 "param", 263 "path_features", 264 "prebuilt", 265 "print", 266 "project_dependencies", 267 "project_glob", 268 "project_id", 269 "project_root_constants", 270 "project_root_rule", 271 "project_test3", 272 "project_test4", 273 "property_expansion", 274 "rebuilds", 275 "relative_sources", 276 "remove_requirement", 277 "rescan_header", 278 "resolution", 279 "rootless", 280 "scanner_causing_rebuilds", 281 "searched_lib", 282 "skipping", 283 "sort_rule", 284 "source_locations", 285 "source_order", 286 "space_in_path", 287 "stage", 288 "standalone", 289 "static_and_shared_library", 290 "suffix", 291 "tag", 292 "test_rc", 293 "testing", 294 "timedata", 295 "toolset_clang_darwin", 296 "toolset_clang_linux", 297 "toolset_clang_vxworks", 298 "toolset_darwin", 299 "toolset_defaults", 300 "toolset_gcc", 301 "toolset_intel_darwin", 302 "toolset_requirements", 303 "unit_test", 304 "unused", 305 "use_requirements", 306 "using", 307 "wrapper", 308 "wrong_project", 309 ] 310 311if os.name == "posix": 312 tests.append("symlink") 313 # On Windows, library order is not important, so skip this test. Besides, 314 # it fails ;-). Further, the test relies on the fact that on Linux, one can 315 # build a shared library with unresolved symbols. This is not true on 316 # Windows, even with cygwin gcc. 317 318# Disable this test until we figure how to address failures due to --as-needed being default now. 319# if "CYGWIN" not in os.uname()[0]: 320# tests.append("library_order") 321 322if toolset.startswith("gcc") and os.name != "nt": 323 # On Windows it's allowed to have a static runtime with gcc. But this test 324 # assumes otherwise. Hence enable it only when not on Windows. 325 tests.append("gcc_runtime") 326 327# PCH test seems broken in strange ways. Disable it. 328# if toolset.startswith("gcc") or toolset.startswith("msvc"): 329# tests.append("pch") 330 331# Disable on OSX as it doesn't seem to work for unknown reasons. 332if sys.platform != 'darwin': 333 tests.append("builtin_glob_archive") 334 335if "--extras" in sys.argv: 336 tests.append("boostbook") 337 tests.append("qt4") 338 tests.append("qt5") 339 tests.append("example_qt4") 340 # Requires ./whatever.py to work, so is not guaranteed to work everywhere. 341 tests.append("example_customization") 342 # Requires gettext tools. 343 tests.append("example_gettext") 344elif not xml: 345 print("Note: skipping extra tests") 346 347run_tests(critical_tests, tests) 348