From 9ee552969c8c13f4c4e3a6c992aec557a2bc70a3 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Fri, 6 Nov 2020 13:57:46 -0800 Subject: [PATCH] Let's rewrite the test harness (#1394) Co-authored-by: Casey Carter Co-authored-by: Stephan T. Lavavej --- azure-devops/run-build.yml | 2 +- tests/CMakeLists.txt | 2 + tests/libcxx/CMakeLists.txt | 4 +- tests/libcxx/lit.cfg | 30 +- tests/libcxx/lit.site.cfg.in | 51 ++- tests/libcxx/usual_matrix.lst | 2 +- tests/std/lit.cfg | 30 +- tests/std/lit.site.cfg.in | 52 ++- .../{test.cpp => test.compile.pass.cpp} | 0 .../custom_format.py | 41 +- .../Dev09_056375_locale_cleanup/lit.local.cfg | 9 +- .../custom_format.py | 27 +- .../Dev09_172666_tr1_tuple_odr/lit.local.cfg | 9 +- .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../custom_format.py | 29 +- .../GH_000545_include_compare/lit.local.cfg | 9 +- .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../P0607R0_inline_variables/custom_format.py | 27 +- .../P0607R0_inline_variables/lit.local.cfg | 9 +- .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../custom_format.py | 61 ++- .../lit.local.cfg | 9 +- .../custom_format.py | 62 ++- .../lit.local.cfg | 11 +- .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../custom_format.py | 27 +- .../lit.local.cfg | 9 +- .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 tests/std/tests/fast_matrix.lst | 2 +- tests/std/tests/rtti_matrix.lst | 2 +- tests/tr1/env_single.lst | 2 +- tests/tr1/lit.cfg | 30 +- tests/tr1/lit.site.cfg.in | 51 ++- tests/utils/stl/compiler.py | 211 --------- tests/utils/stl/test/config.py | 412 ++--------------- tests/utils/stl/test/executor.py | 235 ---------- tests/utils/stl/test/features.py | 48 ++ tests/utils/stl/test/format.py | 428 ++++++++---------- tests/utils/stl/test/params.py | 18 + tests/utils/stl/test/target_info.py | 45 -- tests/utils/stl/test/tests.py | 349 +++++++------- tests/utils/stl/test/tracing.py | 41 -- 74 files changed, 749 insertions(+), 1637 deletions(-) rename tests/std/tests/Dev08_527068_scl_no_exceptions/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev10_609053_ctype_char_table_size/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev10_709168_marking_iterators_as_checked/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0000000_include_each_header_alone/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0272959_make_signed/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0437519_container_requirements/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0453373_codecvt_compiles/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0483851_vector_debug_allocator_use/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0704582_ratio/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/GH_000890_pow_template/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0758R1_is_nothrow_convertible/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0896R4_ranges_algorithm_machinery/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0896R4_ranges_subrange/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0896R4_ranges_test_machinery/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P1423R3_char8_t_remediation/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_fancy_pointers/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_containers/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_cvt/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_iterators_misc/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_type_traits/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_strengthened_noexcept/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0157762_feature_test_macros/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0180469_ptr_cat/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0191296_allocator_construct/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0493909_is_aggregate/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0527559_pragma_managed/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0938757_attribute_order/{test.cpp => test.compile.pass.cpp} (100%) delete mode 100644 tests/utils/stl/compiler.py delete mode 100644 tests/utils/stl/test/executor.py create mode 100644 tests/utils/stl/test/features.py create mode 100644 tests/utils/stl/test/params.py delete mode 100644 tests/utils/stl/test/target_info.py delete mode 100644 tests/utils/stl/test/tracing.py diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index 2d52b4537..bf4c14361 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -63,7 +63,7 @@ jobs: cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=$(vcpkgLocation)\scripts\buildsystems\vcpkg.cmake ^ -DVCPKG_TARGET_TRIPLET=${{ parameters.targetPlatform }}-windows -DCMAKE_CXX_COMPILER=cl ^ -DCMAKE_BUILD_TYPE=Release -DLIT_FLAGS=$(litFlags) ^ - -DCMAKE_CXX_FLAGS=/analyze ^ + -DCMAKE_CXX_FLAGS=/analyze:autolog- ^ -S $(Build.SourcesDirectory) -B $(buildOutputLocation) cmake --build $(buildOutputLocation) displayName: 'Build the STL' diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1103c9dd3..fab5573e6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,8 @@ set(STL_TESTED_HEADERS_DIR "${STL_BUILD_ROOT}/inc") set(LLVM_PROJECT_SOURCE_DIR "${STL_SOURCE_DIR}/llvm-project" CACHE PATH "Location of the llvm-project source tree") +set(LIBCXX_SOURCE_DIR "${LLVM_PROJECT_SOURCE_DIR}/libcxx" CACHE PATH + "Location of the libcxx source tree") add_subdirectory(libcxx) add_subdirectory(std) diff --git a/tests/libcxx/CMakeLists.txt b/tests/libcxx/CMakeLists.txt index 0aba3abeb..cdcc763ff 100644 --- a/tests/libcxx/CMakeLists.txt +++ b/tests/libcxx/CMakeLists.txt @@ -3,8 +3,6 @@ set(LIBCXX_ENVLST "${CMAKE_CURRENT_SOURCE_DIR}/usual_matrix.lst") set(LIBCXX_EXPECTED_RESULTS "${CMAKE_CURRENT_SOURCE_DIR}/expected_results.txt") -set(LIBCXX_SOURCE_DIR "${LLVM_PROJECT_SOURCE_DIR}/libcxx" CACHE PATH - "Location of the libcxx source tree") set(LIBCXX_TEST_OUTPUT_DIR "${STL_TEST_OUTPUT_DIR}/libcxx") configure_file( @@ -12,5 +10,7 @@ configure_file( ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg.py\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") +string(APPEND LIBCXX_LIT_CONFIG_MAP "map_config(\"${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") + set_property(GLOBAL APPEND_STRING PROPERTY STL_LIT_CONFIG_MAP ${LIBCXX_LIT_CONFIG_MAP}) set_property(GLOBAL APPEND PROPERTY STL_LIT_TEST_DIRS "${LIBCXX_SOURCE_DIR}/test/std") diff --git a/tests/libcxx/lit.cfg b/tests/libcxx/lit.cfg index 44b72cde9..e97953f5b 100644 --- a/tests/libcxx/lit.cfg +++ b/tests/libcxx/lit.cfg @@ -1,29 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path -import importlib -import site - -site.addsitedir(str(Path(__file__).parents[1] / "utils")) -site.addsitedir(str(Path(__file__).parent / "tests")) - -config.name = 'libc++' -config.suffixes = {".pass.cpp", ".fail.cpp"} - -if config.test_source_root is None: - config.test_source_root = str(Path(__file__).parent) - -config.test_exec_root = getattr(config, 'test_exec_root', None) - -if not config.test_exec_root: - import tempfile - config.test_exec_root = tempfile.mkdtemp(prefix=config.name + '-testsuite-') - lit_config.note('Creating temporary directory for tests: %s' % config.test_exec_root) - -config_module_name = getattr(config, 'config_module_name', 'stl.test.config') -config_module = importlib.import_module(config_module_name) - -configuration = config_module.Configuration(lit_config, config) -configuration.configure() -config.test_format = configuration.get_test_format() +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index c3eea2c29..fb530312e 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -1,25 +1,40 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os import site site.addsitedir("@STL_TEST_UTILS_DIR@") +site.addsitedir(os.path.join("@LIBCXX_SOURCE_DIR@", "utils")) +import stl.test.config +import stl.test.features +import stl.test.file_parsing +import stl.test.format +import stl.test.params -config.configuration_variant = "stl" -config.cxx_archive_root = "@CMAKE_ARCHIVE_OUTPUT_DIRECTORY@" -config.cxx_headers = "@STL_TESTED_HEADERS_DIR@" -config.cxx_library_root = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" -config.cxx_runtime_root = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" -config.envlst_path = "@LIBCXX_ENVLST@" -config.expected_results_list_path = "@LIBCXX_EXPECTED_RESULTS@" -config.format_name = "LibcxxTestFormat" -config.include_dirs = ["@LIBCXX_SOURCE_DIR@/test/support"] -config.libcxx_obj_root = "@LIBCXX_TEST_OUTPUT_DIR@" -config.msvc_toolset_libs_root = "@TOOLSET_LIB@" -config.stl_build_root = "@STL_BUILD_ROOT@" -config.stl_src_root = "@STL_SOURCE_DIR@" -config.target_arch = "@VCLIBS_TARGET_ARCHITECTURE@" -config.test_exec_root = "@LIBCXX_TEST_OUTPUT_DIR@" -config.test_source_root = "@LIBCXX_SOURCE_DIR@/test" -config.test_subdirs = ["@LIBCXX_SOURCE_DIR@/test/std"] +config.envlst_path = '@LIBCXX_ENVLST@' +config.name = 'libc++' +config.suffixes = ['[.]pass[.]cpp$', '[.]fail[.]cpp$'] +config.test_exec_root = '@LIBCXX_TEST_OUTPUT_DIR@' +config.test_format = stl.test.format.LibcxxTestFormat() +config.test_source_root = '@LIBCXX_SOURCE_DIR@/test' -lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") +lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) +lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) +lit_config.library_dirs = getattr(lit_config, 'library_dirs', dict()) +lit_config.test_subdirs = getattr(lit_config, 'test_subdirs', dict()) + +lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@LIBCXX_EXPECTED_RESULTS@') +lit_config.include_dirs[config.name] = ['@STL_TESTED_HEADERS_DIR@', '@LIBCXX_SOURCE_DIR@/test/support'] +lit_config.library_dirs[config.name] = ['@CMAKE_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.test_subdirs[config.name] = ['@LIBCXX_SOURCE_DIR@/test/std'] + +lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/libcxx/usual_matrix.lst b/tests/libcxx/usual_matrix.lst index 5fa9799ff..a5dd5afec 100644 --- a/tests/libcxx/usual_matrix.lst +++ b/tests/libcxx/usual_matrix.lst @@ -5,5 +5,5 @@ RUNALL_INCLUDE ..\universal_prefix.lst RUNALL_CROSSLIST PM_CL="/EHsc /MTd /std:c++latest /permissive- /FImsvc_stdlib_force_include.h /wd4643" RUNALL_CROSSLIST -PM_CL="/analyze /Zc:preprocessor" +PM_CL="/analyze:autolog- /Zc:preprocessor" PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing" diff --git a/tests/std/lit.cfg b/tests/std/lit.cfg index fc5389e03..e97953f5b 100644 --- a/tests/std/lit.cfg +++ b/tests/std/lit.cfg @@ -1,29 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path -import importlib -import site - -site.addsitedir(str(Path(__file__).parents[1] / "utils")) -site.addsitedir(str(Path(__file__).parent / "tests")) - -config.name = 'std' -config.suffixes.add('test.cpp') - -if config.test_source_root is None: - config.test_source_root = str(Path(__file__).parent) - -config.test_exec_root = getattr(config, 'test_exec_root', None) - -if not config.test_exec_root: - import tempfile - config.test_exec_root = tempfile.mkdtemp(prefix=config.name + '-testsuite-') - lit_config.note('Creating temporary directory for tests: %s' % config.test_exec_root) - -config_module_name = getattr(config, 'config_module_name', 'stl.test.config') -config_module = importlib.import_module(config_module_name) - -configuration = config_module.Configuration(lit_config, config) -configuration.configure() -config.test_format = configuration.get_test_format() +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/std/lit.site.cfg.in b/tests/std/lit.site.cfg.in index e3998e65f..9a2de0aa0 100644 --- a/tests/std/lit.site.cfg.in +++ b/tests/std/lit.site.cfg.in @@ -1,18 +1,42 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -config.cxx_archive_root = "@CMAKE_ARCHIVE_OUTPUT_DIRECTORY@" -config.cxx_headers = "@STL_TESTED_HEADERS_DIR@" -config.cxx_library_root = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" -config.cxx_runtime_root = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" -config.expected_results_list_path = "@STD_EXPECTED_RESULTS@" -config.include_dirs = ["@LIBCXX_SOURCE_DIR@/test/support", "@STL_SOURCE_DIR@/tests/std/include"] -config.msvc_toolset_libs_root = "@TOOLSET_LIB@" -config.stl_build_root = "@STL_BUILD_ROOT@" -config.stl_src_root = "@STL_SOURCE_DIR@" -config.target_arch = "@VCLIBS_TARGET_ARCHITECTURE@" -config.test_exec_root = "@STD_TEST_OUTPUT_DIR@" -config.test_subdirs_file = "@STD_TEST_SUBDIRS_FILE@" -config.test_subdirs_root = "@STD_TEST_SUBDIRS_ROOT@" +import os +import site +site.addsitedir("@STL_TEST_UTILS_DIR@") +site.addsitedir(os.path.join("@LIBCXX_SOURCE_DIR@", "utils")) +import stl.test.config +import stl.test.features +import stl.test.file_parsing +import stl.test.format +import stl.test.params -lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") +config.name = 'std' +config.suffixes = ['test[.]cpp$', 'test[.]compile[.]pass[.]cpp$'] +config.test_exec_root = "@STD_TEST_OUTPUT_DIR@" +config.test_format = stl.test.format.STLTestFormat() + +lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) +lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) +lit_config.library_dirs = getattr(lit_config, 'library_dirs', dict()) +lit_config.test_subdirs = getattr(lit_config, 'test_subdirs', dict()) + +lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@STD_EXPECTED_RESULTS@') +lit_config.include_dirs[config.name] = \ + ['@STL_TESTED_HEADERS_DIR@', '@LIBCXX_SOURCE_DIR@/test/support', '@STL_SOURCE_DIR@/tests/std/include'] +lit_config.library_dirs[config.name] = ['@CMAKE_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.test_subdirs[config.name] = \ + [os.path.normpath(os.path.join('@STD_TEST_SUBDIRS_ROOT@', path)) for \ + path in stl.test.file_parsing.parse_commented_file('@STD_TEST_SUBDIRS_FILE@')] + +lit_config.cxx_headers = '@STL_TESTED_HEADERS_DIR@' +lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/std/tests/Dev08_527068_scl_no_exceptions/test.cpp b/tests/std/tests/Dev08_527068_scl_no_exceptions/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev08_527068_scl_no_exceptions/test.cpp rename to tests/std/tests/Dev08_527068_scl_no_exceptions/test.compile.pass.cpp diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py index 9d7c64eea..1792181ec 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py +++ b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py @@ -1,42 +1,23 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import os from stl.test.format import STLTestFormat, TestStep class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - exe_source = Path(test.getSourcePath()) - dll_source = exe_source.parent / 'TestDll.cpp' - shared.exec_dir = test.getExecDir() - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - pass_var, fail_var = test.getPassFailResultCodes() - dll_output = output_dir / 'TestDll.DLL' + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + dllSource = os.path.join(os.path.dirname(exeSource), 'TestDll.cpp') - dll_compile_cmd, out_files, exec_file = \ - test.cxx.executeBasedOnFlagsCmd([dll_source], output_dir, - shared.exec_dir, 'TestDll', - ['/Fe' + str(dll_output)], - [], ['/DLL']) + outputDir, outputBase = test.getTempPaths() + dllOutput = os.path.join(outputDir, 'TestDll.DLL') - shared.dll_file = dll_output + cmd = [test.cxx, dllSource, *test.flags, *test.compileFlags, '/Fe' + dllOutput, + '/link', '/DLL', *test.linkFlags] - yield TestStep(dll_compile_cmd, shared.exec_dir, [dll_source], - test.cxx.compile_env) + yield TestStep(cmd, shared.execDir, shared.env, False) - exe_compile_cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source], output_dir, - shared.exec_dir, output_base, - [], [], []) - - yield TestStep(exe_compile_cmd, shared.exec_dir, [exe_source], - test.cxx.compile_env) - - def getTestSteps(self, test, lit_config, shared): - if shared.exec_file is not None: - yield TestStep([str(shared.exec_file)], shared.exec_dir, - [shared.exec_file, shared.dll_file], - test.cxx.compile_env) + for step in super().getBuildSteps(test, litConfig, shared): + yield step diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg b/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg index 5a7c740f0..a0ea47697 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg +++ b/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import Dev09_056375_locale_cleanup.custom_format -config.test_format = \ - Dev09_056375_locale_cleanup.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = Dev09_056375_locale_cleanup.custom_format.CustomTestFormat() diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py index 323790ec7..fa2efc437 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py @@ -1,23 +1,24 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - exe_source = Path(test.getSourcePath()) - test2_source = exe_source.parent / 'test2.cpp' - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + test2Source = os.path.join(os.path.dirname(exeSource), 'test2.cpp') - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source, test2_source], - output_dir, shared.exec_dir, - output_base, [], [], []) + outputDir, outputBase = test.getTempPaths() - yield TestStep(cmd, shared.exec_dir, [exe_source, test2_source], - test.cxx.compile_env) + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', exeSource, test2Source, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, test2Source, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, + '/link', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg b/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg index 4c325b481..9d2d29f5b 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import Dev09_172666_tr1_tuple_odr.custom_format -config.test_format = \ - Dev09_172666_tr1_tuple_odr.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = Dev09_172666_tr1_tuple_odr.custom_format.CustomTestFormat() diff --git a/tests/std/tests/Dev10_609053_ctype_char_table_size/test.cpp b/tests/std/tests/Dev10_609053_ctype_char_table_size/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev10_609053_ctype_char_table_size/test.cpp rename to tests/std/tests/Dev10_609053_ctype_char_table_size/test.compile.pass.cpp diff --git a/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.cpp b/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.cpp rename to tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0000000_include_each_header_alone/test.cpp b/tests/std/tests/Dev11_0000000_include_each_header_alone/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0000000_include_each_header_alone/test.cpp rename to tests/std/tests/Dev11_0000000_include_each_header_alone/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0272959_make_signed/test.cpp b/tests/std/tests/Dev11_0272959_make_signed/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0272959_make_signed/test.cpp rename to tests/std/tests/Dev11_0272959_make_signed/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0437519_container_requirements/test.cpp b/tests/std/tests/Dev11_0437519_container_requirements/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0437519_container_requirements/test.cpp rename to tests/std/tests/Dev11_0437519_container_requirements/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0453373_codecvt_compiles/test.cpp b/tests/std/tests/Dev11_0453373_codecvt_compiles/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0453373_codecvt_compiles/test.cpp rename to tests/std/tests/Dev11_0453373_codecvt_compiles/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.cpp b/tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.cpp rename to tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0704582_ratio/test.cpp b/tests/std/tests/Dev11_0704582_ratio/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0704582_ratio/test.cpp rename to tests/std/tests/Dev11_0704582_ratio/test.compile.pass.cpp diff --git a/tests/std/tests/GH_000545_include_compare/custom_format.py b/tests/std/tests/GH_000545_include_compare/custom_format.py index 05c32016f..2d698f717 100644 --- a/tests/std/tests/GH_000545_include_compare/custom_format.py +++ b/tests/std/tests/GH_000545_include_compare/custom_format.py @@ -1,28 +1,27 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - exe_source_dir = Path(test.getSourcePath()).parent + def getBuildSteps(self, test, litConfig, shared): + exeSourceDir = os.path.dirname(test.getSourcePath()) + _, outputBase = test.getTempPaths() - source_files = [] - for filename in os.listdir(exe_source_dir): + sourceFiles = [] + for filename in os.listdir(exeSourceDir): if filename.endswith('.cpp'): - source_files.append(exe_source_dir / filename) + sourceFiles.append(os.path.join(exeSourceDir, filename)) - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd(source_files, output_dir, - shared.exec_dir, output_base, - [], [], []) + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', *sourceFiles, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, *sourceFiles, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, + '/link', *test.linkFlags] - yield TestStep(cmd, shared.exec_dir, source_files, - test.cxx.compile_env) + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/GH_000545_include_compare/lit.local.cfg b/tests/std/tests/GH_000545_include_compare/lit.local.cfg index cbdcadad3..79640e4ec 100644 --- a/tests/std/tests/GH_000545_include_compare/lit.local.cfg +++ b/tests/std/tests/GH_000545_include_compare/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import GH_000545_include_compare.custom_format -config.test_format = \ - GH_000545_include_compare.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = GH_000545_include_compare.custom_format.CustomTestFormat() diff --git a/tests/std/tests/GH_000890_pow_template/test.cpp b/tests/std/tests/GH_000890_pow_template/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/GH_000890_pow_template/test.cpp rename to tests/std/tests/GH_000890_pow_template/test.compile.pass.cpp diff --git a/tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.cpp b/tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.cpp rename to tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.compile.pass.cpp diff --git a/tests/std/tests/P0607R0_inline_variables/custom_format.py b/tests/std/tests/P0607R0_inline_variables/custom_format.py index 323790ec7..fa2efc437 100644 --- a/tests/std/tests/P0607R0_inline_variables/custom_format.py +++ b/tests/std/tests/P0607R0_inline_variables/custom_format.py @@ -1,23 +1,24 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - exe_source = Path(test.getSourcePath()) - test2_source = exe_source.parent / 'test2.cpp' - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + test2Source = os.path.join(os.path.dirname(exeSource), 'test2.cpp') - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source, test2_source], - output_dir, shared.exec_dir, - output_base, [], [], []) + outputDir, outputBase = test.getTempPaths() - yield TestStep(cmd, shared.exec_dir, [exe_source, test2_source], - test.cxx.compile_env) + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', exeSource, test2Source, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, test2Source, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, + '/link', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/P0607R0_inline_variables/lit.local.cfg b/tests/std/tests/P0607R0_inline_variables/lit.local.cfg index 55628eacd..b84c4f43d 100644 --- a/tests/std/tests/P0607R0_inline_variables/lit.local.cfg +++ b/tests/std/tests/P0607R0_inline_variables/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import P0607R0_inline_variables.custom_format -config.test_format = \ - P0607R0_inline_variables.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = P0607R0_inline_variables.custom_format.CustomTestFormat() diff --git a/tests/std/tests/P0758R1_is_nothrow_convertible/test.cpp b/tests/std/tests/P0758R1_is_nothrow_convertible/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0758R1_is_nothrow_convertible/test.cpp rename to tests/std/tests/P0758R1_is_nothrow_convertible/test.compile.pass.cpp diff --git a/tests/std/tests/P0896R4_ranges_algorithm_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_algorithm_machinery/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0896R4_ranges_algorithm_machinery/test.cpp rename to tests/std/tests/P0896R4_ranges_algorithm_machinery/test.compile.pass.cpp diff --git a/tests/std/tests/P0896R4_ranges_subrange/test.cpp b/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0896R4_ranges_subrange/test.cpp rename to tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp diff --git a/tests/std/tests/P0896R4_ranges_test_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0896R4_ranges_test_machinery/test.cpp rename to tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp diff --git a/tests/std/tests/P1423R3_char8_t_remediation/test.cpp b/tests/std/tests/P1423R3_char8_t_remediation/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P1423R3_char8_t_remediation/test.cpp rename to tests/std/tests/P1423R3_char8_t_remediation/test.compile.pass.cpp diff --git a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py index 4338a1186..3c7acccbe 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py +++ b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py @@ -1,19 +1,16 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import itertools +import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - source_path = Path(test.getSourcePath()) - - stl_headers = [ + def getBuildSteps(self, test, litConfig, shared): + stlHeaders = [ 'algorithm', 'any', 'array', @@ -93,34 +90,36 @@ class CustomTestFormat(STLTestFormat): 'version', ] - compile_test_cpp_with_edg = test.cxx.flags.count('/BE') == 1 + outputDir, outputBase = test.getTempPaths() + sourcePath = test.getSourcePath() - if compile_test_cpp_with_edg: - test.cxx.flags.remove('/BE') + compileTestCppWithEdg = '/BE' in itertools.chain(test.flags, test.compileFlags) + if compileTestCppWithEdg: + test.flags.remove('/BE') + test.compileFlags.remove('/BE') - header_unit_options = [] + headerUnitOptions = [] + for header in stlHeaders: + headerObjPath = os.path.join(outputDir, header + '.obj') - for header in stl_headers: - header_obj_path = output_dir / (header + '.obj') + headerUnitOptions.append('/headerUnit') + headerUnitOptions.append('{0}/{1}={1}.ifc'.format(litConfig.cxx_headers, header)) - header_unit_options.append('/headerUnit') - header_unit_options.append('{0}/{1}={1}.ifc'.format(test.config.cxx_headers, header)) + if not compileTestCppWithEdg: + headerUnitOptions.append(headerObjPath) - if not compile_test_cpp_with_edg: - header_unit_options.append(str(header_obj_path)) + cmd = [test.cxx, *test.flags, *test.compileFlags, + '/exportHeader', '<{}>'.format(header), '/Fo{}'.format(headerObjPath)] + yield TestStep(cmd, shared.execDir, shared.env, False) - cmd, out_files = test.cxx._basicCmd(source_files = [], out = None, - flags = ['/exportHeader', '<{}>'.format(header), '/Fo{}'.format(str(header_obj_path))], - skip_mode_flags = True) - yield TestStep(cmd, shared.exec_dir, [], test.cxx.compile_env) + if compileTestCppWithEdg: + test.compileFlags.append('/BE') - if compile_test_cpp_with_edg: - test.cxx.flags.append('/BE') + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', sourcePath, *test.flags, *test.compileFlags, *headerUnitOptions] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, sourcePath, *test.flags, *test.compileFlags, *headerUnitOptions, '/Fe' + shared.execFile, + '/link', *test.linkFlags] - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([source_path], - output_dir, shared.exec_dir, - output_base, header_unit_options, [], []) - - yield TestStep(cmd, shared.exec_dir, [source_path], - test.cxx.compile_env) + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg b/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg index 504df778c..a58f404ef 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg +++ b/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import P1502R1_standard_library_header_units.custom_format -config.test_format = \ - P1502R1_standard_library_header_units.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = P1502R1_standard_library_header_units.custom_format.CustomTestFormat() diff --git a/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py b/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py index 07b7dff9c..0f08a5e01 100644 --- a/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py +++ b/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py @@ -1,52 +1,44 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import itertools +import os from stl.test.format import STLTestFormat, TestStep -from stl.test.tests import STLTest +from stl.test.tests import STLTest, TestType class CustomTest(STLTest): - def __init__(self, suite, path_in_suite, lit_config, test_config, - envlst_entry, env_num, default_cxx, file_path=None): - STLTest.__init__(self, suite, path_in_suite, lit_config, test_config, - envlst_entry, env_num, default_cxx, file_path) - self.calling_convention_a = \ - envlst_entry.getEnvVal('CALLING_CONVENTION_A') - self.calling_convention_b = \ - envlst_entry.getEnvVal('CALLING_CONVENTION_B') + def __init__(self, suite, pathInSuite, litConfig, testConfig, envlstEntry, envNum): + STLTest.__init__(self, suite, pathInSuite, litConfig, testConfig, envlstEntry, envNum) + self.callingConventionA = envlstEntry.getEnvVal('CALLING_CONVENTION_A') + self.callingConventionB = envlstEntry.getEnvVal('CALLING_CONVENTION_B') class CustomTestFormat(STLTestFormat): - def getTestsInDirectory(self, testSuite, path_in_suite, - litConfig, localConfig, test_class=CustomTest): - return super().getTestsInDirectory(testSuite, path_in_suite, litConfig, - localConfig, test_class) + def getTestsInDirectory(self, testSuite, pathInSuite, litConfig, localConfig, testClass=CustomTest): + return super().getTestsInDirectory(testSuite, pathInSuite, litConfig, localConfig, testClass) - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - exe_source = Path(test.getSourcePath()) - a_source = exe_source.parent / 'a.cpp' - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + aSource = os.path.join(os.path.dirname(exeSource), 'a.cpp') - a_compile_cmd, out_files, exec_file = \ - test.cxx.executeBasedOnFlagsCmd([a_source], output_dir, - shared.exec_dir, 'a', - [test.calling_convention_a, '/c'], - [], []) + outputDir, outputBase = test.getTempPaths() + aObj = os.path.join(outputDir, 'a.obj') - yield TestStep(a_compile_cmd, shared.exec_dir, [a_source], - test.cxx.compile_env) + cmd = [test.cxx, aSource, test.callingConventionA, *test.flags, '/c', *test.compileFlags, '/Fo' + aObj] - a_output = output_dir / 'a.obj' + yield TestStep(cmd, shared.execDir, shared.env, False) - exe_compile_cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source], output_dir, - shared.exec_dir, output_base, - [test.calling_convention_b, - str(a_output)], [], []) + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, aObj, test.callingConventionB, *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags] - yield TestStep(exe_compile_cmd, shared.exec_dir, - [a_output, exe_source], test.cxx.compile_env) + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', exeSource, aObj, test.callingConventionB, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, aObj, test.callingConventionB, *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg b/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg index 9f4ac1b16..3086b12de 100644 --- a/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg +++ b/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg @@ -1,12 +1,11 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -config.suffixes = {'b.cpp'} +config.suffixes = ['b[.]cpp$'] +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import VSO_0000000_any_calling_conventions.custom_format -config.test_format = \ - VSO_0000000_any_calling_conventions.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = VSO_0000000_any_calling_conventions.custom_format.CustomTestFormat() diff --git a/tests/std/tests/VSO_0000000_fancy_pointers/test.cpp b/tests/std/tests/VSO_0000000_fancy_pointers/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_fancy_pointers/test.cpp rename to tests/std/tests/VSO_0000000_fancy_pointers/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_containers/test.cpp b/tests/std/tests/VSO_0000000_instantiate_containers/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_containers/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_containers/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_cvt/test.cpp b/tests/std/tests/VSO_0000000_instantiate_cvt/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_cvt/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_cvt/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.cpp b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_type_traits/test.cpp b/tests/std/tests/VSO_0000000_instantiate_type_traits/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_type_traits/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_type_traits/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py index 323790ec7..fa2efc437 100644 --- a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py +++ b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py @@ -1,23 +1,24 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - shared.exec_dir = test.getExecDir() - exe_source = Path(test.getSourcePath()) - test2_source = exe_source.parent / 'test2.cpp' - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + test2Source = os.path.join(os.path.dirname(exeSource), 'test2.cpp') - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source, test2_source], - output_dir, shared.exec_dir, - output_base, [], [], []) + outputDir, outputBase = test.getTempPaths() - yield TestStep(cmd, shared.exec_dir, [exe_source, test2_source], - test.cxx.compile_env) + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', exeSource, test2Source, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, test2Source, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, + '/link', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg b/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg index 994f1aefb..970edc709 100644 --- a/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg +++ b/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import VSO_0000000_matching_npos_address.custom_format -config.test_format = \ - VSO_0000000_matching_npos_address.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = VSO_0000000_matching_npos_address.custom_format.CustomTestFormat() diff --git a/tests/std/tests/VSO_0000000_strengthened_noexcept/test.cpp b/tests/std/tests/VSO_0000000_strengthened_noexcept/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_strengthened_noexcept/test.cpp rename to tests/std/tests/VSO_0000000_strengthened_noexcept/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0157762_feature_test_macros/test.cpp rename to tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp b/tests/std/tests/VSO_0180469_ptr_cat/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0180469_ptr_cat/test.cpp rename to tests/std/tests/VSO_0180469_ptr_cat/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0191296_allocator_construct/test.cpp b/tests/std/tests/VSO_0191296_allocator_construct/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0191296_allocator_construct/test.cpp rename to tests/std/tests/VSO_0191296_allocator_construct/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0493909_is_aggregate/test.cpp b/tests/std/tests/VSO_0493909_is_aggregate/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0493909_is_aggregate/test.cpp rename to tests/std/tests/VSO_0493909_is_aggregate/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0527559_pragma_managed/test.cpp b/tests/std/tests/VSO_0527559_pragma_managed/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0527559_pragma_managed/test.cpp rename to tests/std/tests/VSO_0527559_pragma_managed/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0938757_attribute_order/test.cpp b/tests/std/tests/VSO_0938757_attribute_order/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0938757_attribute_order/test.cpp rename to tests/std/tests/VSO_0938757_attribute_order/test.compile.pass.cpp diff --git a/tests/std/tests/fast_matrix.lst b/tests/std/tests/fast_matrix.lst index a66449fd0..ea19bd9ea 100644 --- a/tests/std/tests/fast_matrix.lst +++ b/tests/std/tests/fast_matrix.lst @@ -4,4 +4,4 @@ # This is for tests that take a long time to execute, so run only one configuration. RUNALL_INCLUDE .\prefix.lst RUNALL_CROSSLIST -PM_CL="/EHsc /MT /O2 /GL /std:c++latest /permissive- /analyze /w14640 /Zc:threadSafeInit-" +PM_CL="/EHsc /MT /O2 /GL /std:c++latest /permissive- /analyze:autolog- /w14640 /Zc:threadSafeInit-" diff --git a/tests/std/tests/rtti_matrix.lst b/tests/std/tests/rtti_matrix.lst index 8ec139c03..568ccf52a 100644 --- a/tests/std/tests/rtti_matrix.lst +++ b/tests/std/tests/rtti_matrix.lst @@ -3,7 +3,7 @@ RUNALL_INCLUDE .\prefix.lst RUNALL_CROSSLIST -PM_CL="/EHsc /MTd /std:c++latest /permissive- /analyze /w14640 /Zc:threadSafeInit-" +PM_CL="/EHsc /MTd /std:c++latest /permissive- /analyze:autolog- /w14640 /Zc:threadSafeInit-" RUNALL_CROSSLIST PM_CL="/GR" PM_CL="/GR-" diff --git a/tests/tr1/env_single.lst b/tests/tr1/env_single.lst index 1710a2a95..7234b0396 100644 --- a/tests/tr1/env_single.lst +++ b/tests/tr1/env_single.lst @@ -3,4 +3,4 @@ RUNALL_INCLUDE .\prefix.lst RUNALL_CROSSLIST -PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze /w14640 /Zc:threadSafeInit-" +PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze:autolog- /w14640 /Zc:threadSafeInit-" diff --git a/tests/tr1/lit.cfg b/tests/tr1/lit.cfg index 0b68aa927..e97953f5b 100644 --- a/tests/tr1/lit.cfg +++ b/tests/tr1/lit.cfg @@ -1,29 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path -import importlib -import site - -site.addsitedir(str(Path(__file__).parents[1] / "utils")) -site.addsitedir(str(Path(__file__).parent / "tests")) - -config.name = 'tr1' -config.suffixes.add('test.cpp') - -if config.test_source_root is None: - config.test_source_root = str(Path(__file__).parent) - -config.test_exec_root = getattr(config, 'test_exec_root', None) - -if not config.test_exec_root: - import tempfile - config.test_exec_root = tempfile.mkdtemp(prefix=config.name + '-testsuite-') - lit_config.note('Creating temporary directory for tests: %s' % config.test_exec_root) - -config_module_name = getattr(config, 'config_module_name', 'stl.test.config') -config_module = importlib.import_module(config_module_name) - -configuration = config_module.Configuration(lit_config, config) -configuration.configure() -config.test_format = configuration.get_test_format() +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/tr1/lit.site.cfg.in b/tests/tr1/lit.site.cfg.in index 49c489910..979944d0d 100644 --- a/tests/tr1/lit.site.cfg.in +++ b/tests/tr1/lit.site.cfg.in @@ -1,18 +1,41 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -config.cxx_archive_root = "@CMAKE_ARCHIVE_OUTPUT_DIRECTORY@" -config.cxx_headers = "@STL_TESTED_HEADERS_DIR@" -config.cxx_library_root = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" -config.cxx_runtime_root = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" -config.expected_results_list_path = "@TR1_EXPECTED_RESULTS@" -config.include_dirs = ["@STL_SOURCE_DIR@/tests/tr1/include", "@STL_SOURCE_DIR@/tests/std/include"] -config.msvc_toolset_libs_root = "@TOOLSET_LIB@" -config.stl_build_root = "@STL_BUILD_ROOT@" -config.stl_src_root = "@STL_SOURCE_DIR@" -config.target_arch = "@VCLIBS_TARGET_ARCHITECTURE@" -config.test_exec_root = "@TR1_TEST_OUTPUT_DIR@" -config.test_subdirs_file = "@TR1_TEST_SUBDIRS_FILE@" -config.test_subdirs_root = "@TR1_TEST_SUBDIRS_ROOT@" +import os +import site +site.addsitedir("@STL_TEST_UTILS_DIR@") +site.addsitedir(os.path.join("@LIBCXX_SOURCE_DIR@", "utils")) +import stl.test.config +import stl.test.features +import stl.test.file_parsing +import stl.test.format +import stl.test.params -lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") +config.name = 'tr1' +config.suffixes = ['test[.]cpp$'] +config.test_exec_root = "@TR1_TEST_OUTPUT_DIR@" +config.test_format = stl.test.format.STLTestFormat() + +lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) +lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) +lit_config.library_dirs = getattr(lit_config, 'library_dirs', dict()) +lit_config.test_subdirs = getattr(lit_config, 'test_subdirs', dict()) + +lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@TR1_EXPECTED_RESULTS@') +lit_config.include_dirs[config.name] = \ + ['@STL_TESTED_HEADERS_DIR@', '@STL_SOURCE_DIR@/tests/tr1/include', '@STL_SOURCE_DIR@/tests/std/include'] +lit_config.library_dirs[config.name] = ['@CMAKE_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.test_subdirs[config.name] = \ + [os.path.normpath(os.path.join('@TR1_TEST_SUBDIRS_ROOT@', path)) for \ + path in stl.test.file_parsing.parse_commented_file('@TR1_TEST_SUBDIRS_FILE@')] + +lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/utils/stl/compiler.py b/tests/utils/stl/compiler.py deleted file mode 100644 index ff5d4ef3b..000000000 --- a/tests/utils/stl/compiler.py +++ /dev/null @@ -1,211 +0,0 @@ -#===----------------------------------------------------------------------===## -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===## - -from itertools import chain -from pathlib import Path -from typing import List -import os - -import stl.util - - -class CXXCompiler: - CM_Default = 0 - CM_PreProcess = 1 - CM_Compile = 2 - CM_Link = 3 - CM_Analyze = 4 - - def __init__(self, path, flags=None, compile_flags=None, - link_flags=None, compile_env=None, edg_drop=None): - self.path = path - if path is not None: - self.name = os.path.basename(path).split('.')[0] - else: - self.name = None - - self.compile_flags = compile_flags or [] - self.flags = flags or [] - self.link_flags = link_flags or [] - - self.compile_env = compile_env - self.edg_drop = edg_drop - - def _basicCmd(self, source_files: List[Path], out: Path, - mode=CM_Default, flags=[], compile_flags=[], link_flags=[], - skip_mode_flags=False): - out_files = [] - cmd = [] - - if out is not None: - out_files.append(out) - - cmd.append(self.path) - - if mode == self.CM_PreProcess: - if out is not None: - cmd.extend(('/P', '/Fi' + str(out))) - else: - cmd.append('/EP') - elif mode == self.CM_Compile: - if not skip_mode_flags: - cmd.append('/c') - if out is not None and len(source_files) <= 1: - cmd.append('/Fo' + str(out)) - else: - for source_file in source_files: - out_files.append( - Path(source_file.name.rsplit('.', 1)[0] + '.obj')) - elif mode == self.CM_Analyze: - if not skip_mode_flags: - cmd.append('/analyze:only') - if out is not None: - cmd.append('/analyze:log' + str(out)) - else: - for source_file in source_files: - out_files.append( - Path(source_file.name.rsplit('.', 1)[0] + - '.nativecodeanalysis.xml')) - elif out is not None: - cmd.append('/Fe' + str(out)) - - if len(source_files) <= 1: - out_obj = str(out).rsplit('.', 1)[0] + '.obj' - cmd.append('/Fo' + out_obj) - out_files.append(Path(out_obj)) - else: - for source_file in source_files: - out_files.append( - Path(source_file.name.rsplit('.', 1)[0] + '.obj')) - - if mode in (self.CM_Analyze, self.CM_Compile, self.CM_Default): - cmd.extend(self.compile_flags) - cmd.extend(compile_flags) - - cmd.extend(self.flags) - cmd.extend(flags) - cmd.extend([str(file) for file in source_files]) - - if mode in (self.CM_Default, self.CM_Link): - cmd.append('/link') - cmd.extend(self.link_flags) - cmd.extend(link_flags) - - return cmd, out_files - - def executeBasedOnFlagsCmd(self, source_files, out_dir, cwd=None, - out_base=None, flags=[], compile_flags=[], - link_flags=[]): - mode = self.CM_Default - exec_file = None - output_file = None - - if out_base is None: - out_base = source_files[0].name.rsplit('.', 1)[0] - - add_analyze_output = False - for flag in chain(flags, self.flags): - flag = flag[1:] - - if flag == 'c': - mode = self.CM_Compile - exec_file = None - output_file = out_dir / (out_base + '.obj') - elif flag.startswith('Fe'): - output_file = Path(flag[2:]) - exec_file = output_file - elif flag == 'analyze:only': - mode = self.CM_Analyze - output_file = out_dir / (out_base + '.nativecodeanalysis.xml') - exec_file = None - elif flag.startswith('analyze') and flag[-1] != '-': - add_analyze_output = True - - if mode is self.CM_Default and output_file is None: - output_file = out_dir / (out_base + '.exe') - exec_file = output_file - - if add_analyze_output and mode != self.CM_Analyze: - flags.append('/analyze:log' + - str(out_dir / (out_base + '.nativecodeanalysis.xml'))) - - cmd, out_files = self._basicCmd(source_files, output_file, mode, flags, - compile_flags, link_flags, True) - return cmd, out_files, exec_file - - def executeBasedOnFlags(self, source_files, out_dir, cwd=None, - out_base=None, flags=[], compile_flags=[], - link_flags=[]): - cmd, out_files, exec_file = \ - self.executeBasedOnFlagsCmd(source_files, out_dir, cwd, out_base, - flags, compile_flags, link_flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc, out_files, exec_file - - def preprocessCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[], mode=self.CM_PreProcess) - - def compileCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[], mode=self.CM_Compile) - - def linkCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[], mode=self.CM_Link) - - def compileLinkCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[]) - - def preprocess(self, source_files, out=None, flags=[], cwd=None): - cmd, _ = self.preprocessCmd(source_files, out, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def compile(self, source_files, out=None, flags=[], cwd=None): - cmd, _ = self.compileCmd(source_files, out, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def link(self, source_files, exec_path=None, flags=[], cwd=None): - cmd, _ = self.linkCmd(source_files, exec_path, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def compileLink(self, source_files, exec_path=None, flags=[], - cwd=None): - cmd, _ = self.compileLinkCmd(source_files, exec_path, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def compileLinkTwoSteps(self, source_file, out=None, object_file=None, - flags=[], cwd=None): - if not isinstance(source_file, str): - raise TypeError('This function only accepts a single input file') - if object_file is None: - # Create, use, and delete a temporary object file if none is given. - def with_fn(): return stl.util.guardedTempFilename(suffix='.obj') - else: - # Otherwise wrap the filename in a context manager function. - def with_fn(): return stl.util.nullContext(object_file) - with with_fn() as object_file: - cc_cmd, cc_stdout, cc_stderr, rc = self.compile( - source_file, object_file, flags=flags, cwd=cwd) - if rc != 0: - return cc_cmd, cc_stdout, cc_stderr, rc - - link_cmd, link_stdout, link_stderr, rc = self.link( - object_file, exec_path=out, flags=flags, cwd=cwd) - return (cc_cmd + ['&'] + link_cmd, cc_stdout + link_stdout, - cc_stderr + link_stderr, rc) diff --git a/tests/utils/stl/test/config.py b/tests/utils/stl/test/config.py index e8f1fd773..a02e8038c 100644 --- a/tests/utils/stl/test/config.py +++ b/tests/utils/stl/test/config.py @@ -6,380 +6,42 @@ # #===----------------------------------------------------------------------===## -from pathlib import Path import os -import platform -import shlex -from stl.test.executor import LocalExecutor -from stl.compiler import CXXCompiler -import stl.util -import stl.test.file_parsing -import stl.test.target_info - - -# Extract the value of a numeric macro such as __cplusplus or a feature-test -# macro. -def intMacroValue(token): - return int(token.rstrip('LlUu')) - - -class Configuration: - # pylint: disable=redefined-outer-name - def __init__(self, lit_config, config): - self.build_executor = None - self.config = config - self.cxx_headers = None - self.cxx_library_root = None - self.cxx_runtime_root = None - self.default_compiler = None - self.execute_external = False - self.expected_results_list_path = None - self.expected_results_list_root = None - self.format_name = None - self.lit_config = lit_config - self.link_shared = True - self.long_tests = None - self.msvc_toolset_libs_root = None - self.stl_build_root = None - self.stl_path_env_var = None - self.stl_src_root = None - self.stl_test_env = None - self.target_arch = None - self.target_info = stl.test.target_info.WindowsLocalTI(lit_config) - self.test_executor = None - self.test_source_root = None - - def get_lit_conf(self, name, default=None): - val = self.lit_config.params.get(name, None) - if val is None: - val = getattr(self.config, name, None) - if val is None: - val = default - return val - - def get_lit_bool(self, name, default=None, env_var=None): - def check_value(value, var_name): - if value is None: - return default - if isinstance(value, bool): - return value - if not isinstance(value, str): - raise TypeError('expected bool or string') - if value.lower() in ('1', 'true'): - return True - if value.lower() in ('', '0', 'false'): - return False - self.lit_config.fatal( - "parameter '{}' should be true or false".format(var_name)) - - conf_val = self.get_lit_conf(name) - if env_var is not None and env_var in os.environ and \ - os.environ[env_var] is not None: - val = os.environ[env_var] - if conf_val is not None: - self.lit_config.warning( - 'Environment variable %s=%s is overriding explicit ' - '--param=%s=%s' % (env_var, val, name, conf_val)) - return check_value(val, env_var) - return check_value(conf_val, name) - - def configure(self): - self.configure_features() - self.configure_default_compiler() - self.configure_executors() - self.configure_expected_results() - self.configure_test_dirs() - self.configure_test_format() - - def configure_test_format(self): - format_name = self.get_lit_conf('format_name', None) - - if format_name is None: - format_name = 'STLTestFormat' - - self.format_name = format_name - - def configure_test_dirs(self): - test_subdirs = list() - - test_subdirs_file = self.get_lit_conf('test_subdirs_file', None) - - if test_subdirs_file is not None: - test_subdirs_file = Path(test_subdirs_file) - test_subdirs += \ - stl.test.file_parsing.parse_commented_file(test_subdirs_file) - - test_subdirs += self.get_lit_conf('test_subdirs', []) - - test_subdirs_root = Path(self.get_lit_conf('test_subdirs_root', '')) - self.lit_config.test_subdirs = \ - list(map(lambda x: str((test_subdirs_root / x).resolve()), - test_subdirs)) - - # TRANSITION: Don't hard-code features. - def configure_features(self): - self.config.available_features.add('long_tests') - self.config.available_features.add('c++2a') - self.config.available_features.add('msvc') - self.config.available_features.update(self.target_info.features) - - if self.target_arch is None: - self.configure_target_architecture() - - if self.target_arch == 'x86': - self.config.available_features.add('edg') - - def configure_test_source_root(self): - test_source_root = self.get_lit_conf('test_source_root', None) - - if test_source_root is not None: - self.test_source_root = Path(test_source_root) - - def configure_src_root(self): - stl_src_root = self.get_lit_conf('stl_src_root', None) - - if stl_src_root is None: - if self.test_source_root is None: - self.configure_test_source_root() - - if self.test_source_root is None: - self.lit_config.fatal( - "Could not infer stl_src_root from test_source_root. " - "test_source_root is None") - - if self.config.name == 'libc++': - stl_src_root = self.test_source_root.parents[2] - else: - stl_src_root = self.test_source_root.parents[1] - - self.lit_config.note( - "stl_src_root was not specified. Defaulting to: %s." % - str(stl_src_root)) - - self.stl_src_root = Path(stl_src_root) - - def configure_target_architecture(self): - target_arch = self.get_lit_conf('target_arch', None) - - if target_arch is None: - target_arch = platform.machine() - - self.lit_config.note( - "target_arch was not specified. Defaulting to %s." % - target_arch) - - self.target_arch = target_arch - self.config.target_arch = target_arch - - def configure_build_root(self): - stl_build_root = self.get_lit_conf('stl_build_root', None) - - if stl_build_root is None: - if self.stl_src_root is None: - self.configure_src_root() - - if self.target_arch is None: - self.configure_target_architecture() - - stl_build_root = self.stl_src_root / 'out' / 'build' - - if self.target_arch.casefold() == 'AMD64'.casefold(): - stl_build_root = stl_build_root / 'x64' / 'out' - elif self.target_arch.casefold() == 'X86'.casefold(): - stl_build_root = stl_build_root / 'i386' / 'out' - else: - stl_build_root = \ - stl_build_root / self.target_arch.upper() / 'out' - - self.lit_config.note( - "stl_build_root was not specified. Defaulting to: %s." % - str(stl_build_root)) - - self.stl_build_root = Path(stl_build_root) - - def configure_library_roots(self): - cxx_runtime_root = self.get_lit_conf('cxx_runtime_root', None) - cxx_library_root = self.get_lit_conf('cxx_library_root', None) - - if cxx_runtime_root is None or cxx_library_root is None: - if self.stl_build_root is None: - self.configure_build_root() - - if self.target_arch is None: - self.configure_target_architecture() - - subfolder_name = None - if self.target_arch.casefold() == 'AMD64'.casefold(): - subfolder_name = 'amd64' - elif self.target_arch.casefold() == 'X86'.casefold(): - subfolder_name = 'i386' - else: - subfolder_name = self.target_arch.lower() - - if cxx_runtime_root is None: - cxx_runtime_root = self.stl_build_root / 'bin' / subfolder_name - - self.lit_config.note( - "cxx_runtime_root was not specified. Defaulting to: %s." % - str(cxx_runtime_root)) - - if cxx_library_root is None: - cxx_library_root = \ - self.stl_build_root / 'lib' / subfolder_name - - self.lit_config.note( - "cxx_library_root was not specified. Defaulting to: %s." - % str(cxx_library_root)) - - self.cxx_runtime_root = Path(cxx_runtime_root) - self.cxx_library_root = Path(cxx_library_root) - - def configure_path_env_var(self): - stl_path_env_var = self.get_lit_conf('stl_path_env_var', None) - - if stl_path_env_var is None: - path_list = list() - - msvc_bin_dir = self.get_lit_conf('msvc_bin_dir', None) - if msvc_bin_dir is not None: - path_list.append(msvc_bin_dir) - - if self.cxx_runtime_root is None: - self.configure_library_roots() - path_list.append(str(self.cxx_runtime_root)) - - config_env = self.config.environment.get('PATH', None) - if config_env is not None: - path_list.append(config_env) - - stl_path_env_var = ';'.join(path_list) - - self.stl_path_env_var = stl_path_env_var - - def configure_test_env(self): - if self.stl_path_env_var is None: - self.configure_path_env_var() - - stl_test_env = {} - stl_test_env['PATH'] = self.stl_path_env_var - - self.config.environment = stl_test_env - - def configure_expected_results_list_location(self): - expected_results_list_path = self.get_lit_conf( - 'expected_results_list_path', None) - - if expected_results_list_path is not None: - self.expected_results_list_path = Path( - expected_results_list_path) - else: - self.expected_results_list_path = Path(os.devnull) - - def configure_expected_results(self): - expected_results = getattr(self.lit_config, 'expected_results', dict()) - - if self.expected_results_list_path is None: - self.configure_expected_results_list_location() - - expected_results[self.config.name] = \ - stl.test.file_parsing.parse_result_file( - self.expected_results_list_path) - - self.lit_config.expected_results = expected_results - self.config.expected_results = \ - getattr(self.config, 'expected_results', dict()) - - def configure_default_compiler(self): - self.default_compiler = CXXCompiler(None) - self.configure_compile_flags() - self.configure_link_flags() - self.configure_test_env() - - self.default_compiler.compile_env = self.config.environment - - env_var = 'STL_EDG_DROP' - if env_var in os.environ and os.environ[env_var] is not None: - self.default_compiler.edg_drop = os.environ[env_var] - - # TRANSITION: Investigate using SSHExecutor for ARM - def configure_executors(self): - self.build_executor = LocalExecutor() - self.test_executor = LocalExecutor() - - def configure_compile_flags(self): - self.configure_compile_flags_header_includes() - # Configure extra flags - self.default_compiler.compile_flags += \ - self.get_lit_conf('compile_flags', []) - additional_flags_str = self.get_lit_conf('additional_compiler_flags') - if additional_flags_str: - self.default_compiler.compile_flags += \ - shlex.split(additional_flags_str) - - def configure_compile_flags_header_includes(self): - if self.cxx_headers is None: - self.configure_cxx_headers() - - self.default_compiler.compile_flags += ['/I' + str(self.cxx_headers)] - - include_dirs = self.get_lit_conf('include_dirs', []) - - for directory in include_dirs: - self.default_compiler.compile_flags.append('/I' + directory) - - def configure_cxx_headers(self): - cxx_headers = self.get_lit_conf('cxx_headers') - - if cxx_headers is None: - if self.stl_build_root is None: - self.configure_build_root() - - cxx_headers = self.stl_build_root / 'inc' - - if not os.path.isdir(cxx_headers): - self.lit_config.fatal("cxx_headers='%s' is not a directory." - % str(cxx_headers)) - else: - cxx_headers = Path(cxx_headers) - - self.cxx_headers = cxx_headers - - def configure_link_flags(self): - if self.cxx_library_root is None: - self.configure_library_roots() - - if self.msvc_toolset_libs_root is None: - self.configure_msvc_toolset_libs_root() - - self.default_compiler.link_flags.append( - '/LIBPATH:' + str(self.cxx_library_root)) - - self.default_compiler.link_flags.append( - '/LIBPATH:' + str(self.msvc_toolset_libs_root)) - - additional_flags_str = self.get_lit_conf('additional_link_flags') - if additional_flags_str: - self.default_compiler.link_flags += \ - shlex.split(additional_flags_str) - - def configure_msvc_toolset_libs_root(self): - msvc_toolset_libs_root = self.get_lit_conf('msvc_toolset_libs_root') - - if msvc_toolset_libs_root is None: - self.lit_config.fatal('msvc_toolset_libs_root must be specified') - - self.msvc_toolset_libs_root = Path(msvc_toolset_libs_root) - - def get_test_format(self): - import stl.test.format - - return getattr(stl.test.format, self.format_name)( - self.default_compiler, - self.execute_external, - self.build_executor, - self.test_executor) - - # TRANSITION: Might be nice to actually print something - def print_config_info(self): - pass +def configure(parameters, features, config, lit_config): + # Apply parameters to the configuration first, since parameters are things + # that we request explicitly and which might influence what features are + # implicitly made available next. + for param in parameters: + feature = param.getFeature(config, lit_config.params) + if feature: + feature.enableIn(config) + lit_config.note( + "Enabling Lit feature '{}' as a result of parameter '{}'".format(feature.getName(config), param.name)) + + # Then, apply the automatically-detected features. + printFeatures = [] + for feature in features: + if feature.isSupported(config): + feature.enableIn(config) + printFeatures.append(feature.getName(config)) + printFeatures = ["'{}'".format(f) for f in sorted(printFeatures)] + lit_config.note("Enabling implicitly detected Lit features {}".format(', '.join(printFeatures))) + + # Normalize and validate all subdirectories to be tested + lit_config.test_subdirs[config.name] = [os.path.normpath(subdir) for subdir in lit_config.test_subdirs[config.name]] + for subdir in lit_config.test_subdirs[config.name]: + if not os.path.exists(subdir): + lit_config.fatal("The directory {} does not exist and was marked as a subdirectory to test".format(subdir)) + + lit_config.flags = getattr(lit_config, 'flags', dict()) + lit_config.compile_flags = getattr(lit_config, 'compile_flags', dict()) + lit_config.link_flags = getattr(lit_config, 'link_flags', dict()) + + lit_config.flags[config.name] = [] + lit_config.compile_flags[config.name] = \ + ['/I' + os.path.normpath(dir) for dir in lit_config.include_dirs[config.name]] + lit_config.link_flags[config.name] = \ + ['/LIBPATH:' + os.path.normpath(dir) for dir in lit_config.library_dirs[config.name]] + + lit_config.test_env = {'PATH' : os.path.normpath(lit_config.cxx_runtime)} diff --git a/tests/utils/stl/test/executor.py b/tests/utils/stl/test/executor.py deleted file mode 100644 index cee2b71bf..000000000 --- a/tests/utils/stl/test/executor.py +++ /dev/null @@ -1,235 +0,0 @@ -#===----------------------------------------------------------------------===## -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===## - -import platform -import os -import posixpath -import ntpath - -from stl.test import tracing -from stl.util import executeCommand - - -class Executor: - def __init__(self): - self.target_info = None - - def run(self, cmd, local_cwd, file_deps=None, env=None): - """Execute a command. - Be very careful not to change shared state in this function. - Executor objects are shared between python processes in `lit -jN`. - Args: - cmd: [str]: subprocess.call style command - local_cwd: str: Local path to the working directory - file_deps: [str]: Files required by the cmd - env: {str: str}: Environment variables to execute under - Returns: - cmd, out, err, exitCode - """ - raise NotImplementedError - - def merge_environments(self, current_env, updated_env): - """Merges two execution environments. - - If both environments contain the PATH variables, they are also merged - using the proper separator. - """ - result_env = dict(current_env) - for k, v in updated_env.items(): - if k == 'PATH' and self.target_info: - self.target_info.add_path(result_env, v) - else: - result_env[k] = v - return result_env - - -class LocalExecutor(Executor): - def __init__(self): - super(LocalExecutor, self).__init__() - self.is_windows = platform.system() == 'Windows' - - def run(self, cmd, work_dir='.', file_deps=None, env=None): - if str(work_dir) == '.': - work_dir = os.getcwd() - - if env: - env = self.merge_environments(os.environ, env) - - out, err, rc = executeCommand(cmd, cwd=work_dir, env=env) - return (cmd, out, err, rc) - - -class PrefixExecutor(Executor): - """Prefix an executor with some other command wrapper. - - Most useful for setting ulimits on commands, or running an emulator like - qemu and valgrind. - """ - def __init__(self, commandPrefix, chain): - super(PrefixExecutor, self).__init__() - - self.commandPrefix = commandPrefix - self.chain = chain - - def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): - cmd = cmd or [exe_path] - return self.chain.run(exe_path, self.commandPrefix + cmd, work_dir, - file_deps, env=env) - - -class PostfixExecutor(Executor): - """Postfix an executor with some args.""" - def __init__(self, commandPostfix, chain): - super(PostfixExecutor, self).__init__() - - self.commandPostfix = commandPostfix - self.chain = chain - - def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): - cmd = cmd or [exe_path] - return self.chain.run(cmd + self.commandPostfix, work_dir, file_deps, - env=env) - - -class RemoteExecutor(Executor): - def __init__(self): - super(RemoteExecutor, self).__init__() - self.local_run = executeCommand - - def remote_temp_dir(self): - return self._remote_temp(True) - - def remote_temp_file(self): - return self._remote_temp(False) - - def _remote_temp(self, is_dir): - raise NotImplementedError() - - def copy_in(self, local_srcs, remote_dsts): - # This could be wrapped up in a tar->scp->untar for performance - # if there are lots of files to be copied/moved - for src, dst in zip(local_srcs, remote_dsts): - self._copy_in_file(src, dst) - - def _copy_in_file(self, src, dst): - raise NotImplementedError() - - def delete_remote(self, remote): - try: - self._execute_command_remote(['rm', '-rf', remote]) - except OSError: - # TRANSITION: Log failure to delete? - pass - - def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): - target_exe_path = None - target_cwd = None - try: - target_cwd = self.remote_temp_dir() - executable_name = 'libcxx_test.exe' - if self.target_info.is_windows(): - target_exe_path = ntpath.join(target_cwd, executable_name) - else: - target_exe_path = posixpath.join(target_cwd, executable_name) - - if cmd: - # Replace exe_path with target_exe_path. - cmd = [c if c != exe_path else target_exe_path for c in cmd] - else: - cmd = [target_exe_path] - - srcs = [exe_path] - dsts = [target_exe_path] - if file_deps is not None: - dev_paths = [os.path.join(target_cwd, os.path.basename(f)) - for f in file_deps] - srcs.extend(file_deps) - dsts.extend(dev_paths) - self.copy_in(srcs, dsts) - - # When testing executables that were cross-compiled on Windows for - # Linux, we may need to explicitly set the execution permission to - # avoid the 'Permission denied' error: - chmod_cmd = ['chmod', '+x', target_exe_path] - - return self._execute_command_remote(chmod_cmd + ['&&'] + cmd, - target_cwd, - env) - finally: - if target_cwd: - self.delete_remote(target_cwd) - - def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): - raise NotImplementedError() - - -class SSHExecutor(RemoteExecutor): - def __init__(self, host, username=None): - super(SSHExecutor, self).__init__() - - self.user_prefix = username + '@' if username else '' - self.host = host - self.scp_command = 'scp' - self.ssh_command = 'ssh' - - if False: - self.local_run = tracing.trace_function( - self.local_run, log_calls=True, log_results=True, - label='ssh_local') - - def _remote_temp(self, is_dir): - # TRANSITION: detect what the target system is, and use the correct - # mktemp command for it. (linux and darwin differ here, and I'm - # sure windows has another way to do it) - - # Not sure how to do suffix on osx yet - dir_arg = '-d' if is_dir else '' - cmd = 'mktemp -q {} /tmp/stl.XXXXXXXXXX'.format(dir_arg) - _, temp_path, err, exitCode = self._execute_command_remote([cmd]) - temp_path = temp_path.strip() - if exitCode != 0: - raise RuntimeError(err) - return temp_path - - def _copy_in_file(self, src, dst): - scp = self.scp_command - remote = self.host - remote = self.user_prefix + remote - cmd = [scp, '-p', src, remote + ':' + dst] - self.local_run(cmd) - - def _export_command(self, env): - if not env: - return [] - - export_cmd = ['export'] - - for k, v in env.items(): - v = v.replace('\\', '\\\\') - if k == 'PATH': - # Pick up the existing paths, so we don't lose any commands - if self.target_info and self.target_info.is_windows(): - export_cmd.append('PATH="%s;%PATH%"' % v) - else: - export_cmd.append('PATH="%s:$PATH"' % v) - else: - export_cmd.append('"%s"="%s"' % (k, v)) - - return export_cmd - - def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): - remote = self.user_prefix + self.host - ssh_cmd = [self.ssh_command, '-oBatchMode=yes', remote] - export_cmd = self._export_command(env) - remote_cmd = ' '.join(cmd) - if export_cmd: - remote_cmd = ' '.join(export_cmd) + ' && ' + remote_cmd - if remote_work_dir != '.': - remote_cmd = 'cd ' + remote_work_dir + ' && ' + remote_cmd - out, err, rc = self.local_run(ssh_cmd + [remote_cmd]) - return (remote_cmd, out, err, rc) diff --git a/tests/utils/stl/test/features.py b/tests/utils/stl/test/features.py new file mode 100644 index 000000000..3128afd16 --- /dev/null +++ b/tests/utils/stl/test/features.py @@ -0,0 +1,48 @@ +#===----------------------------------------------------------------------===// +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#===----------------------------------------------------------------------===// + +import locale +import os +from libcxx.test.dsl import Feature + +def hasLocale(loc): + assert loc is not None + default_locale = locale.setlocale(locale.LC_ALL) + try: + locale.setlocale(locale.LC_ALL, loc) + return True + except locale.Error: + return False + finally: + locale.setlocale(locale.LC_ALL, default_locale) + +def getDefaultFeatures(config, litConfig): + DEFAULT_FEATURES = [Feature(name='msvc'), Feature(name='windows')] + locales = { + 'en_US.UTF-8': ['en_US.UTF-8', 'en_US.utf8', 'English_United States.1252'], + 'fr_FR.UTF-8': ['fr_FR.UTF-8', 'fr_FR.utf8', 'French_France.1252'], + 'ru_RU.UTF-8': ['ru_RU.UTF-8', 'ru_RU.utf8', 'Russian_Russia.1251'], + 'zh_CN.UTF-8': ['zh_CN.UTF-8', 'zh_CN.utf8', 'Chinese_China.936'], + 'fr_CA.ISO8859-1': ['fr_CA.ISO8859-1', 'French_Canada.1252'], + 'cs_CZ.ISO8859-2': ['cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250'] + } + for loc, alts in locales.items(): + # Note: Using alts directly in the lambda body here will bind it to the value at the + # end of the loop. Assigning it to a default argument works around this issue. + DEFAULT_FEATURES.append(Feature(name='locale.{}'.format(loc), + when=lambda cfg, alts=alts: any(hasLocale(alt) for alt in alts))) + env_var = 'STL_EDG_DROP' + litConfig.edg_drop = None + if env_var in os.environ and os.environ[env_var] is not None: + litConfig.edg_drop = os.environ[env_var] + DEFAULT_FEATURES.append(Feature(name='edg_drop')) + + if litConfig.target_arch.casefold() == 'x86'.casefold(): + DEFAULT_FEATURES.append(Feature(name='edg')) + + return DEFAULT_FEATURES diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index d82a1fa91..2526a4f43 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -10,16 +10,15 @@ from dataclasses import dataclass, field from pathlib import Path from typing import Dict, List, Optional import copy -import itertools import errno +import itertools import os +import re import shutil -import time -import lit.Test # pylint: disable=import-error -import lit.TestRunner # pylint: disable=import-error +import lit -from stl.test.tests import STLTest, LibcxxTest +from stl.test.tests import LibcxxTest, STLTest, TestType import stl.test.file_parsing import stl.util @@ -27,295 +26,228 @@ import stl.util @dataclass class TestStep: cmd: List[str] = field(default_factory=list) - work_dir: os.PathLike = field(default=Path('.')) - file_deps: List[os.PathLike] = field(default_factory=list) + workDir: os.PathLike = field(default=Path('.')) env: Dict[str, str] = field(default_factory=dict) - should_fail: bool = field(default=False) + shouldFail: bool = field(default=False) + +def _mergeEnvironments(currentEnv, otherEnv): + """Merges two execution environments. + + If both environments contain PATH variables, they are also merged + using the proper separator. + """ + resultEnv = dict(currentEnv) + for k, v in otherEnv.items(): + if k == 'PATH': + oldPath = currentEnv.get(k, '') + if oldPath != '': + resultEnv[k] = ';'.join((oldPath, v)) + else: + resultEnv[k] = v + else: + resultEnv[k] = v + + return resultEnv + +def _getEnvLst(sourcePath, localConfig): + envlstPath = getattr(localConfig, 'envlst_path', None) + if envlstPath is None: + cwd = Path(sourcePath) + if (cwd / 'env.lst').is_file(): + envlstPath = cwd / 'env.lst' + else: + for parent in cwd.parents: + if (parent / 'env.lst').is_file(): + envlstPath = parent / 'env.lst' + break + + return envlstPath + +def _isLegalDirectory(sourcePath, test_subdirs): + for prefix in test_subdirs: + common = os.path.normpath(os.path.commonpath((sourcePath, prefix))) + if common == sourcePath or common == prefix: + return True + + return False class STLTestFormat: """ Custom test format handler to run MSVC tests. """ - - def __init__(self, default_cxx, execute_external, - build_executor, test_executor): - self.cxx = default_cxx - self.execute_external = execute_external - self.build_executor = build_executor - self.test_executor = test_executor - - def isLegalDirectory(self, source_path, litConfig): - found = False - for prefix in getattr(litConfig, 'test_subdirs', []): - if os.path.commonpath((source_path, prefix)) == prefix or \ - os.path.commonpath((prefix, source_path)) == source_path: - found = True - break - - return found - - def getEnvLst(self, source_path, localConfig): - envlst_path = getattr(localConfig, 'envlst_path', None) - if envlst_path is None: - cwd = Path(source_path) - if (cwd / 'env.lst').is_file(): - envlst_path = cwd / 'env.lst' - else: - for parent in cwd.parents: - if (parent / 'env.lst').is_file(): - envlst_path = parent / 'env.lst' - break - - return envlst_path - - def getTestsInDirectory(self, testSuite, path_in_suite, - litConfig, localConfig, test_class=STLTest): - source_path = testSuite.getSourcePath(path_in_suite) - - if not self.isLegalDirectory(source_path, litConfig): + def getTestsInDirectory(self, testSuite, pathInSuite, litConfig, localConfig, testClass=STLTest): + sourcePath = testSuite.getSourcePath(pathInSuite) + if not _isLegalDirectory(sourcePath, litConfig.test_subdirs[localConfig.name]): return - envlst_path = self.getEnvLst(source_path, localConfig) + envlstPath = _getEnvLst(sourcePath, localConfig) - for filename in os.listdir(source_path): + envEntries = None + if envlstPath is not None: + envEntries = stl.test.file_parsing.parse_env_lst_file(envlstPath) + formatString = '{:0' + str(len(str(len(envEntries)))) + 'd}' + + sourcePath = testSuite.getSourcePath(pathInSuite) + for filename in os.listdir(sourcePath): # Ignore dot files and excluded tests. - filepath = os.path.join(source_path, filename) - if filename.startswith('.'): + if filename.startswith('.') or filename in localConfig.excludes: continue + filepath = os.path.join(sourcePath, filename) if not os.path.isdir(filepath): - if any([filename.endswith(ext) - for ext in localConfig.suffixes]): - - if envlst_path is None: + if any([re.search(ext, filename) for ext in localConfig.suffixes]): + if envEntries is None: litConfig.fatal("Could not find an env.lst file.") - env_entries = \ - stl.test.file_parsing.parse_env_lst_file(envlst_path) - format_string = "{:0" + str(len(str(len(env_entries)))) + \ - "d}" - for env_entry, env_num \ - in zip(env_entries, itertools.count()): - test_config = copy.deepcopy(localConfig) - test_path_in_suite = path_in_suite + (filename,) + for envEntry, envNum in zip(envEntries, itertools.count()): + yield testClass(testSuite, pathInSuite + (filename,), + litConfig, localConfig, envEntry, + formatString.format(envNum)) - yield test_class(testSuite, - test_path_in_suite, - litConfig, test_config, - env_entry, - format_string.format(env_num), - self.cxx) + def getIsenseRspFileSteps(self, test, litConfig, shared): + if litConfig.edg_drop is not None and test.isenseRspPath is not None: + with open(test.isenseRspPath) as f: + cmd = [line.strip() for line in f] + cmd[0] = litConfig.edg_drop - def setup(self, test): - exec_dir = test.getExecDir() - output_dir = test.getOutputDir() - source_dir = Path(test.getSourcePath()).parent - - shutil.rmtree(exec_dir, ignore_errors=True) - shutil.rmtree(output_dir, ignore_errors=True) - exec_dir.mkdir(parents=True, exist_ok=True) - output_dir.mkdir(parents=True, exist_ok=True) - - # TRANSITION: This should be handled by a TestStep with a dependency - # on the .dat files the test requires. - for path in source_dir.iterdir(): - if path.is_file() and path.name.endswith('.dat'): - shutil.copy2(path, exec_dir / path.name) - - def cleanup(self, test): - shutil.rmtree(test.getExecDir(), ignore_errors=True) - shutil.rmtree(test.getOutputDir(), ignore_errors=True) - - def getIntegratedScriptResult(self, test, lit_config): - if test.skipped: - return (lit.Test.SKIPPED, "Test was marked as skipped") - - name = test.path_in_suite[-1] - name_root, name_ext = os.path.splitext(name) - is_sh_test = name_root.endswith('.sh') - is_objcxx_test = name.endswith('.mm') - - if is_sh_test: - return (lit.Test.UNSUPPORTED, - "Sh tests are currently unsupported") - - if is_objcxx_test: - return (lit.Test.UNSUPPORTED, - "Objective-C tests are unsupported") - - if test.config.unsupported: - return (lit.Test.UNSUPPORTED, - "A lit.local.cfg marked this unsupported") - - if lit_config.noExecute: - return lit.Test.Result(lit.Test.PASS) - - if test.expected_result is None: - script = lit.TestRunner.parseIntegratedTestScript( - test, require_script=False) - - if isinstance(script, lit.Test.Result): - return script - - return None - - def execute(self, test, lit_config): - result = None - while True: + # cpfecl translates /Fo into --import_dir, but that is not + # used in the same way by upstream EDG. try: - result = self._execute(test, lit_config) - break - except OSError as oe: - if oe.errno != errno.ETXTBSY: - raise - time.sleep(0.1) + index = cmd.index('--import_dir') + cmd.pop(index) + cmd.pop(index) + except ValueError: + pass - return result + # --print_diagnostics is not recognized by upstream EDG. + try: + index = cmd.index('--print_diagnostics') + cmd.pop(index) + except ValueError: + pass - def _execute(self, test, lit_config): - # TRANSITION: It is potentially wasteful that all the skipping and - # unsupported logic lives here when it is known at time of test - # discovery. Investigate - script_result = self.getIntegratedScriptResult(test, lit_config) - if script_result is not None: - return script_result + yield TestStep(cmd, shared.execDir, shared.env, False) - try: - self.setup(test) - pass_var, fail_var = test.getPassFailResultCodes() - buildSteps, testSteps = self.getSteps(test, lit_config) + def runStep(self, testStep, litConfig): + if str(testStep.workDir) == '.': + testStep.workDir = os.getcwd() - report = "" - for step in buildSteps: - cmd, out, err, rc = \ - self.build_executor.run(step.cmd, step.work_dir, - step.file_deps, step.env) + env = _mergeEnvironments(os.environ, testStep.env) - if step.should_fail and rc == 0: - report += "Build step succeeded unexpectedly.\n" - elif rc != 0: - report += "Build step failed unexpectedly.\n" + return testStep.cmd, *stl.util.executeCommand(testStep.cmd, cwd=testStep.workDir, env=env) - report += stl.util.makeReport(cmd, out, err, rc) - if (step.should_fail and rc == 0) or \ - (not step.should_fail and rc != 0): - lit_config.note(report) - return lit.Test.Result(fail_var, report) - - for step in testSteps: - cmd, out, err, rc = \ - self.test_executor.run(step.cmd, step.work_dir, - step.file_deps, step.env) - - if step.should_fail and rc == 0: - report += "Test step succeeded unexpectedly.\n" - elif rc != 0: - report += "Test step failed unexpectedly.\n" - - report += stl.util.makeReport(cmd, out, err, rc) - if (step.should_fail and rc == 0) or \ - (not step.should_fail and rc != 0): - lit_config.note(report) - return lit.Test.Result(fail_var, report) - - return lit.Test.Result(pass_var, report) - - except Exception as e: - lit_config.warning(str(e)) - raise e - finally: - self.cleanup(test) - - def getSteps(self, test, lit_config): + def getStages(self, test, litConfig): @dataclass class SharedState: - exec_file: Optional[os.PathLike] = field(default=None) - exec_dir: os.PathLike = field(default_factory=Path) + execFile: Optional[os.PathLike] = field(default=None) + execDir: os.PathLike = field(default_factory=Path) + env: Dict[str, str] = field(default_factory=dict) - shared = SharedState() - return self.getBuildSteps(test, lit_config, shared), \ - self.getTestSteps(test, lit_config, shared) + execDir, _ = test.getTempPaths() + shared = SharedState(None, execDir, copy.deepcopy(litConfig.test_env)) + shared.env['TMP'] = execDir + shared.env['TEMP'] = execDir + shared.env['TMPDIR'] = execDir + shared.env['TEMPDIR'] = execDir - def getBuildSteps(self, test, lit_config, shared): - if not test.path_in_suite[-1].endswith('.fail.cpp'): - shared.exec_dir = test.getExecDir() - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - source_path = Path(test.getSourcePath()) + return [ + ('Build setup', self.getBuildSetupSteps(test, litConfig, shared)), + ('Build', self.getBuildSteps(test, litConfig, shared)), + ('Intellisense response file', self.getIsenseRspFileSteps(test, litConfig, shared)), + ('Test setup', self.getTestSetupSteps(test, litConfig, shared)), + ('Test', self.getTestSteps(test, litConfig, shared))] - flags = [] - isense_rsp_path = None - if test.cxx.edg_drop is not None: - isense_rsp_path = output_dir / (output_base + '.isense.rsp') - flags.extend(['/dE--write-isense-rsp', '/dE' + str(isense_rsp_path)]) + def getBuildSetupSteps(self, test, litConfig, shared): + shutil.rmtree(shared.execDir, ignore_errors=True) + Path(shared.execDir).mkdir(parents=True, exist_ok=True) - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([source_path], output_dir, - shared.exec_dir, output_base, - flags, [], []) + # Makes this function a generator which yields nothing + yield from [] - yield TestStep(cmd, shared.exec_dir, [source_path], - test.cxx.compile_env) + def getBuildSteps(self, test, litConfig, shared): + filename = test.path_in_suite[-1] + _, tmpBase = test.getTempPaths() - if isense_rsp_path is not None: - with open(isense_rsp_path) as f: - cmd = [line.strip() for line in f] - cmd[0] = test.cxx.edg_drop + shouldFail = TestType.FAIL in test.testType + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', test.getSourcePath(), *test.flags, *test.compileFlags] + yield TestStep(cmd, shared.execDir, shared.env, shouldFail) + elif TestType.LINK in test.testType: + objFile = tmpBase + '.o' + cmd = [test.cxx, '/c', test.getSourcePath(), *test.flags, *test.compileFlags, '/Fo' + objFile] + yield TestStep(cmd, shared.execDir, shared.env, False) - # cpfecl translates /Fo into --import_dir, but that is not - # used in the same way by upstream EDG. - try: - index = cmd.index('--import_dir') - cmd.pop(index) - cmd.pop(index) - except ValueError: - pass + exeFile = tmpBase + '.exe' + cmd = [test.cxx, objFile, *test.flags, '/Fe' + exeFile, '/link', *test.linkFlags] + yield TestStep(cmd, shared.execDir, shared.env, shouldFail) + elif TestType.RUN in test.testType: + shared.execFile = tmpBase + '.exe' + cmd = [test.cxx, test.getSourcePath(), *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags] + yield TestStep(cmd, shared.execDir, shared.env, False) - # --print_diagnostics is not recognized by upstream EDG. - try: - index = cmd.index('--print_diagnostics') - cmd.pop(index) - except ValueError: - pass + def getTestSetupSteps(self, test, litConfig, shared): + if TestType.RUN in test.testType: + for dependency in test.fileDependencies: + if not os.path.isabs(dependency): + dependency = os.path.join(os.path.dirname(test.getSourcePath()), dependency) + shutil.copy2(dependency, os.path.join(shared.execDir, os.path.basename(dependency))) - yield TestStep(cmd, shared.exec_dir, [source_path], - test.cxx.compile_env) + yield from [] - def getTestSteps(self, test, lit_config, shared): - if shared.exec_file is not None: - exec_env = test.cxx.compile_env - exec_env['TMP'] = str(shared.exec_dir) + def getTestSteps(self, test, litConfig, shared): + if not TestType.RUN in test.testType: + yield from [] + return - yield TestStep([str(shared.exec_file)], shared.exec_dir, - [shared.exec_file], exec_env) - elif test.path_in_suite[-1].endswith('.fail.cpp'): - exec_dir = test.getExecDir() - source_path = Path(test.getSourcePath()) + shouldFail = TestType.FAIL in test.testType + yield TestStep([shared.execFile], shared.execDir, shared.env, shouldFail) - flags = [] - if test.cxx.name == 'cl' and \ - ('/analyze' in test.cxx.flags or - '/analyze' in test.cxx.compile_flags): - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - analyze_path = output_dir / (output_base + - '.nativecodeanalysis.xml') - flags.append('/analyze:log' + str(analyze_path)) + def execute(self, test, litConfig): + try: + result = test.configureTest(litConfig) + if result: + return result - cmd, _ = test.cxx.compileCmd([source_path], os.devnull, flags) - yield TestStep(cmd, exec_dir, [source_path], - test.cxx.compile_env, True) + if test.expectedResult and test.expectedResult.isFailure: + failVar = lit.Test.XFAIL + passVar = lit.Test.XPASS + else: + failVar = lit.Test.FAIL + passVar = lit.Test.PASS + + stages = self.getStages(test, litConfig) + + report = '' + for stageName, steps in stages: + report += stageName + ' steps:\n' + for step in steps: + cmd, out, err, rc = self.runStep(step, litConfig) + + if step.shouldFail and rc == 0: + report += stageName + ' step succeeded unexpectedly.\n' + elif rc != 0: + report += stageName + ' step failed unexpectedly.\n' + + report += stl.util.makeReport(cmd, out, err, rc) + if (step.shouldFail and rc == 0) or (not step.shouldFail and rc != 0): + return (failVar, report) + + return (passVar, '') + + except Exception as e: + litConfig.error(repr(e)) class LibcxxTestFormat(STLTestFormat): """ Custom test format handler to run the libcxx tests for the MSVC STL. """ - def getTestsInDirectory(self, testSuite, path_in_suite, - litConfig, localConfig, test_class=LibcxxTest): - return super().getTestsInDirectory(testSuite, path_in_suite, litConfig, - localConfig, test_class) + def getTestsInDirectory(self, testSuite, pathInSuite, + litConfig, localConfig, testClass=LibcxxTest): + return super().getTestsInDirectory(testSuite, pathInSuite, litConfig, + localConfig, testClass) def addCompileFlags(self, *args): # For now, this is necessary to discard the value of diff --git a/tests/utils/stl/test/params.py b/tests/utils/stl/test/params.py new file mode 100644 index 000000000..e57ddaf0c --- /dev/null +++ b/tests/utils/stl/test/params.py @@ -0,0 +1,18 @@ +#===----------------------------------------------------------------------===## +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#===----------------------------------------------------------------------===## + +from libcxx.test.dsl import * + +def getDefaultParameters(config, litConfig): + DEFAULT_PARAMETERS = [ + Parameter(name='long_tests', choices=[True, False], type=bool, default=True, + help="Whether to run tests that take a long time. This can be useful when running on a slow device.", + feature=lambda enabled: Feature(name='long_tests') if enabled else None), + ] + + return DEFAULT_PARAMETERS diff --git a/tests/utils/stl/test/target_info.py b/tests/utils/stl/test/target_info.py deleted file mode 100644 index 3c8dce3e3..000000000 --- a/tests/utils/stl/test/target_info.py +++ /dev/null @@ -1,45 +0,0 @@ -#===----------------------------------------------------------------------===// -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===// - -import locale - - -def _test_locale(loc): - assert loc is not None - default_locale = locale.setlocale(locale.LC_ALL) - try: - locale.setlocale(locale.LC_ALL, loc) - return True - except locale.Error: - return False - finally: - locale.setlocale(locale.LC_ALL, default_locale) - - -class WindowsLocalTI: - def __init__(self, lit_config): - self.features = set() - self._add_common_locales(lit_config) - - def _add_common_locales(self, lit_config): - locales = [ - ('en_US.UTF-8', 'English_United States.1252'), - ('fr_FR.UTF-8', 'French_France.1252'), - ('ru_RU.UTF-8', 'Russian_Russia.1251'), - ('zh_CN.UTF-8', 'Chinese_China.936'), - ('fr_CA.ISO8859-1', 'French_Canada.1252'), - ('cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250') - ] - - for loc_id, loc_name in locales: - if _test_locale(loc_name): - self.features.add('locale.{0}'.format(loc_id)) - else: - lit_config.note('The locale {0} is not supported by ' - 'your platform. Some tests will be ' - 'unsupported.'.format(loc_name)) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index 0dce11f5a..ced4ff2b2 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -7,215 +7,234 @@ # #===----------------------------------------------------------------------===## +from enum import Flag, auto from itertools import chain -from pathlib import Path -from xml.sax.saxutils import quoteattr +import copy import os import shutil -from lit.Test import FAIL, PASS, SKIPPED, Test, UNSUPPORTED, XPASS, XFAIL +from lit.Test import SKIPPED, Result, Test, UNRESOLVED, UNSUPPORTED +from libcxx.test.dsl import Feature +import lit -from stl.compiler import CXXCompiler +_compilerPathCache = dict() -_compiler_path_cache = dict() + +class TestType(Flag): + UNKNOWN = auto() + COMPILE = auto() + LINK = auto() + RUN = auto() + PASS = auto() + FAIL = auto() class STLTest(Test): - def __init__(self, suite, path_in_suite, lit_config, test_config, - envlst_entry, env_num, default_cxx, file_path=None): - self.env_num = env_num - self.skipped = False - Test.__init__(self, suite, path_in_suite, test_config, file_path) + def __init__(self, suite, pathInSuite, litConfig, testConfig, envlstEntry, envNum): + self.envNum = envNum + self.envlstEntry = envlstEntry + Test.__init__(self, suite, pathInSuite, testConfig, None) - self._configure_expected_result(suite, path_in_suite, lit_config, - test_config, env_num) - if self.skipped: - return + def configureTest(self, litConfig): + self.compileFlags = [] + self.cxx = None + self.fileDependencies = [] + self.flags = [] + self.isenseRspPath = None + self.linkFlags = [] + self.testType = None - self._configure_cxx(lit_config, envlst_entry, default_cxx) + result = self._configureExpectedResult(litConfig) + if result: + return result - use_edg = False - for flag in chain(self.cxx.flags, self.cxx.compile_flags): - if flag[1:] == 'clr:pure': - self.requires.append('clr_pure') # TRANSITION, GH-798 - elif flag[1:] == 'clr': - self.requires.append('clr') # TRANSITION, GH-797 - elif flag[1:] == 'BE': - self.requires.append('edg') # available for x86, see config.py - use_edg = True + self._handleEnvlst(litConfig) + self._parseTest() + self._parseFlags() - if not use_edg and self.cxx.edg_drop is not None: - self.skipped = True + missing_required_features = self.getMissingRequiredFeatures() + if missing_required_features: + msg = ', '.join(missing_required_features) + return Result(UNSUPPORTED, "Test requires the following unavailable features: %s" % msg) - def getOutputDir(self): - return Path(os.path.join( - self.suite.getExecPath(self.path_in_suite[:-1]))) / self.env_num + unsupported_features = self.getUnsupportedFeatures() + if unsupported_features: + msg = ', '.join(unsupported_features) + return Result(UNSUPPORTED, "Test does not support the following features and/or targets: %s" % msg) - def getOutputBaseName(self): - return self.path_in_suite[-2] + if not self.isWithinFeatureLimits(): + msg = ', '.join(self.config.limit_to_features) + return Result(UNSUPPORTED, "Test does not require any of the features specified in limit_to_features: %s" % + msg) - def getExecDir(self): - return self.getOutputDir() + if 'edg_drop' in self.config.available_features: + if not 'edg' in self.requires: + return Result(UNSUPPORTED, 'We only run /BE tests with the edg drop') - def getExecPath(self): - return self.getExecDir() / (self.getOutputBaseName() + '.exe') + _, tmpBase = self.getTempPaths() + self.isenseRspPath = tmpBase + '.isense.rsp' + self.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + self.isenseRspPath]) + + self._configureTestType() + return None + + def _parseTest(self): + additionalCompileFlags = [] + fileDependencies = [] + parsers = [ + lit.TestRunner.IntegratedTestKeywordParser('FILE_DEPENDENCIES:', + lit.TestRunner.ParserKind.LIST, + initial_value=fileDependencies), + lit.TestRunner.IntegratedTestKeywordParser('ADDITIONAL_COMPILE_FLAGS:', + lit.TestRunner.ParserKind.LIST, + initial_value=additionalCompileFlags) + ] + + lit.TestRunner.parseIntegratedTestScript(self, additional_parsers=parsers, require_script=False) + self.compileFlags.extend(additionalCompileFlags) + self.fileDependencies.extend(fileDependencies) + + def _configureTestType(self): + self.testType = TestType.UNKNOWN + filename = self.path_in_suite[-1] + + if filename.endswith('.fail.cpp'): + self.testType = self.testType | TestType.FAIL + elif filename.endswith('.pass.cpp'): + self.testType = self.testType | TestType.PASS + else: + self.testType = self.testType | TestType.PASS + + shortenedFlags = [flag[1:] for flag in chain(self.flags, self.compileFlags, self.linkFlags)] + if 'analyze:only' in shortenedFlags or 'c' in shortenedFlags or \ + filename.endswith(('.compile.pass.cpp', '.compile.fail.cpp')): + self.testType = self.testType | TestType.COMPILE + elif filename.endswith(('.link.pass.cpp', '.link.fail.cpp')): + self.testType = self.testType | TestType.LINK + elif filename.endswith(('run.fail.cpp','run.pass.cpp')): + self.testType = self.testType | TestType.RUN + elif filename.endswith('.fail.cpp'): + self.testType = self.testType | TestType.COMPILE + elif filename.endswith('.pass.cpp'): + self.testType = self.testType | TestType.RUN + else: + self.testType = self.testType | TestType.RUN + + self.testType = self.testType & ~TestType.UNKNOWN def getTestName(self): - return '/'.join(self.path_in_suite[:-1]) + ":" + self.env_num + return '/'.join(self.path_in_suite[:-1]) + ":" + self.envNum def getFullName(self): return self.suite.config.name + ' :: ' + self.getTestName() - def getPassFailResultCodes(self): - should_fail = self.isExpectedToFail() - pass_var = XPASS if should_fail else PASS - fail_var = XFAIL if should_fail else FAIL + def getSourcePath(self): + return os.path.normpath(super().getSourcePath()) - return pass_var, fail_var + def getExecDir(self): + execDir, _ = lit.TestRunner.getTempPaths(self) + execDir = os.path.join(execDir, self.envNum) + return os.path.normpath(execDir) - def getXMLOutputTestName(self): - return ':'.join((self.path_in_suite[-2], self.env_num)) + def getTempPaths(self): + tmpDir = self.getExecDir() + tmpBase = os.path.join(tmpDir, self.path_in_suite[-2]) + return tmpDir, os.path.normpath(tmpBase) - def getXMLOutputClassName(self): - safe_test_path = [x.replace(".", "_") for x in self.path_in_suite[:-1]] - safe_suite_name = self.suite.name.replace(".", "-") + def _configureExpectedResult(self, litConfig): + testName = self.getTestName() + self.expectedResult = None - if safe_test_path: - return safe_suite_name + "." + "/".join(safe_test_path) + if testName in litConfig.expected_results.get(self.config.name, dict()): + self.expectedResult = litConfig.expected_results[self.config.name][testName] else: - return safe_suite_name + "." + safe_suite_name + currentPrefix = "" + for prefix, result in litConfig.expected_results.get(self.config.name, dict()).items(): + if testName == prefix: + self.expectedResult = result + break + elif testName.startswith(prefix) and len(prefix) > len(currentPrefix): + currentPrefix = prefix + self.expectedResult = result - def _configure_expected_result(self, suite, path_in_suite, lit_config, - test_config, env_num): - test_name = self.getTestName() - self.expected_result = None - - current_prefix = "" - for prefix, result in \ - chain(test_config.expected_results.items(), - lit_config.expected_results.get(test_config.name, - dict()).items()): - if test_name == prefix: - self.expected_result = result - break - elif test_name.startswith(prefix) and \ - len(prefix) > len(current_prefix): - current_prefix = prefix - self.expected_result = result - - if test_name in test_config.expected_results: - self.expected_result = test_config.expected_results[test_name] - elif test_name in lit_config.expected_results: - self.expected_result = lit_config.expected_results[test_name] - - if self.expected_result is not None: - if self.expected_result == SKIPPED: - self.skipped = True - elif self.expected_result.isFailure: + if self.expectedResult is not None: + if self.expectedResult == SKIPPED: + return Result(SKIPPED, 'This test was explicitly marked as skipped') + elif self.expectedResult.isFailure: self.xfails = ['*'] + elif self.config.unsupported: + return Result(UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') - def _configure_cxx(self, lit_config, envlst_entry, default_cxx): - env_compiler = envlst_entry.getEnvVal('PM_COMPILER', 'cl') + return None - if not os.path.isfile(env_compiler): - cxx = _compiler_path_cache.get(env_compiler, None) + def _handleEnvlst(self, litConfig): + envCompiler = self.envlstEntry.getEnvVal('PM_COMPILER', 'cl') + + cxx = None + if not os.path.isfile(envCompiler): + cxx = _compilerPathCache.get(envCompiler, None) if cxx is None: - search_paths = self.config.environment['PATH'] - cxx = shutil.which(env_compiler, path=search_paths) - _compiler_path_cache[env_compiler] = cxx + searchPaths = self.config.environment['PATH'] + cxx = shutil.which(envCompiler, path=searchPaths) + _compilerPathCache[envCompiler] = cxx + else: + cxx = envCompiler if not cxx: - lit_config.fatal('Could not find: %r' % env_compiler) + litConfig.fatal('Could not find: %r' % envCompiler) - flags = list() - compile_flags = list() - link_flags = list() + self.flags = copy.deepcopy(litConfig.flags[self.config.name]) + self.compileFlags = copy.deepcopy(litConfig.compile_flags[self.config.name]) + self.linkFlags = copy.deepcopy(litConfig.link_flags[self.config.name]) - flags.extend(default_cxx.flags or []) - compile_flags.extend(default_cxx.compile_flags or []) - link_flags.extend(default_cxx.link_flags or []) - - flags.extend(envlst_entry.getEnvVal('PM_CL', '').split()) - link_flags.extend(envlst_entry.getEnvVal('PM_LINK', '').split()) + self.compileFlags.extend(self.envlstEntry.getEnvVal('PM_CL', '').split()) + self.linkFlags.extend(self.envlstEntry.getEnvVal('PM_LINK', '').split()) if ('clang'.casefold() in os.path.basename(cxx).casefold()): - target_arch = self.config.target_arch.casefold() - if (target_arch == 'x64'.casefold()): - compile_flags.append('-m64') - elif (target_arch == 'x86'.casefold()): - compile_flags.append('-m32') + targetArch = litConfig.target_arch.casefold() + if (targetArch == 'x64'.casefold()): + self.compileFlags.append('-m64') + elif (targetArch == 'x86'.casefold()): + self.compileFlags.append('-m32') - self.cxx = CXXCompiler(cxx, flags, compile_flags, link_flags, - default_cxx.compile_env, default_cxx.edg_drop) + self.cxx = os.path.normpath(cxx) - # This is partially lifted from lit's Test class. The changes here are to - # handle skipped tests, our env.lst format, and different naming schemes. - def writeJUnitXML(self, fil): - """Write the test's report xml representation to a file handle.""" - test_name = quoteattr(self.getXMLOutputTestName()) - class_name = quoteattr(self.getXMLOutputClassName()) + def _parseFlags(self): + foundStd = False + for flag in chain(self.flags, self.compileFlags, self.linkFlags): + if flag[1:5] == 'std:': + foundStd = True + if flag[5:] == 'c++latest': + Feature('c++2a').enableIn(self.config) + elif flag[5:] == 'c++17': + Feature('c++17').enableIn(self.config) + elif flag[5:] == 'c++14': + Feature('c++14').enableIn(self.config) + elif flag[1:] == 'clr:pure': + self.requires.append('clr_pure') # TRANSITION, GH-798 + elif flag[1:] == 'clr': + self.requires.append('clr') # TRANSITION, GH-797 + elif flag[1:] == 'BE': + self.requires.append('edg') # available for x86, see features.py - testcase_template = \ - '\n\t", "]]]]>")) - fil.write("]]>\n") - elif self.result.code == UNSUPPORTED: - unsupported_features = self.getMissingRequiredFeatures() - if unsupported_features: - skip_message = \ - "Skipping because of: " + ", ".join(unsupported_features) - else: - skip_message = "Skipping because of configuration." - skip_message = quoteattr(skip_message) - - fil.write( - ">\n\t\n".format( - skip_message)) - elif self.result.code == SKIPPED: - message = quoteattr('Test is explicitly marked as skipped') - fil.write(">\n\t\n".format( - message)) - else: - fil.write("/>") + if not foundStd: + Feature('c++14').enableIn(self.config) class LibcxxTest(STLTest): - def getOutputBaseName(self): - output_base = self.path_in_suite[-1] - - if output_base.endswith('.cpp'): - return output_base[:-4] - else: - return output_base - - def getOutputDir(self): - dir_name = self.path_in_suite[-1] - if dir_name.endswith('.cpp'): - dir_name = dir_name[:-4] - - return Path(os.path.join( - self.suite.getExecPath(self.path_in_suite[:-1]))) / dir_name / \ - self.env_num - - def getXMLOutputTestName(self): - return ':'.join((self.path_in_suite[-1], self.env_num)) - def getTestName(self): - return '/'.join(self.path_in_suite) + ':' + self.env_num + return '/'.join(self.path_in_suite) + ':' + self.envNum + + def getExecDir(self): + execDir, _ = lit.TestRunner.getTempPaths(self) + execDir = os.path.join(execDir, self.path_in_suite[-1] + '.dir') + execDir = os.path.join(execDir, self.envNum) + return os.path.normpath(execDir) + + def getTempPaths(self): + tmpDir = self.getExecDir() + tmpBase = os.path.join(tmpDir, self.path_in_suite[-1]) + if tmpBase.endswith('.cpp'): + tmpBase = tmpBase[:-4] + return tmpDir, os.path.normpath(tmpBase) diff --git a/tests/utils/stl/test/tracing.py b/tests/utils/stl/test/tracing.py deleted file mode 100644 index 8871c7ef6..000000000 --- a/tests/utils/stl/test/tracing.py +++ /dev/null @@ -1,41 +0,0 @@ -#===----------------------------------------------------------------------===## -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===## - -import inspect - - -def trace_function(function, log_calls, log_results, label=''): - def wrapper(*args, **kwargs): - kwarg_strs = ['{}={}'.format(k, v) for (k, v) in kwargs] - arg_str = ', '.join([str(a) for a in args] + kwarg_strs) - call_str = '{}({})'.format(function.__name__, arg_str) - - # Perform the call itself, logging before, after, and anything thrown. - try: - if log_calls: - print('{}: Calling {}'.format(label, call_str)) - res = function(*args, **kwargs) - if log_results: - print('{}: {} -> {}'.format(label, call_str, res)) - return res - except Exception as ex: - if log_results: - print('{}: {} raised {}'.format(label, call_str, type(ex))) - raise ex - - return wrapper - - -def trace_object(obj, log_calls, log_results, label=''): - for name, member in inspect.getmembers(obj): - if inspect.ismethod(member): - # Skip meta-functions, decorate everything else - if not member.__name__.startswith('__'): - setattr(obj, name, trace_function(member, log_calls, - log_results, label)) - return obj