зеркало из https://github.com/microsoft/STL.git
Let's rewrite the test harness (#1394)
Co-authored-by: Casey Carter <cacarter@microsoft.com> Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
This commit is contained in:
Родитель
185654c523
Коммит
9ee552969c
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 "
|
||||
"<build>/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration "
|
||||
"file is used.")
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 "
|
||||
"<build>/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration "
|
||||
"file is used.")
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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-"
|
||||
|
|
|
@ -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-"
|
||||
|
|
|
@ -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-"
|
||||
|
|
|
@ -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 "
|
||||
"<build>/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration "
|
||||
"file is used.")
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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)
|
|
@ -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)}
|
||||
|
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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))
|
|
@ -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 = \
|
||||
'<testcase classname={class_name} name={test_name} ' \
|
||||
'time="{time:.2f}"'
|
||||
elapsed_time = self.result.elapsed if self.result.elapsed else 0.0
|
||||
testcase_xml = \
|
||||
testcase_template.format(class_name=class_name,
|
||||
test_name=test_name,
|
||||
time=elapsed_time)
|
||||
fil.write(testcase_xml)
|
||||
|
||||
if self.result.code.isFailure:
|
||||
fil.write(">\n\t<failure><![CDATA[")
|
||||
if isinstance(self.result.output, str):
|
||||
encoded_output = self.result.output
|
||||
elif isinstance(self.result.output, bytes):
|
||||
encoded_output = self.result.output.decode("utf-8", 'replace')
|
||||
# In the unlikely case that the output contains the CDATA
|
||||
# terminator we wrap it by creating a new CDATA block
|
||||
fil.write(encoded_output.replace("]]>", "]]]]><![CDATA[>"))
|
||||
fil.write("]]></failure>\n</testcase>")
|
||||
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<skipped message={} />\n</testcase>".format(
|
||||
skip_message))
|
||||
elif self.result.code == SKIPPED:
|
||||
message = quoteattr('Test is explicitly marked as skipped')
|
||||
fil.write(">\n\t<skipped message={} />\n</testcase>".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)
|
||||
|
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче