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:
Curtis J Bezault 2020-11-06 13:57:46 -08:00 коммит произвёл GitHub
Родитель 185654c523
Коммит 9ee552969c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
74 изменённых файлов: 749 добавлений и 1637 удалений

Просмотреть файл

@ -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