From 751506037dc9261d3a22e2bffb745df574ee7783 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Sat, 25 Jul 2020 20:43:54 -0700 Subject: [PATCH 01/56] Update LLVM reference --- llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm-project b/llvm-project index d66428cb995..4b14ef33e81 160000 --- a/llvm-project +++ b/llvm-project @@ -1 +1 @@ -Subproject commit d66428cb995c7a04ecb02951d5021d815fc02b2b +Subproject commit 4b14ef33e81c01632e848e7a67ccc6b11fb4c595 From d4ff68bce985c0c186027cad39dfd8e2387f17df Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 16 Oct 2020 13:41:33 -0700 Subject: [PATCH 02/56] Avoid relying on upstream libcxx lit.cfg --- tests/libcxx/CMakeLists.txt | 2 +- tests/libcxx/lit.cfg | 29 +++++++++++++++++++++++++++++ tests/libcxx/lit.site.cfg.in | 9 +++------ 3 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 tests/libcxx/lit.cfg diff --git a/tests/libcxx/CMakeLists.txt b/tests/libcxx/CMakeLists.txt index 3272b95ff78..0aba3abeb45 100644 --- a/tests/libcxx/CMakeLists.txt +++ b/tests/libcxx/CMakeLists.txt @@ -11,6 +11,6 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) -set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") +set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg.py\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") set_property(GLOBAL APPEND_STRING PROPERTY STL_LIT_CONFIG_MAP ${LIBCXX_LIT_CONFIG_MAP}) set_property(GLOBAL APPEND PROPERTY STL_LIT_TEST_DIRS "${LIBCXX_SOURCE_DIR}/test/std") diff --git a/tests/libcxx/lit.cfg b/tests/libcxx/lit.cfg new file mode 100644 index 00000000000..44b72cde9e6 --- /dev/null +++ b/tests/libcxx/lit.cfg @@ -0,0 +1,29 @@ +# 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() diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index 473dace7e7c..c3eea2c29b6 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -18,11 +18,8 @@ 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"] -lit_config.params['use_old_format'] = True -config.loaded_site_config = True -lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/test/lit.cfg") - -config.suffixes = [".pass.cpp", ".fail.cpp"] -config.test_exec_root = "@LIBCXX_TEST_OUTPUT_DIR@" +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") From f62ad74fc3b430c430672b8d8b93bc906b36f52c Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 19 Oct 2020 08:39:13 -0700 Subject: [PATCH 03/56] Skip bogus failing tests --- tests/libcxx/expected_results.txt | 4 ++++ tests/libcxx/skipped_tests.txt | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 33115b7aed8..411b28d1b10 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -768,6 +768,10 @@ std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/eval.pass.cpp F # They shouldn't behave differently. Both of them should probably return NaN. std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp FAIL +# These tests supress warnings only for Clang [Fixed upstream] +std/numerics/numbers/defined.pass.cpp:0 FAIL +std/numerics/numbers/specialize.pass.cpp:0 FAIL + # *** LIKELY STL BUGS *** # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 4239de46b5b..ef393ad298a 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -768,6 +768,10 @@ numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\eval.pass.cpp # They shouldn't behave differently. Both of them should probably return NaN. numerics\c.math\c.math.lerp\c.math.lerp.pass.cpp +# These tests supress warnings only for Clang [Fixed upstream] +numerics\numbers\defined.pass.cpp +numerics\numbers\specialize.pass.cpp + # *** LIKELY STL BUGS *** # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. From 7a859cd423e2ad0254a2c988a46ff547dd1c041b Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 19 Oct 2020 08:41:13 -0700 Subject: [PATCH 04/56] Apply suggestions from code review Fix tpyos --- tests/libcxx/expected_results.txt | 2 +- tests/libcxx/skipped_tests.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 411b28d1b10..fc811145556 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -768,7 +768,7 @@ std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/eval.pass.cpp F # They shouldn't behave differently. Both of them should probably return NaN. std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp FAIL -# These tests supress warnings only for Clang [Fixed upstream] +# These tests suppress warnings only for Clang [Fixed upstream] std/numerics/numbers/defined.pass.cpp:0 FAIL std/numerics/numbers/specialize.pass.cpp:0 FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index ef393ad298a..1656bc0ff03 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -768,7 +768,7 @@ numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\eval.pass.cpp # They shouldn't behave differently. Both of them should probably return NaN. numerics\c.math\c.math.lerp\c.math.lerp.pass.cpp -# These tests supress warnings only for Clang [Fixed upstream] +# These tests suppress warnings only for Clang [Fixed upstream] numerics\numbers\defined.pass.cpp numerics\numbers\specialize.pass.cpp From 777d49b76cbe7e62951416c15f773c1a392d470b Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Mon, 19 Oct 2020 13:08:11 -0700 Subject: [PATCH 05/56] Update LLVM reference to latest --- llvm-project | 2 +- tests/libcxx/expected_results.txt | 4 ---- tests/libcxx/skipped_tests.txt | 4 ---- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/llvm-project b/llvm-project index 4b14ef33e81..edd0cb11bd1 160000 --- a/llvm-project +++ b/llvm-project @@ -1 +1 @@ -Subproject commit 4b14ef33e81c01632e848e7a67ccc6b11fb4c595 +Subproject commit edd0cb11bd182de8d70b7bbeba73f88d7a3714db diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index fc811145556..33115b7aed8 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -768,10 +768,6 @@ std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/eval.pass.cpp F # They shouldn't behave differently. Both of them should probably return NaN. std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp FAIL -# These tests suppress warnings only for Clang [Fixed upstream] -std/numerics/numbers/defined.pass.cpp:0 FAIL -std/numerics/numbers/specialize.pass.cpp:0 FAIL - # *** LIKELY STL BUGS *** # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 1656bc0ff03..4239de46b5b 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -768,10 +768,6 @@ numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\eval.pass.cpp # They shouldn't behave differently. Both of them should probably return NaN. numerics\c.math\c.math.lerp\c.math.lerp.pass.cpp -# These tests suppress warnings only for Clang [Fixed upstream] -numerics\numbers\defined.pass.cpp -numerics\numbers\specialize.pass.cpp - # *** LIKELY STL BUGS *** # Not yet analyzed, likely STL bugs. Assertions and other runtime failures. From 5d3ee9ada7a80b6f1746db0a262ca0071d5259b8 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 19 Oct 2020 14:11:36 -0700 Subject: [PATCH 06/56] Update atomic_init per P0883R3 We correctly deprecated `atomic_init` when implementing P0883R2, but missed that the effects changed as well. --- stl/inc/atomic | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/stl/inc/atomic b/stl/inc/atomic index 78820eb37b3..349bcc92615 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -2465,25 +2465,6 @@ _NODISCARD bool atomic_is_lock_free(const atomic<_Ty>* _Mem) noexcept { return _Mem->is_lock_free(); } -template -_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( - atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { -#if 1 // TRANSITION, ABI - _CSTD memcpy(_STD addressof(_Mem->_Storage), _STD addressof(_Value), sizeof(_Ty)); -#else // ^^^ don't break ABI / break ABI vvv - _CSTD memcpy(_Mem, _STD addressof(_Value), sizeof(_Ty)); -#endif // TRANSITION, ABI - _CSTD memset(reinterpret_cast(_Mem) + sizeof(_Ty), 0, sizeof(atomic<_Ty>) - sizeof(_Ty)); -} - -template -_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( - volatile atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { - // NB: respecting volatility here appears unimplementable - static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); - _STD atomic_init(const_cast*>(_Mem), _Value); -} - template void atomic_store(volatile atomic<_Ty>* const _Mem, const _Identity_t<_Ty> _Value) noexcept { static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); @@ -2507,6 +2488,19 @@ void atomic_store_explicit(atomic<_Ty>* const _Mem, const _Identity_t<_Ty> _Valu _Mem->store(_Value, _Order); } +template +_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( + volatile atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { + static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); + _STD atomic_store_explicit(_Mem, _Value, memory_order_relaxed); +} + +template +_CXX20_DEPRECATE_ATOMIC_INIT void atomic_init( + atomic<_Ty>* const _Mem, const typename atomic<_Ty>::value_type _Value) noexcept { + _STD atomic_store_explicit(_Mem, _Value, memory_order_relaxed); +} + template _NODISCARD _Ty atomic_load(const volatile atomic<_Ty>* const _Mem) noexcept { static_assert(_Deprecate_non_lock_free_volatile<_Ty>, "Never fails"); From e46a1620b1ec7299dccf9fd2c9abb8c858af2efd Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 19 Oct 2020 17:24:14 -0700 Subject: [PATCH 07/56] Update LLVM reference once again --- llvm-project | 2 +- tests/libcxx/expected_results.txt | 40 +++++++++++++++++++++++++------ tests/libcxx/skipped_tests.txt | 40 +++++++++++++++++++++++++------ 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/llvm-project b/llvm-project index edd0cb11bd1..a668ad92d5e 160000 --- a/llvm-project +++ b/llvm-project @@ -1 +1 @@ -Subproject commit edd0cb11bd182de8d70b7bbeba73f88d7a3714db +Subproject commit a668ad92d5e2161e07e1a435a19ea5072f52a989 diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 33115b7aed8..b98dcb3243b 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -66,6 +66,12 @@ std/numerics/bit/bit.pow.two/log2p1.pass.cpp FAIL # test emits warning C4310: cast truncates constant value std/numerics/bit/bitops.rot/rotl.pass.cpp:0 FAIL +# libc++ doesn't yet implement P1754R1 or P1964R2, so it expects an old value for `__cpp_lib_concepts` +std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp FAIL + +# libc++ doesn't yet implement P1001R2, so it expects an old value for `__cpp_lib_execution` +std/language.support/support.limits/support.limits.general/execution.version.pass.cpp FAIL + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -252,6 +258,9 @@ std/utilities/function.objects/negators/not2.depr_in_cxx17.verify.cpp SKIPPED std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.cpp SKIPPED std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKIPPED +# GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests +strings\string.view\string.view.io\stream_insert_decl_present.compile.pass.cpp + # *** MISSING STL FEATURES *** # C++20 P0355R7 " Calendars And Time Zones" @@ -464,6 +473,21 @@ std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp FAIL # C++20 P0768R1 "Library Support for the Spaceship (Comparison) Operator" std/language.support/support.limits/support.limits.general/compare.version.pass.cpp FAIL +# C++20 P0784R7 "More constexpr containers" +std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp FAIL +std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp FAIL +std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp FAIL +std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp FAIL +std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp FAIL + # C++20 P0896R4 "" std/language.support/support.limits/support.limits.general/algorithm.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/functional.version.pass.cpp FAIL @@ -494,6 +518,11 @@ std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_len.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_ptr.pass.cpp:0 FAIL +# VSO-1168723 "Implicit copy assignment incorrectly not constexpr when subobject has explicit constexpr copy constructor" +std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp:0 FAIL +std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp:0 FAIL +std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp:0 FAIL + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -503,11 +532,6 @@ std/thread/macro.pass.cpp:1 FAIL std/depr/depr.c.headers/tgmath_h.pass.cpp:1 FAIL -# *** CLANG FEATURES NOT YET IMPLEMENTED *** -# P0960R3 "Allow initializing aggregates from a parenthesized list of values" -std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp:0 FAIL - - # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_fsizeddeallocation.pass.cpp:1 FAIL @@ -617,6 +641,10 @@ std/language.support/support.runtime/cstdlib.pass.cpp FAIL std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp SKIPPED std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp SKIPPED +# OS-29877133 "LDBL_DECIMAL_DIG missing from " +std/depr/depr.c.headers/float_h.pass.cpp:0 FAIL +std/language.support/support.limits/c.limits/cfloat.pass.cpp:0 FAIL + # *** LIKELY BOGUS TESTS *** # "error: _LIBCPP_VERSION not defined" @@ -746,8 +774,6 @@ std/containers/sequences/array/array.creation/to_array.pass.cpp:0 FAIL std/iterators/predef.iterators/insert.iterators/back.insert.iterator/types.pass.cpp FAIL std/iterators/predef.iterators/insert.iterators/front.insert.iterator/types.pass.cpp FAIL std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp FAIL -std/iterators/stream.iterators/ostream.iterator/types.pass.cpp FAIL -std/iterators/stream.iterators/ostreambuf.iterator/types.pass.cpp FAIL # Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex::_Ty', possible loss of data std/numerics/complex.number/cmplx.over/conj.pass.cpp:0 FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 4239de46b5b..b8e1d482c42 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -66,6 +66,12 @@ numerics\bit\bit.pow.two\log2p1.pass.cpp # test emits warning C4310: cast truncates constant value numerics\bit\bitops.rot\rotl.pass.cpp +# libc++ doesn't yet implement P1754R1 or P1964R2, so it expects an old value for `__cpp_lib_concepts` +language.support\support.limits\support.limits.general\concepts.version.pass.cpp + +# libc++ doesn't yet implement P1001R2, so it expects an old value for `__cpp_lib_execution` +language.support\support.limits\support.limits.general\execution.version.pass.cpp + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -252,6 +258,9 @@ utilities\function.objects\negators\not2.depr_in_cxx17.verify.cpp utilities\memory\allocator.traits\allocator.traits.members\allocate.verify.cpp utilities\memory\default.allocator\allocator.members\allocate.verify.cpp +# GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests +strings\string.view\string.view.io\stream_insert_decl_present.compile.pass.cpp + # *** MISSING STL FEATURES *** # C++20 P0355R7 " Calendars And Time Zones" @@ -464,6 +473,21 @@ utilities\variant\variant.variant\variant.ctor\T.pass.cpp # C++20 P0768R1 "Library Support for the Spaceship (Comparison) Operator" language.support\support.limits\support.limits.general\compare.version.pass.cpp +# C++20 P0784R7 "More constexpr containers" +utilities\memory\allocator.traits\allocator.traits.members\allocate.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\allocate_hint.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\construct.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\deallocate.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\destroy.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\max_size.pass.cpp +utilities\memory\allocator.traits\allocator.traits.members\select_on_container_copy_construction.pass.cpp +utilities\memory\default.allocator\allocator.globals\eq.pass.cpp +utilities\memory\default.allocator\allocator.members\allocate.pass.cpp +utilities\memory\specialized.algorithms\specialized.construct\construct_at.pass.cpp +utilities\memory\specialized.algorithms\specialized.destroy\destroy.pass.cpp +utilities\memory\specialized.algorithms\specialized.destroy\destroy_at.pass.cpp +utilities\memory\specialized.algorithms\specialized.destroy\destroy_n.pass.cpp + # C++20 P0896R4 "" language.support\support.limits\support.limits.general\algorithm.version.pass.cpp language.support\support.limits\support.limits.general\functional.version.pass.cpp @@ -494,6 +518,11 @@ utilities\meta\meta.unary\meta.unary.prop\is_constructible.pass.cpp containers\views\span.cons\ptr_len.pass.cpp containers\views\span.cons\ptr_ptr.pass.cpp +# VSO-1168723 "Implicit copy assignment incorrectly not constexpr when subobject has explicit constexpr copy constructor" +utilities\utility\pairs\pairs.pair\assign_pair.pass.cpp +utilities\utility\pairs\pairs.pair\assign_rv_pair.pass.cpp +utilities\utility\pairs\pairs.pair\assign_rv_pair_U_V.pass.cpp + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -503,11 +532,6 @@ thread\macro.pass.cpp depr\depr.c.headers\tgmath_h.pass.cpp -# *** CLANG FEATURES NOT YET IMPLEMENTED *** -# P0960R3 "Allow initializing aggregates from a parenthesized list of values" -utilities\tuple\tuple.tuple\tuple.creation\tuple_cat.pass.cpp - - # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? language.support\support.dynamic\new.delete\new.delete.array\sized_delete_array_fsizeddeallocation.pass.cpp @@ -617,6 +641,10 @@ language.support\support.runtime\cstdlib.pass.cpp thread\thread.threads\thread.thread.class\thread.thread.assign\move2.pass.cpp thread\thread.threads\thread.thread.class\thread.thread.member\join.pass.cpp +# OS-29877133 "LDBL_DECIMAL_DIG missing from " +depr\depr.c.headers\float_h.pass.cpp +language.support\support.limits\c.limits\cfloat.pass.cpp + # *** LIKELY BOGUS TESTS *** # "error: _LIBCPP_VERSION not defined" @@ -746,8 +774,6 @@ containers\sequences\array\array.creation\to_array.pass.cpp iterators\predef.iterators\insert.iterators\back.insert.iterator\types.pass.cpp iterators\predef.iterators\insert.iterators\front.insert.iterator\types.pass.cpp iterators\predef.iterators\insert.iterators\insert.iterator\types.pass.cpp -iterators\stream.iterators\ostream.iterator\types.pass.cpp -iterators\stream.iterators\ostreambuf.iterator\types.pass.cpp # Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex::_Ty', possible loss of data numerics\complex.number\cmplx.over\conj.pass.cpp From 40b5aac966caebf1060e2f9d1705ca4813a706c6 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 19 Oct 2020 18:14:18 -0700 Subject: [PATCH 08/56] Fix mis-formatted line in expected_results.txt --- tests/libcxx/expected_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index b98dcb3243b..c2cd5295e10 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -259,7 +259,7 @@ std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.c std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKIPPED # GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests -strings\string.view\string.view.io\stream_insert_decl_present.compile.pass.cpp +strings\string.view\string.view.io\stream_insert_decl_present.compile.pass.cpp SKIPPED # *** MISSING STL FEATURES *** From 16c00b2761892367eb78da81ad3f4eca10597880 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 19 Oct 2020 18:27:58 -0700 Subject: [PATCH 09/56] Fix bad separators in libcxx/expected_results --- tests/libcxx/expected_results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index c2cd5295e10..4ec759b4b00 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -259,7 +259,7 @@ std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.c std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKIPPED # GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests -strings\string.view\string.view.io\stream_insert_decl_present.compile.pass.cpp SKIPPED +std/strings/string.view/string.view.io/stream_insert_decl_present.compile.pass.cpp SKIPPED # *** MISSING STL FEATURES *** From c72c9fd2f43d76138ce982a6cc54866f478961d7 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Thu, 22 Oct 2020 19:05:42 -0700 Subject: [PATCH 10/56] Let's rewrite the test harness --- .../std_init_once_begin_initialize.obj | Bin 0 -> 223 bytes .../arm64ec/std_init_once_complete.obj | Bin 0 -> 208 bytes stl/inc/barrier | 198 ++++++++ stl/inc/latch | 101 ++++ stl/inc/semaphore | 311 ++++++++++++ stl/inc/stop_token | 398 +++++++++++++++ stl/src/dllmain_satellite.cpp | 16 + tests/CMakeLists.txt | 2 + tests/libcxx/CMakeLists.txt | 4 +- tests/libcxx/expected_results.txt | 129 ++--- tests/libcxx/lit.cfg | 25 + tests/libcxx/lit.site.cfg.in | 52 +- tests/libcxx/skipped_tests.txt | 129 ++--- tests/std/lit.site.cfg.in | 51 +- .../custom_format.py | 49 +- .../Dev09_056375_locale_cleanup/lit.local.cfg | 9 +- .../custom_format.py | 33 +- .../Dev09_172666_tr1_tuple_odr/lit.local.cfg | 9 +- .../custom_format.py | 26 +- .../GH_000545_include_compare/lit.local.cfg | 9 +- .../P0607R0_inline_variables/custom_format.py | 33 +- .../P0607R0_inline_variables/lit.local.cfg | 9 +- .../custom_format.py | 67 +-- .../lit.local.cfg | 11 +- .../custom_format.py | 33 +- .../lit.local.cfg | 9 +- tests/tr1/lit.site.cfg.in | 51 +- tests/utils/stl/test/config.py | 427 ++-------------- tests/utils/stl/test/features.py | 45 ++ tests/utils/stl/test/format.py | 479 ++++++++++-------- tests/utils/stl/test/params.py | 18 + tests/utils/stl/test/tests.py | 313 ++++++------ 32 files changed, 1909 insertions(+), 1137 deletions(-) create mode 100644 stl/aliases/arm64ec/std_init_once_begin_initialize.obj create mode 100644 stl/aliases/arm64ec/std_init_once_complete.obj create mode 100644 stl/inc/barrier create mode 100644 stl/inc/latch create mode 100644 stl/inc/semaphore create mode 100644 stl/inc/stop_token create mode 100644 stl/src/dllmain_satellite.cpp create mode 100644 tests/libcxx/lit.cfg create mode 100644 tests/utils/stl/test/features.py create mode 100644 tests/utils/stl/test/params.py diff --git a/stl/aliases/arm64ec/std_init_once_begin_initialize.obj b/stl/aliases/arm64ec/std_init_once_begin_initialize.obj new file mode 100644 index 0000000000000000000000000000000000000000..593e6c144ab5e6aa52dbeb9f4e318a275dc0154a GIT binary patch literal 223 zcmZ=<#>nu03QN2V0|Nsq5QBhTN>OTZNm(j{hlAu|U~ovz&n?i)Oi9cC%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTM0=dlMy7wj3mOq;0ff#$7kji#CzstmiXr-r#hvk lXXb%8nTa`>RjE+f`1snu03QN2V0|Nsq5QBhTN>OTZNm(j{hlAu|U~ovz&n?i)Oi9cC%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTN+6ulMy7wj3mOqUV7nh{OX96YT^MSJQAeVrp0TqrXJOBUy literal 0 HcmV?d00001 diff --git a/stl/inc/barrier b/stl/inc/barrier new file mode 100644 index 00000000000..2258cfe26de --- /dev/null +++ b/stl/inc/barrier @@ -0,0 +1,198 @@ +// barrier standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _BARRIER_ +#define _BARRIER_ +#include +#if _STL_COMPILER_PREPROCESSOR + +#ifdef _M_CEE_PURE +#error is not supported when compiling with /clr:pure. +#endif // _M_CEE_PURE + +#if !_HAS_CXX20 +#pragma message("The contents of are available only with C++20 or later.") +#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv + +#include +#include +#include +#include + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +_STD_BEGIN + +struct _No_completion_function { + void operator()() noexcept {} +}; + +template +class barrier; + +inline constexpr ptrdiff_t _Barrier_arrival_token_mask = 1; +inline constexpr ptrdiff_t _Barrier_value_mask = ~_Barrier_arrival_token_mask; +inline constexpr ptrdiff_t _Barrier_value_shift = 1; +inline constexpr ptrdiff_t _Barrier_invalid_token = 0; +inline constexpr ptrdiff_t _Barrier_value_step = 1 << _Barrier_value_shift; +inline constexpr ptrdiff_t _Barrier_max = (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 2)) - 1; + +template +class _Arrival_token { +public: + _Arrival_token(_Arrival_token&& _Other) noexcept { + _Value = _Other._Value; + _Other._Value = _Barrier_invalid_token; + } + + _Arrival_token& operator=(_Arrival_token&& _Other) noexcept { + _Value = _Other._Value; + _Other._Value = _Barrier_invalid_token; + return *this; + } + +private: + explicit _Arrival_token(ptrdiff_t _Value_) noexcept : _Value(_Value_) {} + friend barrier<_Completion_function>; + + ptrdiff_t _Value; +}; + +template +class barrier { +public: + static_assert( +#ifndef __cpp_noexcept_function_type + is_function_v> || +#endif // __cpp_noexcept_function_type + is_nothrow_invocable_v<_Completion_function&>, + "N4861 [thread.barrier.class]/5: is_nothrow_invocable_v shall be true"); + + using arrival_token = _Arrival_token<_Completion_function>; + + constexpr explicit barrier( + const ptrdiff_t _Expected, _Completion_function _Fn = _Completion_function()) noexcept /* strengthened */ + : _Val(_One_then_variadic_args_t{}, _STD move(_Fn), _Expected << _Barrier_value_shift) { + _STL_VERIFY(_Val._Myval2._Current.load(memory_order_relaxed) >= 0, + "Precondition: expected >= 0 and expected <= max() (N4861 [thread.barrier.class]/9)"); + } + + barrier(const barrier&) = delete; + barrier& operator=(const barrier&) = delete; + + _NODISCARD static constexpr ptrdiff_t(max)() noexcept { + return _Barrier_max; + } + + _NODISCARD arrival_token arrive(ptrdiff_t _Update = 1) noexcept /* strengthened */ { + // Shifting before precondition check, so that exceeding max() will trigger precondition check too + _Update <<= _Barrier_value_shift; + _STL_VERIFY(_Update > 0, "Precondition: update > 0 (N4861 [thread.barrier.class]/12)"); + // TRANSITION, GH-1133: should be memory_order_release + ptrdiff_t _Current = _Val._Myval2._Current.fetch_sub(_Update) - _Update; + _STL_VERIFY(_Current >= 0, "Precondition: update is less than or equal to the expected count " + "for the current barrier phase (N4861 [thread.barrier.class]/12)"); + if ((_Current & _Barrier_value_mask) == 0) { + // TRANSITION, GH-1133: should have this fence: + // atomic_thread_fence(memory_order_acquire); + _Completion(_Current); + } + // Embedding this into the token to provide an additional correctness check that the token is from the same + // barrier and wasn't used. All bits of this fit, as barrier should be aligned to at least the size of an + // atomic counter. + return arrival_token{(_Current & _Barrier_arrival_token_mask) | reinterpret_cast(this)}; + } + + void wait(arrival_token&& _Arrival) const noexcept /* strengthened */ { + _STL_VERIFY((_Arrival._Value & _Barrier_value_mask) == reinterpret_cast(this), + "Preconditions: arrival is associated with the phase synchronization point for the current phase " + "or the immediately preceding phase of the same barrier object (N4861 [thread.barrier.class]/19)"); + const ptrdiff_t _Arrival_value = _Arrival._Value & _Barrier_arrival_token_mask; + _Arrival._Value = _Barrier_invalid_token; + for (;;) { + // TRANSITION, GH-1133: should be memory_order_acquire + const ptrdiff_t _Current = _Val._Myval2._Current.load(); + _STL_VERIFY(_Current >= 0, "Invariant counter >= 0, possibly caused by preconditions violation " + "(N4861 [thread.barrier.class]/12)"); + if ((_Current & _Barrier_arrival_token_mask) != _Arrival_value) { + break; + } + _Val._Myval2._Current.wait(_Current, memory_order_relaxed); + } + } + + void arrive_and_wait() noexcept /* strengthened */ { + // TRANSITION, GH-1133: should be memory_order_acq_rel + ptrdiff_t _Current = _Val._Myval2._Current.fetch_sub(_Barrier_value_step) - _Barrier_value_step; + const ptrdiff_t _Arrival = _Current & _Barrier_arrival_token_mask; + _STL_VERIFY(_Current >= 0, "Precondition: update is less than or equal to the expected count " + "for the current barrier phase (N4861 [thread.barrier.class]/12)"); + if ((_Current & _Barrier_value_mask) == 0) { + _Completion(_Current); + return; + } + + for (;;) { + _Val._Myval2._Current.wait(_Current, memory_order_relaxed); + // TRANSITION, GH-1133: should be memory_order_acquire + _Current = _Val._Myval2._Current.load(); + _STL_VERIFY(_Current >= 0, "Invariant counter >= 0, possibly caused by preconditions violation " + "(N4861 [thread.barrier.class]/12)"); + if ((_Current & _Barrier_arrival_token_mask) != _Arrival) { + break; + } + } + } + + void arrive_and_drop() noexcept /* strengthened */ { + const ptrdiff_t _Rem_count = + _Val._Myval2._Total.fetch_sub(_Barrier_value_step, memory_order_relaxed) - _Barrier_value_step; + _STL_VERIFY(_Rem_count >= 0, "Precondition: The expected count for the current barrier phase " + "is greater than zero (N4861 [thread.barrier.class]/24) " + "(checked initial expected count, which is not less than the current)"); + (void) arrive(1); + } + +private: + void _Completion(const ptrdiff_t _Current) noexcept { + const ptrdiff_t _Rem_count = _Val._Myval2._Total.load(memory_order_relaxed); + _STL_VERIFY(_Rem_count >= 0, "Invariant: initial expected count less than zero, " + "possibly caused by preconditions violation " + "(N4861 [thread.barrier.class]/24)"); + _Val._Get_first()(); + const ptrdiff_t _New_phase_count = _Rem_count | ((_Current + 1) & _Barrier_arrival_token_mask); + // TRANSITION, GH-1133: should be memory_order_release + _Val._Myval2._Current.store(_New_phase_count); + _Val._Myval2._Current.notify_all(); + } + + struct _Counter_t { + constexpr explicit _Counter_t(ptrdiff_t _Initial) : _Current(_Initial), _Total(_Initial) {} + // wait(arrival_token&&) accepts a token from the current phase or the immediately preceding phase; this means + // we can track which phase is the current phase using 1 bit which alternates between each phase. For this + // purpose we use the low order bit of _Current. + atomic _Current; + atomic _Total; + }; + + _Compressed_pair<_Completion_function, _Counter_t> _Val; +}; + +_STD_END + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // ^^^ _HAS_CXX20 ^^^ + +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _BARRIER_ diff --git a/stl/inc/latch b/stl/inc/latch new file mode 100644 index 00000000000..3743af76484 --- /dev/null +++ b/stl/inc/latch @@ -0,0 +1,101 @@ +// latch standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _LATCH_ +#define _LATCH_ +#include +#if _STL_COMPILER_PREPROCESSOR + +#ifdef _M_CEE_PURE +#error is not supported when compiling with /clr:pure. +#endif // _M_CEE_PURE + +#if !_HAS_CXX20 +#pragma message("The contents of are available only with C++20 or later.") +#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv + +#include +#include + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +_STD_BEGIN + +class latch { +public: + _NODISCARD static constexpr ptrdiff_t(max)() noexcept { + return (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 1)) - 1; + } + + constexpr explicit latch(const ptrdiff_t _Expected) noexcept /* strengthened */ : _Counter{_Expected} { + _STL_VERIFY(_Expected >= 0, "Precondition: expected >= 0 (N4861 [thread.latch.class]/4)"); + } + + latch(const latch&) = delete; + latch& operator=(const latch&) = delete; + + void count_down(const ptrdiff_t _Update = 1) noexcept /* strengthened */ { + _STL_VERIFY(_Update >= 0, "Precondition: update >= 0 (N4861 [thread.latch.class]/7)"); + // TRANSITION, GH-1133: should be memory_order_release + const ptrdiff_t _Current = _Counter.fetch_sub(_Update) - _Update; + if (_Current == 0) { + _Counter.notify_all(); + } else { + _STL_VERIFY(_Current >= 0, "Precondition: update <= counter (N4861 [thread.latch.class]/7)"); + } + } + + _NODISCARD bool try_wait() const noexcept { + // TRANSITION, GH-1133: should be memory_order_acquire + return _Counter.load() == 0; + } + + void wait() const noexcept /* strengthened */ { + for (;;) { + // TRANSITION, GH-1133: should be memory_order_acquire + const ptrdiff_t _Current = _Counter.load(); + if (_Current == 0) { + return; + } else { + _STL_VERIFY(_Current > 0, "Invariant counter >= 0, possibly caused by preconditions violation " + "(N4861 [thread.latch.class]/7)"); + } + _Counter.wait(_Current, memory_order_relaxed); + } + } + + void arrive_and_wait(const ptrdiff_t _Update = 1) noexcept /* strengthened */ { + _STL_VERIFY(_Update >= 0, "Precondition: update >= 0 (N4861 [thread.latch.class]/7)"); + // TRANSITION, GH-1133: should be memory_order_acq_rel + const ptrdiff_t _Current = _Counter.fetch_sub(_Update) - _Update; + if (_Current == 0) { + _Counter.notify_all(); + } else { + _STL_VERIFY(_Current > 0, "Precondition: update <= counter (N4861 [thread.latch.class]/7)"); + _Counter.wait(_Current, memory_order_relaxed); + wait(); + } + } + +private: + atomic _Counter; +}; + +_STD_END + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // ^^^ _HAS_CXX20 ^^^ + +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _LATCH_ diff --git a/stl/inc/semaphore b/stl/inc/semaphore new file mode 100644 index 00000000000..0845bdf00f3 --- /dev/null +++ b/stl/inc/semaphore @@ -0,0 +1,311 @@ +// semaphore standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _SEMAPHORE_ +#define _SEMAPHORE_ +#include +#if _STL_COMPILER_PREPROCESSOR + +#ifdef _M_CEE_PURE +#error is not supported when compiling with /clr:pure. +#endif // _M_CEE_PURE + +#if !_HAS_CXX20 +#pragma message("The contents of are available only with C++20 or later.") +#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv + +#include +#include +#include + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +_STD_BEGIN + +template +_NODISCARD unsigned long long _Semaphore_deadline(const chrono::duration<_Rep, _Period>& _Rel_time) { + return __std_atomic_wait_get_deadline( + chrono::duration_cast>(_Rel_time).count()); +} + +template +_NODISCARD unsigned long _Semaphore_remaining_timeout(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + const auto _Now = _Clock::now(); + if (_Now >= _Abs_time) { + return 0; + } + + const auto _Rel_time = chrono::ceil(_Abs_time - _Now); + static constexpr chrono::milliseconds _Ten_days{chrono::hours{24 * 10}}; + static_assert(_Ten_days.count() < ULONG_MAX, "Bad sizing assumption"); + if (_Rel_time >= _Ten_days) { + return static_cast(_Ten_days.count()); + } + + return static_cast(_Rel_time.count()); +} + +inline constexpr ptrdiff_t _Semaphore_max = (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 1)) - 1; + +template +class counting_semaphore { +public: + _NODISCARD static constexpr ptrdiff_t(max)() noexcept { + return _Least_max_value; + } + + constexpr explicit counting_semaphore(const ptrdiff_t _Desired) noexcept /* strengthened */ + : _Counter(_Desired) { + _STL_VERIFY(_Desired >= 0 && _Desired <= _Least_max_value, + "Precondition: desired >= 0, and desired <= max() (N4861 [thread.sema.cnt]/5)"); + } + + counting_semaphore(const counting_semaphore&) = delete; + counting_semaphore& operator=(const counting_semaphore&) = delete; + + void release(ptrdiff_t _Update = 1) noexcept /* strengthened */ { + if (_Update == 0) { + return; + } + _STL_VERIFY(_Update > 0 && _Update <= _Least_max_value, + "Precondition: update >= 0, and update <= max() - counter (N4861 [thread.sema.cnt]/8)"); + + // We need to notify (wake) at least _Update waiting threads. + // Errors towards waking more cannot be always avoided, but they are performance issues. + // Errors towards waking fewer must be avoided, as they are correctness issues. + + // release thread: Increment semaphore counter, then load waiting counter; + // acquire thread: Increment waiting counter, then load semaphore counter; + + // memory_order_seq_cst for all four operations guarantees that the release thread loads + // the incremented value, or the acquire thread loads the incremented value, or both, but not neither. + // memory_order_seq_cst might be superfluous for some hardware mappings of the C++ memory model, + // but from the point of view of the C++ memory model itself it is needed; weaker orders don't work. + + const ptrdiff_t _Prev = _Counter.fetch_add(static_cast(_Update)); + _STL_VERIFY(_Prev + _Update > 0 && _Prev + _Update <= _Least_max_value, + "Precondition: update <= max() - counter (N4861 [thread.sema.cnt]/8)"); + + const ptrdiff_t _Waiting_upper_bound = _Waiting.load(); + + if (_Waiting_upper_bound == 0) { + // Definitely no one is waiting + } else if (_Waiting_upper_bound <= _Update) { + // No more waiting threads than update, can wake everyone. + _Counter.notify_all(); + } else { + // Wake at most _Update. Though repeated notify_one() is somewhat less efficient than single notify_all(), + // the amount of OS calls is still the same; the benefit from trying not to wake unnecessary threads + // is expected to be greater than the loss on extra calls and atomic operations. + for (; _Update != 0; --_Update) { + _Counter.notify_one(); + } + } + } + + void _Wait(const unsigned long _Remaining_timeout) noexcept { + // See the comment in release() + _Waiting.fetch_add(1); + ptrdiff_t _Current = _Counter.load(); + if (_Current == 0) { + __std_atomic_wait_direct(&_Counter, &_Current, sizeof(_Current), _Remaining_timeout); + } + _Waiting.fetch_sub(1, memory_order_relaxed); + } + + void acquire() noexcept /* strengthened */ { + ptrdiff_t _Current = _Counter.load(memory_order_relaxed); + for (;;) { + while (_Current == 0) { + _Wait(_Atomic_wait_no_timeout); + _Current = _Counter.load(memory_order_relaxed); + } + _STL_VERIFY(_Current > 0 && _Current <= _Least_max_value, + "Invariant: counter >= 0, and counter <= max() " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + + // "happens after release" ordering is provided by this CAS, so loads and waits can be relaxed + if (_Counter.compare_exchange_weak(_Current, _Current - 1)) { + return; + } + } + } + + _NODISCARD bool try_acquire() noexcept { + ptrdiff_t _Current = _Counter.load(); + if (_Current == 0) { + return false; + } + _STL_VERIFY(_Current > 0 && _Current <= _Least_max_value, + "Invariant: counter >= 0, and counter <= max() " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + + return _Counter.compare_exchange_weak(_Current, _Current - 1); + } + + template + _NODISCARD bool try_acquire_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + auto _Deadline = _Semaphore_deadline(_Rel_time); + ptrdiff_t _Current = _Counter.load(memory_order_relaxed); + for (;;) { + while (_Current == 0) { + const auto _Remaining_timeout = __std_atomic_wait_get_remaining_timeout(_Deadline); + if (_Remaining_timeout == 0) { + return false; + } + _Wait(_Remaining_timeout); + _Current = _Counter.load(memory_order_relaxed); + } + _STL_VERIFY(_Current > 0 && _Current <= _Least_max_value, + "Invariant: counter >= 0, and counter <= max() " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + + // "happens after release" ordering is provided by this CAS, so loads and waits can be relaxed + if (_Counter.compare_exchange_weak(_Current, _Current - 1)) { + return true; + } + } + } + + template + _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + ptrdiff_t _Current = _Counter.load(memory_order_relaxed); + for (;;) { + while (_Current == 0) { + const unsigned long _Remaining_timeout = _Semaphore_remaining_timeout(_Abs_time); + if (_Remaining_timeout == 0) { + return false; + } + _Wait(_Remaining_timeout); + _Current = _Counter.load(memory_order_relaxed); + } + _STL_VERIFY(_Current > 0 && _Current <= _Least_max_value, + "Invariant: counter >= 0, and counter <= max() " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + + // "happens after release" ordering is provided by this CAS, so loads and waits can be relaxed + if (_Counter.compare_exchange_weak(_Current, _Current - 1)) { + return true; + } + } + } + +private: + atomic _Counter; + atomic _Waiting; +}; + +template <> +class counting_semaphore<1> { +public: + _NODISCARD static constexpr ptrdiff_t(max)() noexcept { + return 1; + } + + constexpr explicit counting_semaphore(const ptrdiff_t _Desired) noexcept /* strengthened */ + : _Counter(static_cast(_Desired)) { + _STL_VERIFY((_Desired & ~1) == 0, "Precondition: desired >= 0, and desired <= max() " + "(N4861 [thread.sema.cnt]/5)"); + } + + counting_semaphore(const counting_semaphore&) = delete; + counting_semaphore& operator=(const counting_semaphore&) = delete; + + void release(const ptrdiff_t _Update = 1) noexcept /* strengthened */ { + if (_Update == 0) { + return; + } + _STL_VERIFY(_Update == 1, "Precondition: update >= 0, " + "and update <= max() - counter (N4861 [thread.sema.cnt]/8)"); + // TRANSITION, GH-1133: should be memory_order_release + _Counter.store(1); + _Counter.notify_one(); + } + + void acquire() noexcept /* strengthened */ { + for (;;) { + // "happens after release" ordering is provided by this exchange, so loads and waits can be relaxed + // TRANSITION, GH-1133: should be memory_order_acquire + unsigned char _Prev = _Counter.exchange(0); + if (_Prev == 1) { + break; + } + _STL_VERIFY(_Prev == 0, "Invariant: semaphore counter is non-negative and doesn't exceed max(), " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + _Counter.wait(0, memory_order_relaxed); + } + } + + _NODISCARD bool try_acquire() noexcept { + // TRANSITION, GH-1133: should be memory_order_acquire + unsigned char _Prev = _Counter.exchange(0); + _STL_VERIFY((_Prev & ~1) == 0, "Invariant: semaphore counter is non-negative and doesn't exceed max(), " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + return reinterpret_cast(_Prev); + } + + template + _NODISCARD bool try_acquire_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + auto _Deadline = _Semaphore_deadline(_Rel_time); + for (;;) { + // "happens after release" ordering is provided by this exchange, so loads and waits can be relaxed + // TRANSITION, GH-1133: should be memory_order_acquire + unsigned char _Prev = _Counter.exchange(0); + if (_Prev == 1) { + return true; + } + _STL_VERIFY(_Prev == 0, "Invariant: semaphore counter is non-negative and doesn't exceed max(), " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + const auto _Remaining_timeout = __std_atomic_wait_get_remaining_timeout(_Deadline); + if (_Remaining_timeout == 0) { + return false; + } + __std_atomic_wait_direct(&_Counter, &_Prev, sizeof(_Prev), _Remaining_timeout); + } + } + + template + _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + for (;;) { + // "happens after release" ordering is provided by this exchange, so loads and waits can be relaxed + // TRANSITION, GH-1133: should be memory_order_acquire + unsigned char _Prev = _Counter.exchange(0); + if (_Prev == 1) { + return true; + } + _STL_VERIFY(_Prev == 0, "Invariant: semaphore counter is non-negative and doesn't exceed max(), " + "possibly caused by preconditions violation (N4861 [thread.sema.cnt]/8)"); + + const unsigned long _Remaining_timeout = _Semaphore_remaining_timeout(_Abs_time); + if (_Remaining_timeout == 0) { + return false; + } + + __std_atomic_wait_direct(&_Counter, &_Prev, sizeof(_Prev), _Remaining_timeout); + } + } + +private: + atomic _Counter; +}; + +using binary_semaphore = counting_semaphore<1>; + +_STD_END + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // ^^^ _HAS_CXX20 ^^^ + +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _SEMAPHORE_ diff --git a/stl/inc/stop_token b/stl/inc/stop_token new file mode 100644 index 00000000000..ac4bc775af4 --- /dev/null +++ b/stl/inc/stop_token @@ -0,0 +1,398 @@ +// stop_token standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _STOP_TOKEN_ +#define _STOP_TOKEN_ +#include +#if _STL_COMPILER_PREPROCESSOR + +#if !_HAS_CXX20 +#pragma message("The contents of are available only with C++20 or later.") +#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv + +#include +#include +#include + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +_STD_BEGIN +struct nostopstate_t { + explicit nostopstate_t() = default; +}; + +inline constexpr nostopstate_t nostopstate{}; + +struct _Stop_state; +class stop_token; + +class _Stop_callback_base { + friend _Stop_state; + +private: + using _Callback_fn = void(__cdecl*)(_Stop_callback_base*) _NOEXCEPT_FNPTR; + +public: + explicit _Stop_callback_base(const _Callback_fn _Fn_) noexcept : _Fn{_Fn_} {} + + _Stop_callback_base(const _Stop_callback_base&) = delete; + _Stop_callback_base& operator=(const _Stop_callback_base&) = delete; + +protected: + // if _Token is _Stop_requested, calls the callback; + // otherwise, inserts *this into the callback list if stop is possible + inline void _Attach(const stop_token& _Token) noexcept; + inline void _Attach(stop_token&& _Token) noexcept; + + // if *this is in a callback list, removes it + inline void _Detach() noexcept; + +private: + template + void _Do_attach(conditional_t<_Transfer_ownership, _Stop_state*&, _Stop_state* const> _State) noexcept; + +protected: + _Stop_state* _Parent = nullptr; + _Stop_callback_base* _Next = nullptr; + _Stop_callback_base* _Prev = nullptr; + _Callback_fn _Fn; +}; + +struct _Stop_state { + atomic _Stop_tokens = 1; // plus one shared by all stop_sources + atomic _Stop_sources = 2; // plus the low order bit is the stop requested bit + _Locked_pointer<_Stop_callback_base> _Callbacks; + // always uses relaxed operations; ordering provided by the _Callbacks lock + // (atomic just to get wait/notify support) + atomic _Current_callback = nullptr; + _Thrd_id_t _Stopping_thread = 0; + + _NODISCARD bool _Stop_requested() const noexcept { + return (_Stop_sources.load() & uint32_t{1}) != 0; + } + + _NODISCARD bool _Stop_possible() const noexcept { + return _Stop_sources.load() != 0; + } + + _NODISCARD bool _Request_stop() noexcept { + // Attempts to request stop and call callbacks, returns whether request was successful + if ((_Stop_sources.fetch_or(uint32_t{1}) & uint32_t{1}) != 0) { + // another thread already requested + return false; + } + + _Stopping_thread = _Thrd_id(); + for (;;) { + auto _Head = _Callbacks._Lock_and_load(); + _Current_callback.store(_Head, memory_order_relaxed); + _Current_callback.notify_all(); + if (_Head == nullptr) { + _Callbacks._Store_and_unlock(nullptr); + return true; + } + + const auto _Next = _STD exchange(_Head->_Next, nullptr); + _STL_INTERNAL_CHECK(_Head->_Prev == nullptr); + if (_Next != nullptr) { + _Next->_Prev = nullptr; + } + + _Callbacks._Store_and_unlock(_Next); // unlock before running _Head so other registrations + // can detach without blocking on the callback + + _Head->_Fn(_Head); // might destroy *_Head + } + } +}; + +class stop_source; + +class stop_token { + friend stop_source; + friend _Stop_callback_base; + +public: + stop_token() noexcept : _State{} {} + stop_token(const stop_token& _Other) noexcept : _State{_Other._State} { + const auto _Local = _State; + if (_Local != nullptr) { + _Local->_Stop_tokens.fetch_add(1, memory_order_relaxed); + } + } + + stop_token(stop_token&& _Other) noexcept : _State{_STD exchange(_Other._State, nullptr)} {} + stop_token& operator=(const stop_token& _Other) noexcept { + stop_token{_Other}.swap(*this); + return *this; + } + + stop_token& operator=(stop_token&& _Other) noexcept { + stop_token{_STD move(_Other)}.swap(*this); + return *this; + } + + ~stop_token() { + const auto _Local = _State; + if (_Local != nullptr) { + if (_Local->_Stop_tokens.fetch_sub(1, memory_order_acq_rel) == 1) { + delete _Local; + } + } + } + + void swap(stop_token& _Other) noexcept { + _STD swap(_State, _Other._State); + } + + _NODISCARD bool stop_requested() const noexcept { + const auto _Local = _State; + return _Local != nullptr && _Local->_Stop_requested(); + } + + _NODISCARD bool stop_possible() const noexcept { + const auto _Local = _State; + return _Local != nullptr && _Local->_Stop_possible(); + } + + _NODISCARD friend bool operator==(const stop_token& _Lhs, const stop_token& _Rhs) noexcept = default; + + friend void swap(stop_token& _Lhs, stop_token& _Rhs) noexcept { + _STD swap(_Lhs._State, _Rhs._State); + } + +private: + explicit stop_token(_Stop_state* const _State_) : _State{_State_} {} + + _Stop_state* _State; +}; + +class stop_source { +public: + stop_source() : _State{new _Stop_state} {} + explicit stop_source(nostopstate_t) noexcept : _State{} {} + stop_source(const stop_source& _Other) noexcept : _State{_Other._State} { + const auto _Local = _State; + if (_Local != nullptr) { + _Local->_Stop_sources.fetch_add(2, memory_order_relaxed); + } + } + + stop_source(stop_source&& _Other) noexcept : _State{_STD exchange(_Other._State, nullptr)} {} + stop_source& operator=(const stop_source& _Other) noexcept { + stop_source{_Other}.swap(*this); + return *this; + } + + stop_source& operator=(stop_source&& _Other) noexcept { + stop_source{_STD move(_Other)}.swap(*this); + return *this; + } + + ~stop_source() { + const auto _Local = _State; + if (_Local != nullptr) { + if ((_Local->_Stop_sources.fetch_sub(2, memory_order_acq_rel) >> 1) == 1) { + if (_Local->_Stop_tokens.fetch_sub(1, memory_order_acq_rel) == 1) { + delete _Local; + } + } + } + } + + void swap(stop_source& _Other) noexcept { + _STD swap(_State, _Other._State); + } + + _NODISCARD stop_token get_token() const noexcept { + const auto _Local = _State; + if (_Local != nullptr) { + _Local->_Stop_tokens.fetch_add(1, memory_order_relaxed); + } + + return stop_token{_Local}; + } + + _NODISCARD bool stop_requested() const noexcept { + const auto _Local = _State; + return _Local != nullptr && _Local->_Stop_requested(); + } + + _NODISCARD bool stop_possible() const noexcept { + return _State != nullptr; + } + + bool request_stop() noexcept { + const auto _Local = _State; + return _Local && _Local->_Request_stop(); + } + + _NODISCARD friend bool operator==(const stop_source& _Lhs, const stop_source& _Rhs) noexcept = default; + + friend void swap(stop_source& _Lhs, stop_source& _Rhs) noexcept { + _STD swap(_Lhs._State, _Rhs._State); + } + +private: + _Stop_state* _State; +}; + +template +void _Stop_callback_base::_Do_attach( + conditional_t<_Transfer_ownership, _Stop_state*&, _Stop_state* const> _State_raw) noexcept { + const auto _State = _State_raw; // avoid an indirection in all of the below + if (_State == nullptr) { + return; + } + + // fast path check if the state is already known + auto _Local_sources = _State->_Stop_sources.load(); + if ((_Local_sources & uint32_t{1}) != 0) { + // stop already requested + _Fn(this); + return; + } + + if (_Local_sources == 0) { + return; // stop not possible + } + + // fast path doesn't know, so try to insert + auto _Head = _State->_Callbacks._Lock_and_load(); + // recheck the state in case it changed while we were waiting to acquire the lock + _Local_sources = _State->_Stop_sources.load(); + if ((_Local_sources & uint32_t{1}) != 0) { + // stop already requested + _State->_Callbacks._Store_and_unlock(_Head); + _Fn(this); + return; + } + + if (_Local_sources != 0) { + // stop possible, do the insert + _Parent = _State; + _Next = _Head; + if constexpr (_Transfer_ownership) { + _State_raw = nullptr; + } else { + _State->_Stop_tokens.fetch_add(1, memory_order_relaxed); + } + + if (_Head != nullptr) { + _Head->_Prev = this; + } + + _Head = this; + } + + _State->_Callbacks._Store_and_unlock(_Head); +} + +inline void _Stop_callback_base::_Attach(const stop_token& _Token) noexcept { + this->_Do_attach(_Token._State); +} + +inline void _Stop_callback_base::_Attach(stop_token&& _Token) noexcept { + this->_Do_attach(_Token._State); +} + +inline void _Stop_callback_base::_Detach() noexcept { + stop_token _Token{_Parent}; // transfers ownership + if (_Token._State == nullptr) { + // callback was never inserted into the list + return; + } + + auto _Head = _Token._State->_Callbacks._Lock_and_load(); + if (this == _Head) { + // we are still in the list, so the callback is not being request_stop'd + const auto _Local_next = _Next; + if (_Local_next != nullptr) { + _Local_next->_Prev = nullptr; + } + + _STL_INTERNAL_CHECK(_Prev == nullptr); + _Token._State->_Callbacks._Store_and_unlock(_Next); + return; + } + + const auto _Local_prev = _Prev; + if (_Local_prev != nullptr) { + // we are still in the list, so the callback is not being request_stop'd, and there is at least one other + // callback still registered + const auto _Local_next = _Next; + if (_Local_next != nullptr) { + _Next->_Prev = _Local_prev; + } + + _Prev->_Next = _Local_next; + _Token._State->_Callbacks._Store_and_unlock(_Head); + return; + } + + // we aren't in the callback list even though we were added to it, so the stop requesting thread is attempting to + // call the callback + _STL_INTERNAL_CHECK((_Token._State->_Stop_sources.load() & uint32_t{1}) != 0); + if (_Token._State->_Current_callback.load(memory_order_acquire) != this + || _Token._State->_Stopping_thread == _Thrd_id()) { + // the callback is done or the dtor is being recursively reentered, do not block + _Token._State->_Callbacks._Store_and_unlock(_Head); + return; + } + + // the callback is being executed by another thread, block until it is complete + _Token._State->_Callbacks._Store_and_unlock(_Head); + _Token._State->_Current_callback.wait(this, memory_order_acquire); +} + +template +class stop_callback : public _Stop_callback_base { +public: + using callback_type = _Callback; + + template , int> = 0> + explicit stop_callback(const stop_token& _Token, _CbInitTy&& _Cb_) noexcept( + is_nothrow_constructible_v<_Callback, _CbInitTy>) + : _Stop_callback_base{_Invoke_by_stop}, _Cb(_STD forward<_CbInitTy>(_Cb_)) { + _Attach(_Token); + } + + template , int> = 0> + explicit stop_callback(stop_token&& _Token, _CbInitTy&& _Cb_) noexcept( + is_nothrow_constructible_v<_Callback, _CbInitTy>) + : _Stop_callback_base{_Invoke_by_stop}, _Cb(_STD forward<_CbInitTy>(_Cb_)) { + _Attach(_STD move(_Token)); + } + + ~stop_callback() { + _Detach(); + } + +private: + static void __cdecl _Invoke_by_stop(_Stop_callback_base* const _This) noexcept // terminates + { + _STD forward<_Callback>(static_cast(_This)->_Cb)(); + } + + _Callback _Cb; +}; + +template +stop_callback(stop_token, _Callback) -> stop_callback<_Callback>; + +_STD_END +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // _HAS_CXX20 +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _STOP_TOKEN_ diff --git a/stl/src/dllmain_satellite.cpp b/stl/src/dllmain_satellite.cpp new file mode 100644 index 00000000000..af2e024c1fe --- /dev/null +++ b/stl/src/dllmain_satellite.cpp @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +// DllMain for 'satellite' DLLs which don't need TLS. + +extern "C" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID) { + if (ul_reason_for_call == DLL_PROCESS_ATTACH) { + if (!DisableThreadLibraryCalls(hModule)) { + return FALSE; + } + } + + return TRUE; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b8059d68cd6..60c9ee58a2a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,8 @@ set(STL_TESTED_HEADERS_DIR "${STL_BUILD_ROOT}/inc") set(LLVM_PROJECT_SOURCE_DIR "${STL_SOURCE_DIR}/llvm-project" CACHE PATH "Location of the llvm-project source tree") +set(LIBCXX_SOURCE_DIR "${LLVM_PROJECT_SOURCE_DIR}/libcxx" CACHE PATH + "Location of the libcxx source tree") add_subdirectory(libcxx) add_subdirectory(std) diff --git a/tests/libcxx/CMakeLists.txt b/tests/libcxx/CMakeLists.txt index 3272b95ff78..215f9cedd27 100644 --- a/tests/libcxx/CMakeLists.txt +++ b/tests/libcxx/CMakeLists.txt @@ -3,14 +3,12 @@ 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( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) -set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") +set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg.py\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") set_property(GLOBAL APPEND_STRING PROPERTY STL_LIT_CONFIG_MAP ${LIBCXX_LIT_CONFIG_MAP}) set_property(GLOBAL APPEND PROPERTY STL_LIT_TEST_DIRS "${LIBCXX_SOURCE_DIR}/test/std") diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 366bc6b380e..33115b7aed8 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -49,6 +49,7 @@ std/containers/unord/unord.map/unord.map.modifiers/insert_and_emplace_allocator_ std/containers/unord/unord.set/insert_and_emplace_allocator_requirements.pass.cpp FAIL # libc++ doesn't yet implement P1423R3, so it expects an old value for `__cpp_lib_char8_t` +std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/istream.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/limits.version.pass.cpp FAIL @@ -65,6 +66,7 @@ std/numerics/bit/bit.pow.two/log2p1.pass.cpp FAIL # test emits warning C4310: cast truncates constant value std/numerics/bit/bitops.rot/rotl.pass.cpp:0 FAIL + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" # rapid-cxx-test.hpp uses pragma system_header @@ -252,9 +254,6 @@ std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKI # *** MISSING STL FEATURES *** -# C++20 P0019R8 "atomic_ref" -std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp FAIL - # C++20 P0355R7 " Calendars And Time Zones" std/utilities/time/days.pass.cpp FAIL std/utilities/time/months.pass.cpp FAIL @@ -471,26 +470,6 @@ std/language.support/support.limits/support.limits.general/functional.version.pa std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/memory.version.pass.cpp FAIL -# C++20 P1135R6 "The C++20 Synchronization Library" -std/thread/thread.barrier/arrive.pass.cpp FAIL -std/thread/thread.barrier/arrive_and_drop.pass.cpp FAIL -std/thread/thread.barrier/arrive_and_wait.pass.cpp FAIL -std/thread/thread.barrier/completion.pass.cpp FAIL -std/thread/thread.barrier/max.pass.cpp FAIL -std/thread/thread.barrier/version.pass.cpp FAIL -std/thread/thread.latch/arrive_and_wait.pass.cpp FAIL -std/thread/thread.latch/count_down.pass.cpp FAIL -std/thread/thread.latch/max.pass.cpp FAIL -std/thread/thread.latch/try_wait.pass.cpp FAIL -std/thread/thread.latch/version.pass.cpp FAIL -std/thread/thread.semaphore/acquire.pass.cpp FAIL -std/thread/thread.semaphore/binary.pass.cpp FAIL -std/thread/thread.semaphore/max.pass.cpp FAIL -std/thread/thread.semaphore/release.pass.cpp FAIL -std/thread/thread.semaphore/timed.pass.cpp FAIL -std/thread/thread.semaphore/try_acquire.pass.cpp FAIL -std/thread/thread.semaphore/version.pass.cpp FAIL - # *** MISSING COMPILER FEATURES *** # Nothing here! :-) @@ -508,16 +487,10 @@ std/thread/futures/futures.task/futures.task.members/make_ready_at_thread_exit.p # *** C1XX COMPILER BUGS *** -# Compiler bug: VSO-106654 "error C2580 "multiple versions of a defaulted special member functions are not allowed" is bogus and ungrammatical" -std/utilities/tuple/tuple.tuple/tuple.cnstr/test_lazy_sfinae.pass.cpp:0 FAIL - -# Compiler bug: DevCom-409222 "Constructing rvalue reference from non-reference-related lvalue reference" +# DevCom-409222 "Constructing rvalue reference from non-reference-related lvalue reference" std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp:0 FAIL -# Compiler bug: VSO-1035737 "constexpr pointers-by-reference" -std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.index/difference_type.pass.cpp:0 FAIL - -# Compiler bug: DevCom-876860 "conditional operator errors" blocks readable. +# DevCom-876860 "conditional operator errors" blocks readable. std/containers/views/span.cons/ptr_len.pass.cpp:0 FAIL std/containers/views/span.cons/ptr_ptr.pass.cpp:0 FAIL @@ -530,6 +503,11 @@ std/thread/macro.pass.cpp:1 FAIL std/depr/depr.c.headers/tgmath_h.pass.cpp:1 FAIL +# *** CLANG FEATURES NOT YET IMPLEMENTED *** +# P0960R3 "Allow initializing aggregates from a parenthesized list of values" +std/utilities/tuple/tuple.tuple/tuple.creation/tuple_cat.pass.cpp:0 FAIL + + # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_fsizeddeallocation.pass.cpp:1 FAIL @@ -542,52 +520,42 @@ std/language.support/support.limits/limits/numeric.limits.members/traps.pass.cpp # *** STL BUGS *** -# STL bug: VSO-121977 ": the enum value of std::money_base is not correct[libcxx]" +# GH-1112 : the enum value of std::money_base is not correct std/localization/locale.categories/category.monetary/locale.moneypunct/money_base.pass.cpp FAIL -# STL Bug: VSO-595631 basic_filebuf doesn't comply with setbuf(0,0) requirement in the standard +# GH-1113 : basic_filebuf doesn't comply with setbuf(0,0) requirement in the standard std/input.output/file.streams/fstreams/filebuf.virtuals/overflow.pass.cpp FAIL std/input.output/file.streams/fstreams/filebuf.virtuals/underflow.pass.cpp FAIL -# STL bug: Our inheritance implementation is allowing this to compile when it shouldn't. -std/numerics/complex.number/complex.special/double_long_double_implicit.compile.fail.cpp FAIL -std/numerics/complex.number/complex.special/float_double_implicit.compile.fail.cpp FAIL -std/numerics/complex.number/complex.special/float_long_double_implicit.compile.fail.cpp FAIL - -# STL bug: regex_traits::transform() isn't following the Standard. +# GH-1004 : Error C2664 in std::regex_traits::transform std/re/re.traits/transform.pass.cpp FAIL -# STL bug: Incorrect return types. -std/numerics/complex.number/cmplx.over/pow.pass.cpp FAIL - -# STL bug: We allow fill() and swap() for array. +# GH-1295 : array allows fill() and swap() std/containers/sequences/array/array.fill/fill.fail.cpp FAIL std/containers/sequences/array/array.swap/swap.fail.cpp FAIL -# STL bug: VSO-207715 We reject array. +# GH-942 : std::array doesn't compile - when type is not default constructible std/containers/sequences/array/array.cons/implicit_copy.pass.cpp FAIL std/containers/sequences/array/array.cons/initialization.pass.cpp FAIL std/containers/sequences/array/array.data/data_const.pass.cpp FAIL std/containers/sequences/array/array.data/data.pass.cpp FAIL std/containers/sequences/array/iterators.pass.cpp FAIL -# STL bug: string_view doesn't enforce "non-array trivial standard-layout", related to LWG-3034. -std/strings/string.view/char.bad.fail.cpp:0 FAIL - -# Predicate count assertions - IDL2 is slightly bending the Standard's rules here. +# GH-1006 : debug checks for predicates are observable std/algorithms/alg.sorting/alg.heap.operations/make.heap/make_heap_comp.pass.cpp FAIL std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp FAIL std/algorithms/alg.sorting/alg.min.max/minmax_init_list_comp.pass.cpp FAIL -# STL bug: We don't match strtod / strtof when doing field extraction for hexfloats, or special cases like inf +# GH-1259 : wrong field extraction for hexfloats, or special cases like inf std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp FAIL std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp FAIL std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp FAIL -# STL bug: We don't match numpunct groups correctly in do_get +# GH-1277 : We don't match numpunct groups correctly in do_get std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp FAIL -# STL test bug: We don't have the locale names libcxx wants specialized in platform_support.hpp +# GH-1275 : missing some locale names +# We don't have the locale names libcxx wants specialized in platform_support.hpp # More bugs may be uncovered when the locale names are present. # move.pass.cpp can crash. std/input.output/iostreams.base/ios/basic.ios.members/move.pass.cpp SKIPPED @@ -619,22 +587,26 @@ std/localization/locale.categories/category.time/locale.time.put.byname/put1.pas std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp FAIL std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/thousands_sep.pass.cpp FAIL -# STL Bug? Our wbuffer_convert does not implement seek. [depr.conversions.buffer] is completely underspecified. +# GH-1264 : wbuffer_convert does not implement seek std/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp FAIL -# STL Bug: error_category's default ctor isn't constexpr. (Should be fixed in vNext.) +# GH-1116 : error_category's default ctor isn't constexpr. std/diagnostics/syserr/syserr.errcat/syserr.errcat.nonvirtuals/default_ctor.pass.cpp:1 FAIL -# STL Bug: future incorrectly uses copy assignment instead of copy construction in set_value. (Should be fixed in vNext.) +# GH-1190 : incorrectly used copy assignment instead of copy construction in set_value std/thread/futures/futures.promise/set_value_const.pass.cpp FAIL -# STL bug: GH-757 : Too many enabled hash specializations +# GH-757 : Too many enabled hash specializations std/strings/basic.string.hash/char_type_hash.fail.cpp FAIL std/strings/string.view/string.view.hash/char_type.hash.fail.cpp FAIL -# STL bug: GH-784 : aligned_storage has incorrect alignment defaults +# GH-784 : aligned_storage has incorrect alignment defaults std/utilities/meta/meta.trans/meta.trans.other/aligned_storage.pass.cpp FAIL +# GH-519 : signbit() misses overloads for integer types +std/depr/depr.c.headers/math_h.pass.cpp FAIL +std/numerics/c.math/cmath.pass.cpp FAIL + # *** CRT BUGS *** # We're permanently missing aligned_alloc(). @@ -647,9 +619,18 @@ std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp # *** LIKELY BOGUS TESTS *** -# Test bug/LEWG issue or STL bug. See GH-519 ": signbit() misses overloads for integer types". -std/depr/depr.c.headers/math_h.pass.cpp FAIL -std/numerics/c.math/cmath.pass.cpp FAIL +# "error: _LIBCPP_VERSION not defined" +std/thread/thread.barrier/version.pass.cpp FAIL +std/thread/thread.latch/version.pass.cpp FAIL +std/thread/thread.semaphore/version.pass.cpp FAIL + +# "error C3861: 'assert': identifier not found" +std/thread/thread.semaphore/timed.pass.cpp FAIL +std/thread/thread.semaphore/try_acquire.pass.cpp FAIL + +# pass lambda without noexcept to barrier +std/thread/thread.barrier/completion.pass.cpp FAIL +std/thread/thread.barrier/max.pass.cpp FAIL # Test bug after LWG-2899 "is_(nothrow_)move_constructible and tuple, optional and unique_ptr" was accepted. std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.asgn/move_convert.pass.cpp FAIL @@ -761,15 +742,27 @@ std/language.support/cmp/cmp.weakord/weakord.pass.cpp FAIL # error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax std/containers/sequences/array/array.creation/to_array.pass.cpp:0 FAIL -# Tests that need to learn that insert iterators have non-void difference type in C++20 +# Tests that need to learn that iterators have non-void difference types in C++20 std/iterators/predef.iterators/insert.iterators/back.insert.iterator/types.pass.cpp FAIL std/iterators/predef.iterators/insert.iterators/front.insert.iterator/types.pass.cpp FAIL std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp FAIL +std/iterators/stream.iterators/ostream.iterator/types.pass.cpp FAIL +std/iterators/stream.iterators/ostreambuf.iterator/types.pass.cpp FAIL # Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex::_Ty', possible loss of data std/numerics/complex.number/cmplx.over/conj.pass.cpp:0 FAIL +std/numerics/complex.number/cmplx.over/pow.pass.cpp:0 FAIL std/numerics/complex.number/cmplx.over/proj.pass.cpp:0 FAIL +# Assertion failed: std::abs(skew - x_skew) < 0.01 +# Random number generation test with too strict pass criteria (test8 failure probability ~= 0.04) +std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.pconst/eval.pass.cpp FAIL + +# Assertion failed: std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001 +# Random number generation test with too strict pass criteria (test6 failure probability > 0.2) +std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/eval_param.pass.cpp FAIL +std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/eval.pass.cpp FAIL + # Assertion failed: (std::lerp(T(2.3), T(2.3), inf) == T(2.3)) # Asserts `(std::lerp(T(2.3), T(2.3), inf) == T(2.3))` and `std::isnan(std::lerp(T( 0), T( 0), inf))` # They shouldn't behave differently. Both of them should probably return NaN. @@ -812,22 +805,6 @@ std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.gamma/min.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.poisson/eval_param.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.poisson/eval.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.pois/rand.dist.pois.weibull/max.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.pconst/ctor_init_func.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.pconst/ctor_iterator.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.pconst/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.pconst/param_ctor_init_func.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.pconst/param_ctor_iterator.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/ctor_default.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/ctor_func.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/ctor_init_func.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/ctor_iterator.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/ctor_param.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/eval_param.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/eval.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/param_ctor_default.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/param_ctor_func.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/param_ctor_init_func.pass.cpp FAIL -std/numerics/rand/rand.dis/rand.dist.samp/rand.dist.samp.plinear/param_ctor_iterator.pass.cpp FAIL std/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.real/param_ctor.pass.cpp FAIL # Not yet analyzed, likely STL bugs. Various assertions. diff --git a/tests/libcxx/lit.cfg b/tests/libcxx/lit.cfg new file mode 100644 index 00000000000..bd6e637ee27 --- /dev/null +++ b/tests/libcxx/lit.cfg @@ -0,0 +1,25 @@ +# 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")) + +config.name = 'libc++' +config.suffixes = ['.pass.cpp', '.fail.cpp'] + +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() diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index 473dace7e7c..bae25803316 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -1,28 +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_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.params['use_old_format'] = True -config.loaded_site_config = True -lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/test/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()) -config.suffixes = [".pass.cpp", ".fail.cpp"] -config.test_exec_root = "@LIBCXX_TEST_OUTPUT_DIR@" +lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@LIBCXX_EXPECTED_RESULTS@') +lit_config.include_dirs[config.name] = ['@STL_TESTED_HEADERS_DIR@', '@LIBCXX_SOURCE_DIR@/test/support'] +lit_config.library_dirs[config.name] = ['@CMAKE_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.test_subdirs[config.name] = ['@LIBCXX_SOURCE_DIR@/test/std'] + +lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index ca2297c46b0..4239de46b5b 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -49,6 +49,7 @@ containers\unord\unord.map\unord.map.modifiers\insert_and_emplace_allocator_requ containers\unord\unord.set\insert_and_emplace_allocator_requirements.pass.cpp # libc++ doesn't yet implement P1423R3, so it expects an old value for `__cpp_lib_char8_t` +language.support\support.limits\support.limits.general\atomic.version.pass.cpp language.support\support.limits\support.limits.general\filesystem.version.pass.cpp language.support\support.limits\support.limits.general\istream.version.pass.cpp language.support\support.limits\support.limits.general\limits.version.pass.cpp @@ -65,6 +66,7 @@ numerics\bit\bit.pow.two\log2p1.pass.cpp # test emits warning C4310: cast truncates constant value numerics\bit\bitops.rot\rotl.pass.cpp + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" # rapid-cxx-test.hpp uses pragma system_header @@ -252,9 +254,6 @@ utilities\memory\default.allocator\allocator.members\allocate.verify.cpp # *** MISSING STL FEATURES *** -# C++20 P0019R8 "atomic_ref" -language.support\support.limits\support.limits.general\atomic.version.pass.cpp - # C++20 P0355R7 " Calendars And Time Zones" utilities\time\days.pass.cpp utilities\time\months.pass.cpp @@ -471,26 +470,6 @@ language.support\support.limits\support.limits.general\functional.version.pass.c language.support\support.limits\support.limits.general\iterator.version.pass.cpp language.support\support.limits\support.limits.general\memory.version.pass.cpp -# C++20 P1135R6 "The C++20 Synchronization Library" -thread\thread.barrier\arrive.pass.cpp -thread\thread.barrier\arrive_and_drop.pass.cpp -thread\thread.barrier\arrive_and_wait.pass.cpp -thread\thread.barrier\completion.pass.cpp -thread\thread.barrier\max.pass.cpp -thread\thread.barrier\version.pass.cpp -thread\thread.latch\arrive_and_wait.pass.cpp -thread\thread.latch\count_down.pass.cpp -thread\thread.latch\max.pass.cpp -thread\thread.latch\try_wait.pass.cpp -thread\thread.latch\version.pass.cpp -thread\thread.semaphore\acquire.pass.cpp -thread\thread.semaphore\binary.pass.cpp -thread\thread.semaphore\max.pass.cpp -thread\thread.semaphore\release.pass.cpp -thread\thread.semaphore\timed.pass.cpp -thread\thread.semaphore\try_acquire.pass.cpp -thread\thread.semaphore\version.pass.cpp - # *** MISSING COMPILER FEATURES *** # Nothing here! :-) @@ -508,16 +487,10 @@ thread\futures\futures.task\futures.task.members\make_ready_at_thread_exit.pass. # *** C1XX COMPILER BUGS *** -# Compiler bug: VSO-106654 "error C2580 "multiple versions of a defaulted special member functions are not allowed" is bogus and ungrammatical" -utilities\tuple\tuple.tuple\tuple.cnstr\test_lazy_sfinae.pass.cpp - -# Compiler bug: DevCom-409222 "Constructing rvalue reference from non-reference-related lvalue reference" +# DevCom-409222 "Constructing rvalue reference from non-reference-related lvalue reference" utilities\meta\meta.unary\meta.unary.prop\is_constructible.pass.cpp -# Compiler bug: VSO-1035737 "constexpr pointers-by-reference" -iterators\predef.iterators\move.iterators\move.iter.ops\move.iter.op.index\difference_type.pass.cpp - -# Compiler bug: DevCom-876860 "conditional operator errors" blocks readable. +# DevCom-876860 "conditional operator errors" blocks readable. containers\views\span.cons\ptr_len.pass.cpp containers\views\span.cons\ptr_ptr.pass.cpp @@ -530,6 +503,11 @@ thread\macro.pass.cpp depr\depr.c.headers\tgmath_h.pass.cpp +# *** CLANG FEATURES NOT YET IMPLEMENTED *** +# P0960R3 "Allow initializing aggregates from a parenthesized list of values" +utilities\tuple\tuple.tuple\tuple.creation\tuple_cat.pass.cpp + + # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? language.support\support.dynamic\new.delete\new.delete.array\sized_delete_array_fsizeddeallocation.pass.cpp @@ -542,52 +520,42 @@ language.support\support.limits\limits\numeric.limits.members\traps.pass.cpp # *** STL BUGS *** -# STL bug: VSO-121977 ": the enum value of std::money_base is not correct[libcxx]" +# GH-1112 : the enum value of std::money_base is not correct localization\locale.categories\category.monetary\locale.moneypunct\money_base.pass.cpp -# STL Bug: VSO-595631 basic_filebuf doesn't comply with setbuf(0,0) requirement in the standard +# GH-1113 : basic_filebuf doesn't comply with setbuf(0,0) requirement in the standard input.output\file.streams\fstreams\filebuf.virtuals\overflow.pass.cpp input.output\file.streams\fstreams\filebuf.virtuals\underflow.pass.cpp -# STL bug: Our inheritance implementation is allowing this to compile when it shouldn't. -numerics\complex.number\complex.special\double_long_double_implicit.compile.fail.cpp -numerics\complex.number\complex.special\float_double_implicit.compile.fail.cpp -numerics\complex.number\complex.special\float_long_double_implicit.compile.fail.cpp - -# STL bug: regex_traits::transform() isn't following the Standard. +# GH-1004 : Error C2664 in std::regex_traits::transform re\re.traits\transform.pass.cpp -# STL bug: Incorrect return types. -numerics\complex.number\cmplx.over\pow.pass.cpp - -# STL bug: We allow fill() and swap() for array. +# GH-1295 : array allows fill() and swap() containers\sequences\array\array.fill\fill.fail.cpp containers\sequences\array\array.swap\swap.fail.cpp -# STL bug: VSO-207715 We reject array. +# GH-942 : std::array doesn't compile - when type is not default constructible containers\sequences\array\array.cons\implicit_copy.pass.cpp containers\sequences\array\array.cons\initialization.pass.cpp containers\sequences\array\array.data\data_const.pass.cpp containers\sequences\array\array.data\data.pass.cpp containers\sequences\array\iterators.pass.cpp -# STL bug: string_view doesn't enforce "non-array trivial standard-layout", related to LWG-3034. -strings\string.view\char.bad.fail.cpp - -# Predicate count assertions - IDL2 is slightly bending the Standard's rules here. +# GH-1006 : debug checks for predicates are observable algorithms\alg.sorting\alg.heap.operations\make.heap\make_heap_comp.pass.cpp algorithms\alg.sorting\alg.merge\inplace_merge_comp.pass.cpp algorithms\alg.sorting\alg.min.max\minmax_init_list_comp.pass.cpp -# STL bug: We don't match strtod / strtof when doing field extraction for hexfloats, or special cases like inf +# GH-1259 : wrong field extraction for hexfloats, or special cases like inf localization\locale.categories\category.numeric\locale.num.get\facet.num.get.members\get_double.pass.cpp localization\locale.categories\category.numeric\locale.num.get\facet.num.get.members\get_float.pass.cpp localization\locale.categories\category.numeric\locale.num.get\facet.num.get.members\get_long_double.pass.cpp -# STL bug: We don't match numpunct groups correctly in do_get +# GH-1277 : We don't match numpunct groups correctly in do_get localization\locale.categories\category.numeric\locale.num.get\facet.num.get.members\get_long.pass.cpp -# STL test bug: We don't have the locale names libcxx wants specialized in platform_support.hpp +# GH-1275 : missing some locale names +# We don't have the locale names libcxx wants specialized in platform_support.hpp # More bugs may be uncovered when the locale names are present. # move.pass.cpp can crash. input.output\iostreams.base\ios\basic.ios.members\move.pass.cpp @@ -619,22 +587,26 @@ localization\locale.categories\category.time\locale.time.put.byname\put1.pass.cp localization\locale.categories\facet.numpunct\locale.numpunct.byname\grouping.pass.cpp localization\locale.categories\facet.numpunct\locale.numpunct.byname\thousands_sep.pass.cpp -# STL Bug? Our wbuffer_convert does not implement seek. [depr.conversions.buffer] is completely underspecified. +# GH-1264 : wbuffer_convert does not implement seek localization\locales\locale.convenience\conversions\conversions.buffer\seekoff.pass.cpp -# STL Bug: error_category's default ctor isn't constexpr. (Should be fixed in vNext.) +# GH-1116 : error_category's default ctor isn't constexpr. diagnostics\syserr\syserr.errcat\syserr.errcat.nonvirtuals\default_ctor.pass.cpp -# STL Bug: future incorrectly uses copy assignment instead of copy construction in set_value. (Should be fixed in vNext.) +# GH-1190 : incorrectly used copy assignment instead of copy construction in set_value thread\futures\futures.promise\set_value_const.pass.cpp -# STL bug: GH-757 : Too many enabled hash specializations +# GH-757 : Too many enabled hash specializations strings\basic.string.hash\char_type_hash.fail.cpp strings\string.view\string.view.hash\char_type.hash.fail.cpp -# STL bug: GH-784 : aligned_storage has incorrect alignment defaults +# GH-784 : aligned_storage has incorrect alignment defaults utilities\meta\meta.trans\meta.trans.other\aligned_storage.pass.cpp +# GH-519 : signbit() misses overloads for integer types +depr\depr.c.headers\math_h.pass.cpp +numerics\c.math\cmath.pass.cpp + # *** CRT BUGS *** # We're permanently missing aligned_alloc(). @@ -647,9 +619,18 @@ thread\thread.threads\thread.thread.class\thread.thread.member\join.pass.cpp # *** LIKELY BOGUS TESTS *** -# Test bug/LEWG issue or STL bug. See GH-519 ": signbit() misses overloads for integer types". -depr\depr.c.headers\math_h.pass.cpp -numerics\c.math\cmath.pass.cpp +# "error: _LIBCPP_VERSION not defined" +thread\thread.barrier\version.pass.cpp +thread\thread.latch\version.pass.cpp +thread\thread.semaphore\version.pass.cpp + +# "error C3861: 'assert': identifier not found" +thread\thread.semaphore\timed.pass.cpp +thread\thread.semaphore\try_acquire.pass.cpp + +# pass lambda without noexcept to barrier +thread\thread.barrier\completion.pass.cpp +thread\thread.barrier\max.pass.cpp # Test bug after LWG-2899 "is_(nothrow_)move_constructible and tuple, optional and unique_ptr" was accepted. utilities\smartptr\unique.ptr\unique.ptr.class\unique.ptr.asgn\move_convert.pass.cpp @@ -761,15 +742,27 @@ language.support\cmp\cmp.weakord\weakord.pass.cpp # error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax containers\sequences\array\array.creation\to_array.pass.cpp -# Tests that need to learn that insert iterators have non-void difference type in C++20 +# Tests that need to learn that iterators have non-void difference types in C++20 iterators\predef.iterators\insert.iterators\back.insert.iterator\types.pass.cpp iterators\predef.iterators\insert.iterators\front.insert.iterator\types.pass.cpp iterators\predef.iterators\insert.iterators\insert.iterator\types.pass.cpp +iterators\stream.iterators\ostream.iterator\types.pass.cpp +iterators\stream.iterators\ostreambuf.iterator\types.pass.cpp # Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex::_Ty', possible loss of data numerics\complex.number\cmplx.over\conj.pass.cpp +numerics\complex.number\cmplx.over\pow.pass.cpp numerics\complex.number\cmplx.over\proj.pass.cpp +# Assertion failed: std::abs(skew - x_skew) < 0.01 +# Random number generation test with too strict pass criteria (test8 failure probability ~= 0.04) +numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.pconst\eval.pass.cpp + +# Assertion failed: std::abs(f(u[i], a, m, bk, c) - double(i)/N) < .001 +# Random number generation test with too strict pass criteria (test6 failure probability > 0.2) +numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\eval_param.pass.cpp +numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\eval.pass.cpp + # Assertion failed: (std::lerp(T(2.3), T(2.3), inf) == T(2.3)) # Asserts `(std::lerp(T(2.3), T(2.3), inf) == T(2.3))` and `std::isnan(std::lerp(T( 0), T( 0), inf))` # They shouldn't behave differently. Both of them should probably return NaN. @@ -812,22 +805,6 @@ numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.gamma\min.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.poisson\eval_param.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.poisson\eval.pass.cpp numerics\rand\rand.dis\rand.dist.pois\rand.dist.pois.weibull\max.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.pconst\ctor_init_func.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.pconst\ctor_iterator.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.pconst\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.pconst\param_ctor_init_func.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.pconst\param_ctor_iterator.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\ctor_default.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\ctor_func.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\ctor_init_func.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\ctor_iterator.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\ctor_param.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\eval_param.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\eval.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\param_ctor_default.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\param_ctor_func.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\param_ctor_init_func.pass.cpp -numerics\rand\rand.dis\rand.dist.samp\rand.dist.samp.plinear\param_ctor_iterator.pass.cpp numerics\rand\rand.dis\rand.dist.uni\rand.dist.uni.real\param_ctor.pass.cpp # Not yet analyzed, likely STL bugs. Various assertions. diff --git a/tests/std/lit.site.cfg.in b/tests/std/lit.site.cfg.in index e3998e65f93..ccc358b665d 100644 --- a/tests/std/lit.site.cfg.in +++ b/tests/std/lit.site.cfg.in @@ -1,18 +1,41 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -config.cxx_archive_root = "@CMAKE_ARCHIVE_OUTPUT_DIRECTORY@" -config.cxx_headers = "@STL_TESTED_HEADERS_DIR@" -config.cxx_library_root = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" -config.cxx_runtime_root = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" -config.expected_results_list_path = "@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$'] +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_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py index 9d7c64eeaec..72f419e67d0 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py +++ b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py @@ -1,42 +1,23 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path +import os from stl.test.format import STLTestFormat, TestStep class CustomTestFormat(STLTestFormat): - def getBuildSteps(self, test, lit_config, shared): - exe_source = Path(test.getSourcePath()) - dll_source = exe_source.parent / 'TestDll.cpp' - shared.exec_dir = test.getExecDir() - output_base = test.getOutputBaseName() - output_dir = test.getOutputDir() - pass_var, fail_var = test.getPassFailResultCodes() - dll_output = output_dir / 'TestDll.DLL' - - dll_compile_cmd, out_files, exec_file = \ - test.cxx.executeBasedOnFlagsCmd([dll_source], output_dir, - shared.exec_dir, 'TestDll', - ['/Fe' + str(dll_output)], - [], ['/DLL']) - - shared.dll_file = dll_output - - yield TestStep(dll_compile_cmd, shared.exec_dir, [dll_source], - test.cxx.compile_env) - - 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) + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + dll_source = os.path.join(os.path.dirname(exeSource), 'TestDll.cpp') + + outputDir, outputBase = test.getTempPaths() + dllOutput = os.path.join(outputDir, 'TestDll.DLL') + + cmd = [test.cxx, dll_source, *test.flags, *test.compileFlags, '/Fe' + dllOutput, + '/link', '/DLL', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) + + for step in super().getBuildSteps(test, litConfig, shared): + yield step diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg b/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg index 5a7c740f058..a0ea4769781 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg +++ b/tests/std/tests/Dev09_056375_locale_cleanup/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import Dev09_056375_locale_cleanup.custom_format -config.test_format = \ - Dev09_056375_locale_cleanup.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = Dev09_056375_locale_cleanup.custom_format.CustomTestFormat() diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py index 323790ec7cb..2c34a4c7020 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py @@ -1,23 +1,26 @@ # 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): - 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() - - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source, test2_source], - output_dir, shared.exec_dir, - output_base, [], [], []) - - yield TestStep(cmd, shared.exec_dir, [exe_source, test2_source], - test.cxx.compile_env) + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + test2Source = os.path.join(os.path.dirname(exeSource), 'test2.cpp') + + outputDir, outputBase = test.getTempPaths() + + if litConfig.edg_drop is not None: + isenseRspPath = outputBase + '.isense.rsp' + test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) + + 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) + + for step in self._handleIsenseRspFile(test, litConfig): + yield step diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg b/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg index 4c325b48119..9d2d29f5b71 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import Dev09_172666_tr1_tuple_odr.custom_format -config.test_format = \ - Dev09_172666_tr1_tuple_odr.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = Dev09_172666_tr1_tuple_odr.custom_format.CustomTestFormat() diff --git a/tests/std/tests/GH_000545_include_compare/custom_format.py b/tests/std/tests/GH_000545_include_compare/custom_format.py index 05c32016fde..3affd95aeee 100644 --- a/tests/std/tests/GH_000545_include_compare/custom_format.py +++ b/tests/std/tests/GH_000545_include_compare/custom_format.py @@ -1,28 +1,22 @@ # 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): - 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, - [], [], []) - - yield TestStep(cmd, shared.exec_dir, source_files, - test.cxx.compile_env) + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, *sourceFiles, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, + '/link', *test.linkFlags] + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/GH_000545_include_compare/lit.local.cfg b/tests/std/tests/GH_000545_include_compare/lit.local.cfg index cbdcadad3d6..79640e4ec5e 100644 --- a/tests/std/tests/GH_000545_include_compare/lit.local.cfg +++ b/tests/std/tests/GH_000545_include_compare/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import GH_000545_include_compare.custom_format -config.test_format = \ - GH_000545_include_compare.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = GH_000545_include_compare.custom_format.CustomTestFormat() diff --git a/tests/std/tests/P0607R0_inline_variables/custom_format.py b/tests/std/tests/P0607R0_inline_variables/custom_format.py index 323790ec7cb..2c34a4c7020 100644 --- a/tests/std/tests/P0607R0_inline_variables/custom_format.py +++ b/tests/std/tests/P0607R0_inline_variables/custom_format.py @@ -1,23 +1,26 @@ # 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): - 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() - - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source, test2_source], - output_dir, shared.exec_dir, - output_base, [], [], []) - - yield TestStep(cmd, shared.exec_dir, [exe_source, test2_source], - test.cxx.compile_env) + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + test2Source = os.path.join(os.path.dirname(exeSource), 'test2.cpp') + + outputDir, outputBase = test.getTempPaths() + + if litConfig.edg_drop is not None: + isenseRspPath = outputBase + '.isense.rsp' + test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) + + 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) + + for step in self._handleIsenseRspFile(test, litConfig): + yield step diff --git a/tests/std/tests/P0607R0_inline_variables/lit.local.cfg b/tests/std/tests/P0607R0_inline_variables/lit.local.cfg index 55628eacde9..b84c4f43d5d 100644 --- a/tests/std/tests/P0607R0_inline_variables/lit.local.cfg +++ b/tests/std/tests/P0607R0_inline_variables/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import P0607R0_inline_variables.custom_format -config.test_format = \ - P0607R0_inline_variables.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = P0607R0_inline_variables.custom_format.CustomTestFormat() diff --git a/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py b/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py index 07b7dff9cfe..a35ed2fd2f5 100644 --- a/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py +++ b/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py @@ -1,52 +1,37 @@ # 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 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() - - a_compile_cmd, out_files, exec_file = \ - test.cxx.executeBasedOnFlagsCmd([a_source], output_dir, - shared.exec_dir, 'a', - [test.calling_convention_a, '/c'], - [], []) - - yield TestStep(a_compile_cmd, shared.exec_dir, [a_source], - test.cxx.compile_env) - - a_output = output_dir / 'a.obj' - - 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)], [], []) - - yield TestStep(exe_compile_cmd, shared.exec_dir, - [a_output, exe_source], test.cxx.compile_env) + def getTestsInDirectory(self, testSuite, pathInSuite, litConfig, localConfig, testClass=CustomTest): + return super().getTestsInDirectory(testSuite, pathInSuite, litConfig, localConfig, testClass) + + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + aSource = os.path.join(os.path.dirname(exeSource), 'a.cpp') + + outputDir, outputBase = test.getTempPaths() + aObj = os.path.join(outputDir, 'a.obj') + + cmd = [test.cxx, aSource, test.callingConventionA, *test.flags, '/c', *test.compileFlags, '/Fo' + aObj] + + yield TestStep(cmd, shared.execDir, shared.env, False) + + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, aObj, test.callingConventionB, *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags] + + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg b/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg index 9f4ac1b16d8..3086b12de22 100644 --- a/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg +++ b/tests/std/tests/VSO_0000000_any_calling_conventions/lit.local.cfg @@ -1,12 +1,11 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -config.suffixes = {'b.cpp'} +config.suffixes = ['b[.]cpp$'] +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import VSO_0000000_any_calling_conventions.custom_format -config.test_format = \ - VSO_0000000_any_calling_conventions.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = VSO_0000000_any_calling_conventions.custom_format.CustomTestFormat() diff --git a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py index 323790ec7cb..2c34a4c7020 100644 --- a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py +++ b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py @@ -1,23 +1,26 @@ # 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): - 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() - - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([exe_source, test2_source], - output_dir, shared.exec_dir, - output_base, [], [], []) - - yield TestStep(cmd, shared.exec_dir, [exe_source, test2_source], - test.cxx.compile_env) + def getBuildSteps(self, test, litConfig, shared): + exeSource = test.getSourcePath() + test2Source = os.path.join(os.path.dirname(exeSource), 'test2.cpp') + + outputDir, outputBase = test.getTempPaths() + + if litConfig.edg_drop is not None: + isenseRspPath = outputBase + '.isense.rsp' + test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) + + 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) + + for step in self._handleIsenseRspFile(test, litConfig): + yield step diff --git a/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg b/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg index 994f1aefbc5..970edc70950 100644 --- a/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg +++ b/tests/std/tests/VSO_0000000_matching_npos_address/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import VSO_0000000_matching_npos_address.custom_format -config.test_format = \ - VSO_0000000_matching_npos_address.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = VSO_0000000_matching_npos_address.custom_format.CustomTestFormat() diff --git a/tests/tr1/lit.site.cfg.in b/tests/tr1/lit.site.cfg.in index 49c489910f6..c2879998983 100644 --- a/tests/tr1/lit.site.cfg.in +++ b/tests/tr1/lit.site.cfg.in @@ -1,18 +1,41 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -config.cxx_archive_root = "@CMAKE_ARCHIVE_OUTPUT_DIRECTORY@" -config.cxx_headers = "@STL_TESTED_HEADERS_DIR@" -config.cxx_library_root = "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" -config.cxx_runtime_root = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" -config.expected_results_list_path = "@TR1_EXPECTED_RESULTS@" -config.include_dirs = ["@STL_SOURCE_DIR@/tests/tr1/include", "@STL_SOURCE_DIR@/tests/std/include"] -config.msvc_toolset_libs_root = "@TOOLSET_LIB@" -config.stl_build_root = "@STL_BUILD_ROOT@" -config.stl_src_root = "@STL_SOURCE_DIR@" -config.target_arch = "@VCLIBS_TARGET_ARCHITECTURE@" -config.test_exec_root = "@TR1_TEST_OUTPUT_DIR@" -config.test_subdirs_file = "@TR1_TEST_SUBDIRS_FILE@" -config.test_subdirs_root = "@TR1_TEST_SUBDIRS_ROOT@" +import os +import site +site.addsitedir("@STL_TEST_UTILS_DIR@") +site.addsitedir(os.path.join("@LIBCXX_SOURCE_DIR@", "utils")) +import stl.test.config +import stl.test.features +import stl.test.file_parsing +import stl.test.format +import stl.test.params -lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") +config.name = 'tr1' +config.suffixes = ['test[.]cpp$'] +config.test_exec_root = "@TR1_TEST_OUTPUT_DIR@" +config.test_format = stl.test.format.STLTestFormat() + +lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) +lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) +lit_config.library_dirs = getattr(lit_config, 'library_dirs', dict()) +lit_config.test_subdirs = getattr(lit_config, 'test_subdirs', dict()) + +lit_config.expected_results[config.name] = stl.test.file_parsing.parse_result_file('@TR1_EXPECTED_RESULTS@') +lit_config.include_dirs[config.name] = \ + ['@STL_TESTED_HEADERS_DIR@', '@LIBCXX_SOURCE_DIR@/test/support', '@STL_SOURCE_DIR@/tests/std/include', '@STL_SOURCE_DIR@/tests/tr1/include'] +lit_config.library_dirs[config.name] = ['@CMAKE_LIBRARY_OUTPUT_DIRECTORY@', '@TOOLSET_LIB@'] +lit_config.test_subdirs[config.name] = \ + [os.path.normpath(os.path.join('@TR1_TEST_SUBDIRS_ROOT@', path)) for \ + path in stl.test.file_parsing.parse_commented_file('@TR1_TEST_SUBDIRS_FILE@')] + +lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' +lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' + +# Add parameters and features to the config +stl.test.config.configure( + stl.test.params.getDefaultParameters(config, lit_config), + stl.test.features.getDefaultFeatures(config, lit_config), + config, + lit_config +) diff --git a/tests/utils/stl/test/config.py b/tests/utils/stl/test/config.py index d9a6c040352..998bfe47d04 100644 --- a/tests/utils/stl/test/config.py +++ b/tests/utils/stl/test/config.py @@ -1,381 +1,46 @@ -#===----------------------------------------------------------------------===## -# -# 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 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 - - # 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 +#===----------------------------------------------------------------------===## +# +# 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 os + +def configure(parameters, features, config, lit_config): + # Apply parameters to the configuration first, since parameters are things + # that we request explicitly and which might influence what features are + # implicitly made available next. + for param in parameters: + feature = param.getFeature(config, lit_config.params) + if feature: + feature.enableIn(config) + lit_config.note("Enabling Lit feature '{}' as a result of parameter '{}'".format(feature.getName(config), param.name)) + + # Then, apply the automatically-detected features. + printFeatures = [] + for feature in features: + if feature.isSupported(config): + feature.enableIn(config) + printFeatures.append(feature.getName(config)) + printFeatures = ["'{}'".format(f) for f in sorted(printFeatures)] + lit_config.note("Enabling implicitly detected Lit features {}".format(', '.join(printFeatures))) + + # Normalize and validate all subdirectories to be tested + lit_config.test_subdirs[config.name] = [os.path.normpath(subdir) for subdir in lit_config.test_subdirs[config.name]] + for subdir in lit_config.test_subdirs[config.name]: + if not os.path.exists(subdir): + lit_config.fatal("The directory {} does not exist and was marked as a subdirectory to test".format(subdir)) + + lit_config.flags = getattr(lit_config, 'flags', dict()) + lit_config.compile_flags = getattr(lit_config, 'compile_flags', dict()) + lit_config.link_flags = getattr(lit_config, 'link_flags', dict()) + + lit_config.flags[config.name] = [] + lit_config.compile_flags[config.name] = \ + ['/I' + os.path.normpath(dir) for dir in lit_config.include_dirs[config.name]] + lit_config.link_flags[config.name] = \ + ['/LIBPATH:' + os.path.normpath(dir) for dir in lit_config.library_dirs[config.name]] + + lit_config.test_env = {'PATH' : os.path.normpath(lit_config.cxx_runtime)} diff --git a/tests/utils/stl/test/features.py b/tests/utils/stl/test/features.py new file mode 100644 index 00000000000..5c144b45ae9 --- /dev/null +++ b/tests/utils/stl/test/features.py @@ -0,0 +1,45 @@ +#===----------------------------------------------------------------------===// +# +# 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')) + + return DEFAULT_FEATURES diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 8132ba29b3f..06b6ca87664 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -10,16 +10,15 @@ 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,265 +26,299 @@ @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. -class STLTestFormat: + If both environments contain the PATH variables, they are also merged + using the proper separator. """ - 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' + resultEnv = dict(currentEnv) + for k, v in otherEnv.items(): + if k == 'PATH': + oldPath = currentEnv.get(k, '') + if oldPath != '': + resultEnv[k] = ';'.join((oldPath, v)) else: - for parent in cwd.parents: - if (parent / 'env.lst').is_file(): - envlst_path = parent / 'env.lst' - break + resultEnv[k] = v + else: + resultEnv[k] = v - return envlst_path + return resultEnv - def getTestsInDirectory(self, testSuite, path_in_suite, - litConfig, localConfig, test_class=STLTest): - source_path = testSuite.getSourcePath(path_in_suite) +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 - if not self.isLegalDirectory(source_path, litConfig): + 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 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) + + 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}' - for filename in os.listdir(source_path): + 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,) - - yield test_class(testSuite, - test_path_in_suite, - litConfig, test_config, - env_entry, - format_string.format(env_num), - self.cxx) - - 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: + for envEntry, envNum in zip(envEntries, itertools.count()): + + yield testClass(testSuite, pathInSuite + (filename,), + litConfig, localConfig, envEntry, + formatString.format(envNum)) + + def _parseScript(self, test): + 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) + ] + + script = \ + lit.TestRunner.parseIntegratedTestScript(test, additional_parsers=parsers, require_script=False) + + if isinstance(script, lit.Test.Result): + test.result = script + return + + test.compileFlags.extend(additionalCompileFlags) + test.fileDependencies.extend(fileDependencies) + + def _handleIsenseRspFile(self, test, litConfig): + if litConfig.edg_drop is not None: + with open(isenseRspPath) as f: + cmd = [line.strip() for line in f] + cmd[0] = litConfig.edg_drop + + # 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) - - return result - - 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 + index = cmd.index('--import_dir') + cmd.pop(index) + cmd.pop(index) + except ValueError: + pass + + # --print_diagnostics is not recognized by upstream EDG. + try: + index = cmd.index('--print_diagnostics') + cmd.pop(index) + except ValueError: + pass + + yield TestStep(cmd, shared.execDir, shared.env, False) + def runStep(self, testStep, litConfig): + if str(testStep.workDir) == '.': + testStep.workDir = os.getcwd() + + env = _mergeEnvironments(os.environ, testStep.env) + + return testStep.cmd, *stl.util.executeCommand(testStep.cmd, cwd=testStep.workDir, env=env) + + def getSteps(self, test, litConfig): + @dataclass + class SharedState: + execFile: Optional[os.PathLike] = field(default=None) + execDir: os.PathLike = field(default_factory=Path) + env: Dict[str, str] = field(default_factory=dict) + + 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 + + return \ + self.getBuildSetupSteps(test, litConfig, shared), \ + self.getBuildSteps(test, litConfig, shared), \ + self.getTestSetupSteps(test, litConfig, shared), \ + self.getTestSteps(test, litConfig, shared) + + def getBuildSetupSteps(self, test, litConfig, shared): + shutil.rmtree(shared.execDir, ignore_errors=True) + Path(shared.execDir).mkdir(parents=True, exist_ok=True) + + # Makes this function a generator which yields nothing + yield from [] + + def getBuildSteps(self, test, litConfig, shared): + filename = test.path_in_suite[-1] + _, tmpBase = test.getTempPaths() + + if litConfig.edg_drop is not None: + isenseRspPath = tmpBase + '.isense.rsp' + test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) + + shouldFail = TestType.FAIL in test.testType + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', test.getSourcePath(), *test.flags, *test.compileFlags] + return 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) + + 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) + + for step in self._handleIsenseRspFile(test, litConfig): + yield step + + 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 from [] + + def getTestSteps(self, test, litConfig, shared): + if not TestType.RUN in test.testType: + yield from [] + return + + shouldFail = TestType.FAIL in test.testType + yield TestStep([shared.execFile], shared.execDir, shared.env, shouldFail) + + def execute(self, test, litConfig): try: - self.setup(test) - pass_var, fail_var = test.getPassFailResultCodes() - buildSteps, testSteps = self.getSteps(test, lit_config) + self._parseScript(test) + if test.result is not None: + # TRANSITION: Find a way to do this more cleanly. + # Lit asserts that the result has not already been set. + result = test.result + test.result = None + return result + + if test.expectedResult and test.expectedResult.isFailure: + failVar = lit.Test.XFAIL + passVar = lit.Test.XPASS + else: + failVar = lit.Test.FAIL + passVar = lit.Test.PASS + + buildSetupSteps, buildSteps, testSetupSteps, testSteps = self.getSteps(test, litConfig) + + report = '' + for step in buildSetupSteps: + cmd, out, err, rc = self.runStep(step, litConfig) + + if step.shouldFail and rc == 0: + report += 'Build setup step succeeded unexpectedly.\n' + elif rc != 0: + report += 'Build setup 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): + litConfig.note(report) + return lit.Test.Result(failVar, report) - report = "" for step in buildSteps: - cmd, out, err, rc = \ - self.build_executor.run(step.cmd, step.work_dir, - step.file_deps, step.env) + cmd, out, err, rc = self.runStep(step, litConfig) - if step.should_fail and rc == 0: - report += "Build step succeeded unexpectedly.\n" + if step.shouldFail and rc == 0: + report += 'Build step succeeded unexpectedly.\n' elif rc != 0: - report += "Build step failed unexpectedly.\n" + report += 'Build 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) + if (step.shouldFail and rc == 0) or (not step.shouldFail and rc != 0): + litConfig.note(report) + return lit.Test.Result(failVar, report) + + for step in testSetupSteps: + cmd, out, err, rc = self.runStep(step, litConfig) + + if step.shouldFail and rc == 0: + report += 'Test setup step succeeded unexpectedly.\n' + elif rc != 0: + report += 'Test setup 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): + litConfig.note(report) + return lit.Test.Result(failVar, report) for step in testSteps: - cmd, out, err, rc = \ - self.test_executor.run(step.cmd, step.work_dir, - step.file_deps, step.env) + cmd, out, err, rc = self.runStep(step, litConfig) - if step.should_fail and rc == 0: - report += "Test step succeeded unexpectedly.\n" + if step.shouldFail and rc == 0: + report += 'Test step succeeded unexpectedly.\n' elif rc != 0: - report += "Test step failed unexpectedly.\n" + 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) + if (step.shouldFail and rc == 0) or (not step.shouldFail and rc != 0): + litConfig.note(report) + return lit.Test.Result(failVar, report) - return lit.Test.Result(pass_var, report) + return lit.Test.Result(passVar, report) except Exception as e: - lit_config.warning(str(e)) - raise e - finally: - self.cleanup(test) - - def getSteps(self, test, lit_config): - @dataclass - class SharedState: - exec_file: Optional[os.PathLike] = field(default=None) - exec_dir: os.PathLike = field(default_factory=Path) - - shared = SharedState() - return self.getBuildSteps(test, lit_config, shared), \ - self.getTestSteps(test, lit_config, shared) - - 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()) - - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([source_path], output_dir, - shared.exec_dir, output_base, - [], [], []) - - yield TestStep(cmd, shared.exec_dir, [source_path], - test.cxx.compile_env) - - 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) - - 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()) - - 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)) - - cmd, _ = test.cxx.compileCmd([source_path], os.devnull, flags) - yield TestStep(cmd, exec_dir, [source_path], - test.cxx.compile_env, True) + print(repr(e)) class LibcxxTestFormat(STLTestFormat): """ Custom test format handler to run the libcxx tests for the MSVC STL. """ - def getTestsInDirectory(self, testSuite, path_in_suite, - litConfig, localConfig, test_class=LibcxxTest): - return super().getTestsInDirectory(testSuite, path_in_suite, litConfig, - localConfig, test_class) + def getTestsInDirectory(self, testSuite, pathInSuite, + litConfig, localConfig, testClass=LibcxxTest): + return super().getTestsInDirectory(testSuite, pathInSuite, litConfig, + localConfig, testClass) def addCompileFlags(self, *args): # For now, this is necessary to discard the value of diff --git a/tests/utils/stl/test/params.py b/tests/utils/stl/test/params.py new file mode 100644 index 00000000000..12fe9ad5654 --- /dev/null +++ b/tests/utils/stl/test/params.py @@ -0,0 +1,18 @@ +#===----------------------------------------------------------------------===## +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#===----------------------------------------------------------------------===## + +from libcxx.test.dsl import * + +def getDefaultParameters(config, litConfig): + DEFAULT_PARAMETERS = [ + Parameter(name='long_tests', choices=[True, False], type=bool, default=True, + help="Whether to tests that take longer to run. This can be useful when running on a very slow device.", + feature=lambda enabled: Feature(name='long_tests') if enabled else None), + ] + + return DEFAULT_PARAMETERS diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index 6728132870a..7b4b7355a97 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -7,210 +7,197 @@ # #===----------------------------------------------------------------------===## +from enum import Flag, auto from itertools import chain from pathlib import Path -from xml.sax.saxutils import quoteattr +import copy import os +import pipes import shutil -from lit.Test import FAIL, PASS, SKIPPED, Test, UNSUPPORTED, XPASS, XFAIL +from lit.Test import SKIPPED, Test, UNRESOLVED, UNSUPPORTED +from libcxx.test.dsl import Feature +import lit from stl.compiler import CXXCompiler -_compiler_path_cache = dict() +_compilerPathCache = dict() -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) - - self._configure_expected_result(suite, path_in_suite, lit_config, - test_config, env_num) - if self.skipped: - return +class TestType(Flag): + UNKNOWN = auto() + COMPILE = auto() + LINK = auto() + RUN = auto() + PASS = auto() + FAIL = auto() - self._configure_cxx(lit_config, envlst_entry, default_cxx) - 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 +class STLTest(Test): + def __init__(self, suite, pathInSuite, litConfig, testConfig, + envlstEntry, envNum): + self.compileFlags = [] + self.cxx = None + self.envNum = envNum + self.fileDependencies = [] + self.flags = [] + self.linkFlags = [] + self.testType = None + Test.__init__(self, suite, pathInSuite, copy.deepcopy(testConfig), + None) + + self._configureExpectedResult(suite, litConfig) + if self.result: + return - def getOutputDir(self): - return Path(os.path.join( - self.suite.getExecPath(self.path_in_suite[:-1]))) / self.env_num + self._handleEnvlst(litConfig, envlstEntry) + self._configureTestType() - def getOutputBaseName(self): - return self.path_in_suite[-2] + def _configureTestType(self): + self.testType = TestType.UNKNOWN + filename = self.path_in_suite[-1] - def getExecDir(self): - return self.getOutputDir() + 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 + + if 'analyze:only' in [flag[1:] for flag in \ + chain(self.flags, self.compileFlags, self.linkFlags)] or \ + filename.endswith('.compile.pass.cpp') or filename.endswith('.compile.fail.cpp'): + self.testType = self.testType | TestType.COMPILE + elif filename.endswith('.link.pass.cpp') or filename.endswith('.link.fail.cpp'): + self.testType = self.testType | TestType.LINK + elif filename.endswith('run.fail.cpp') or filename.endswith('run.pass.cpp') or filename == 'test.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 - def getExecPath(self): - return self.getExecDir() / (self.getOutputBaseName() + '.exe') + 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, suite, 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 - - 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: + 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 + + if self.expectedResult is not None: + if self.expectedResult == SKIPPED: + self.result = (lit.Test.SKIPPED, 'This test was explicitly marked as skipped') + elif self.expectedResult.isFailure: self.xfails = ['*'] - def _configure_cxx(self, lit_config, envlst_entry, default_cxx): - env_compiler = envlst_entry.getEnvVal('PM_COMPILER', 'cl') + def _handleEnvlst(self, litConfig, envlstEntry): + envCompiler = envlstEntry.getEnvVal('PM_COMPILER', 'cl') - if not os.path.isfile(env_compiler): - cxx = _compiler_path_cache.get(env_compiler, None) + 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) - - flags = list() - compile_flags = list() - link_flags = list() + litConfig.fatal('Could not find: %r' % envCompiler) - flags.extend(default_cxx.flags or []) - compile_flags.extend(default_cxx.compile_flags or []) - link_flags.extend(default_cxx.link_flags or []) + 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(envlst_entry.getEnvVal('PM_CL', '').split()) - link_flags.extend(envlst_entry.getEnvVal('PM_LINK', '').split()) + self.compileFlags.extend(envlstEntry.getEnvVal('PM_CL', '').split()) + self.linkFlags.extend(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') + targetArch = litConfig.target_arch.casefold() + if (targetArch == 'x64'.casefold()): + self.compileFlags.append('-m64') elif (target_arch == 'x86'.casefold()): - compile_flags.append('-m32') - - self.cxx = CXXCompiler(cxx, flags, compile_flags, link_flags, - default_cxx.compile_env) - - # 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()) - - testcase_template = \ - '\n\t", "]]]]>")) - fil.write("]]>\n") - elif self.result.code == UNSUPPORTED: - unsupported_features = self.getMissingRequiredFeatures() - if unsupported_features: - skip_message = \ - "Skipping because of: " + ", ".join(unsupported_features) - else: - skip_message = "Skipping because of configuration." - skip_message = quoteattr(skip_message) - - fil.write( - ">\n\t\n".format( - skip_message)) - elif self.result.code == SKIPPED: - message = quoteattr('Test is explicitly marked as skipped') - fil.write(">\n\t\n".format( - message)) - else: - fil.write("/>") - - -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 + self.compileFlags.append('-m32') + + self.cxx = os.path.normpath(cxx) + + 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) + self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17=constexpr') + elif flag[5:] == 'c++17': + Feature('c++17').enableIn(self.config) + self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17=constexpr') + elif flag[5:] == 'c++14': + Feature('c++14').enableIn(self.config) + self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17= ') + 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 config.py - def getOutputDir(self): - dir_name = self.path_in_suite[-1] - if dir_name.endswith('.cpp'): - dir_name = dir_name[:-4] + if not foundStd: + Feature('c++14').enableIn(self.config) + self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17= ') - return Path(os.path.join( - self.suite.getExecPath(self.path_in_suite[:-1]))) / dir_name / \ - self.env_num + if 'edg_drop' in self.config.available_features and not 'edg' in self.requires: + self.result = lit.Test.Result(UNSUPPORTED, "We only run /BE tests with the edg drop") - def getXMLOutputTestName(self): - return ':'.join((self.path_in_suite[-1], self.env_num)) +class LibcxxTest(STLTest): 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) From 8b3708f15691deab3778a0e0ae385944689a6864 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Thu, 22 Oct 2020 19:28:09 -0700 Subject: [PATCH 11/56] Get past file validation --- llvm-project | 2 +- tests/utils/stl/test/config.py | 93 ++++++++++++++++--------------- tests/utils/stl/test/features.py | 96 ++++++++++++++++---------------- tests/utils/stl/test/format.py | 2 +- tests/utils/stl/test/params.py | 36 ++++++------ vcpkg | 2 +- 6 files changed, 116 insertions(+), 115 deletions(-) diff --git a/llvm-project b/llvm-project index d66428cb995..cb9ca359772 160000 --- a/llvm-project +++ b/llvm-project @@ -1 +1 @@ -Subproject commit d66428cb995c7a04ecb02951d5021d815fc02b2b +Subproject commit cb9ca3597727bb323576972a6a74b5897125b41a diff --git a/tests/utils/stl/test/config.py b/tests/utils/stl/test/config.py index 998bfe47d04..a02e8038c68 100644 --- a/tests/utils/stl/test/config.py +++ b/tests/utils/stl/test/config.py @@ -1,46 +1,47 @@ -#===----------------------------------------------------------------------===## -# -# 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 os - -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)} +#===----------------------------------------------------------------------===## +# +# 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 os + +def configure(parameters, features, config, lit_config): + # Apply parameters to the configuration first, since parameters are things + # that we request explicitly and which might influence what features are + # implicitly made available next. + for param in parameters: + feature = param.getFeature(config, lit_config.params) + if feature: + feature.enableIn(config) + lit_config.note( + "Enabling Lit feature '{}' as a result of parameter '{}'".format(feature.getName(config), param.name)) + + # Then, apply the automatically-detected features. + printFeatures = [] + for feature in features: + if feature.isSupported(config): + feature.enableIn(config) + printFeatures.append(feature.getName(config)) + printFeatures = ["'{}'".format(f) for f in sorted(printFeatures)] + lit_config.note("Enabling implicitly detected Lit features {}".format(', '.join(printFeatures))) + + # Normalize and validate all subdirectories to be tested + lit_config.test_subdirs[config.name] = [os.path.normpath(subdir) for subdir in lit_config.test_subdirs[config.name]] + for subdir in lit_config.test_subdirs[config.name]: + if not os.path.exists(subdir): + lit_config.fatal("The directory {} does not exist and was marked as a subdirectory to test".format(subdir)) + + lit_config.flags = getattr(lit_config, 'flags', dict()) + lit_config.compile_flags = getattr(lit_config, 'compile_flags', dict()) + lit_config.link_flags = getattr(lit_config, 'link_flags', dict()) + + lit_config.flags[config.name] = [] + lit_config.compile_flags[config.name] = \ + ['/I' + os.path.normpath(dir) for dir in lit_config.include_dirs[config.name]] + lit_config.link_flags[config.name] = \ + ['/LIBPATH:' + os.path.normpath(dir) for dir in lit_config.library_dirs[config.name]] + + lit_config.test_env = {'PATH' : os.path.normpath(lit_config.cxx_runtime)} diff --git a/tests/utils/stl/test/features.py b/tests/utils/stl/test/features.py index 5c1fde07272..fdad9b08f08 100644 --- a/tests/utils/stl/test/features.py +++ b/tests/utils/stl/test/features.py @@ -1,48 +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 == 'x86': - DEFAULT_FEATURES.append(Feature(name='edg')) - - return DEFAULT_FEATURES +#===----------------------------------------------------------------------===// +# +# 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 == 'x86': + DEFAULT_FEATURES.append(Feature(name='edg')) + + return DEFAULT_FEATURES diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 865590a7851..aa0eab01335 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -117,7 +117,7 @@ def _parseScript(self, test): lit.TestRunner.ParserKind.LIST, initial_value=additionalCompileFlags) ] - + script = \ lit.TestRunner.parseIntegratedTestScript(test, additional_parsers=parsers, require_script=False) diff --git a/tests/utils/stl/test/params.py b/tests/utils/stl/test/params.py index 12fe9ad5654..f082f3d1532 100644 --- a/tests/utils/stl/test/params.py +++ b/tests/utils/stl/test/params.py @@ -1,18 +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 tests that take longer to run. This can be useful when running on a very slow device.", - feature=lambda enabled: Feature(name='long_tests') if enabled else None), - ] - - return DEFAULT_PARAMETERS +#===----------------------------------------------------------------------===## +# +# 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 tests that take longer to run. This can be useful when running on a very slow device.", + feature=lambda enabled: Feature(name='long_tests') if enabled else None), + ] + + return DEFAULT_PARAMETERS diff --git a/vcpkg b/vcpkg index 6185aa76504..bff4dd9c944 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 6185aa76504a5025f36754324abf307cc776f3da +Subproject commit bff4dd9c944b9fbad40ec1a36d7c2365287ce0a6 From 352715d2aed1e8b1b9e907e5e742f764296a18d5 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Thu, 22 Oct 2020 19:40:05 -0700 Subject: [PATCH 12/56] That's what I get for not testing x86 --- tests/utils/stl/test/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index 7b4b7355a97..dd339a5e57b 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -152,7 +152,7 @@ def _handleEnvlst(self, litConfig, envlstEntry): targetArch = litConfig.target_arch.casefold() if (targetArch == 'x64'.casefold()): self.compileFlags.append('-m64') - elif (target_arch == 'x86'.casefold()): + elif (targetArch == 'x86'.casefold()): self.compileFlags.append('-m32') self.cxx = os.path.normpath(cxx) From 9bb228a2d7715af9e16431822a8fda4b1463ed13 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 08:41:28 -0700 Subject: [PATCH 13/56] Undo unwanted changes to submodules fixup tests which embed /c flag --- llvm-project | 2 +- tests/utils/stl/test/features.py | 2 +- tests/utils/stl/test/tests.py | 13 +++++++------ vcpkg | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/llvm-project b/llvm-project index cb9ca359772..a668ad92d5e 160000 --- a/llvm-project +++ b/llvm-project @@ -1 +1 @@ -Subproject commit cb9ca3597727bb323576972a6a74b5897125b41a +Subproject commit a668ad92d5e2161e07e1a435a19ea5072f52a989 diff --git a/tests/utils/stl/test/features.py b/tests/utils/stl/test/features.py index fdad9b08f08..3128afd165f 100644 --- a/tests/utils/stl/test/features.py +++ b/tests/utils/stl/test/features.py @@ -42,7 +42,7 @@ def getDefaultFeatures(config, litConfig): litConfig.edg_drop = os.environ[env_var] DEFAULT_FEATURES.append(Feature(name='edg_drop')) - if litConfig.target_arch == 'x86': + if litConfig.target_arch.casefold() == 'x86'.casefold(): DEFAULT_FEATURES.append(Feature(name='edg')) return DEFAULT_FEATURES diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index dd339a5e57b..f275b6bdc28 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -52,6 +52,7 @@ def __init__(self, suite, pathInSuite, litConfig, testConfig, self._handleEnvlst(litConfig, envlstEntry) self._configureTestType() + _, tmpBase = self.getTempPaths() def _configureTestType(self): self.testType = TestType.UNKNOWN @@ -64,13 +65,13 @@ def _configureTestType(self): else: self.testType = self.testType | TestType.PASS - if 'analyze:only' in [flag[1:] for flag in \ - chain(self.flags, self.compileFlags, self.linkFlags)] or \ - filename.endswith('.compile.pass.cpp') or filename.endswith('.compile.fail.cpp'): + 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') or filename.endswith('.link.fail.cpp'): + elif filename.endswith(('.link.pass.cpp', '.link.fail.cpp')): self.testType = self.testType | TestType.LINK - elif filename.endswith('run.fail.cpp') or filename.endswith('run.pass.cpp') or filename == 'test.cpp': + 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 @@ -175,7 +176,7 @@ def _handleEnvlst(self, litConfig, envlstEntry): 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 + self.requires.append('edg') # available for x86, see features.py if not foundStd: Feature('c++14').enableIn(self.config) diff --git a/vcpkg b/vcpkg index bff4dd9c944..6185aa76504 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit bff4dd9c944b9fbad40ec1a36d7c2365287ce0a6 +Subproject commit 6185aa76504a5025f36754324abf307cc776f3da From 0b5cdafb678ebba9a7b8160b97783e146360ff68 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 08:45:50 -0700 Subject: [PATCH 14/56] Resolves GH-1382 --- tests/libcxx/expected_results.txt | 3 --- tests/libcxx/skipped_tests.txt | 3 --- 2 files changed, 6 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 4ec759b4b00..2450d308aab 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -258,9 +258,6 @@ std/utilities/function.objects/negators/not2.depr_in_cxx17.verify.cpp SKIPPED std/utilities/memory/allocator.traits/allocator.traits.members/allocate.verify.cpp SKIPPED std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKIPPED -# GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests -std/strings/string.view/string.view.io/stream_insert_decl_present.compile.pass.cpp SKIPPED - # *** MISSING STL FEATURES *** # C++20 P0355R7 " Calendars And Time Zones" diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index b8e1d482c42..983136fe149 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -258,9 +258,6 @@ utilities\function.objects\negators\not2.depr_in_cxx17.verify.cpp utilities\memory\allocator.traits\allocator.traits.members\allocate.verify.cpp utilities\memory\default.allocator\allocator.members\allocate.verify.cpp -# GH-1382: Our machinery doesn't understand compile-only `.compile.pass.cpp` tests -strings\string.view\string.view.io\stream_insert_decl_present.compile.pass.cpp - # *** MISSING STL FEATURES *** # C++20 P0355R7 " Calendars And Time Zones" From 1d3cc67861729ab97025937e8ed2ecee6c88851f Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 10:22:06 -0700 Subject: [PATCH 15/56] cleanup the new custom format --- tests/std/lit.site.cfg.in | 1 + .../custom_format.py | 4 +- .../custom_format.py | 55 ++++++++----------- .../lit.local.cfg | 9 ++- 4 files changed, 31 insertions(+), 38 deletions(-) diff --git a/tests/std/lit.site.cfg.in b/tests/std/lit.site.cfg.in index ccc358b665d..d23187382e1 100644 --- a/tests/std/lit.site.cfg.in +++ b/tests/std/lit.site.cfg.in @@ -29,6 +29,7 @@ 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@' diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py index 72f419e67d0..1792181ec4c 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py +++ b/tests/std/tests/Dev09_056375_locale_cleanup/custom_format.py @@ -9,12 +9,12 @@ class CustomTestFormat(STLTestFormat): def getBuildSteps(self, test, litConfig, shared): exeSource = test.getSourcePath() - dll_source = os.path.join(os.path.dirname(exeSource), 'TestDll.cpp') + dllSource = os.path.join(os.path.dirname(exeSource), 'TestDll.cpp') outputDir, outputBase = test.getTempPaths() dllOutput = os.path.join(outputDir, 'TestDll.DLL') - cmd = [test.cxx, dll_source, *test.flags, *test.compileFlags, '/Fe' + dllOutput, + cmd = [test.cxx, dllSource, *test.flags, *test.compileFlags, '/Fe' + dllOutput, '/link', '/DLL', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py index 4338a118680..8edeb0f4bdc 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py +++ b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py @@ -1,19 +1,15 @@ # 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 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 +89,31 @@ def getBuildSteps(self, test, lit_config, shared): 'version', ] - compile_test_cpp_with_edg = test.cxx.flags.count('/BE') == 1 - - if compile_test_cpp_with_edg: - test.cxx.flags.remove('/BE') + outputDir, outputBase = test.getTempPaths() + sourcePath = test.getSourcePath() - header_unit_options = [] + compileTestCppWithEdg = '/BE' in itertools.chain(test.flags, test.compileFlags) + if compileTestCppWithEdg: + test.flags.remove('/BE') + test.compileFlags.remove('/BE') - for header in stl_headers: - header_obj_path = output_dir / (header + '.obj') + headerUnitOptions = [] + for header in stlHeaders: + headerObjPath = os.path.join(outputDir, header + '.obj') - header_unit_options.append('/headerUnit') - header_unit_options.append('{0}/{1}={1}.ifc'.format(test.config.cxx_headers, header)) + headerUnitOptions.append('/headerUnit') + headerUnitOptions.append('{0}/{1}={1}.ifc'.format(litConfig.cxx_headers, header)) - if not compile_test_cpp_with_edg: - header_unit_options.append(str(header_obj_path)) + if not compileTestCppWithEdg: + headerUnitOptions.append(headerObjPath) - 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) + cmd = [test.cxx, '/exportHeader', '<{}>'.format(header), '/Fo{}'.format(headerObjPath)] + yield TestStep(cmd, shared.execDir, shared.env, False) - if compile_test_cpp_with_edg: - test.cxx.flags.append('/BE') + if compileTestCppWithEdg: + test.compileFlags.append('/BE') - cmd, out_files, shared.exec_file = \ - test.cxx.executeBasedOnFlagsCmd([source_path], - output_dir, shared.exec_dir, - output_base, header_unit_options, [], []) + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, sourcePath, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, '/link', *test.linkFlags] - yield TestStep(cmd, shared.exec_dir, [source_path], - test.cxx.compile_env) + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg b/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg index 504df778c67..a58f404ef47 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg +++ b/tests/std/tests/P1502R1_standard_library_header_units/lit.local.cfg @@ -1,10 +1,9 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import site +site.addsitedir(os.path.dirname(os.path.dirname(__file__))) import P1502R1_standard_library_header_units.custom_format -config.test_format = \ - P1502R1_standard_library_header_units.custom_format.CustomTestFormat(config.test_format.cxx, - config.test_format.execute_external, - config.test_format.build_executor, - config.test_format.test_executor) +config.test_format = P1502R1_standard_library_header_units.custom_format.CustomTestFormat() From d6eab204baf0c2bb538fd7952ae95308c0a6490a Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 10:31:28 -0700 Subject: [PATCH 16/56] Fix broken custom format --- .../P1502R1_standard_library_header_units/custom_format.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py index 8edeb0f4bdc..dbbf566e04c 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py +++ b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py @@ -107,13 +107,15 @@ def getBuildSteps(self, test, litConfig, shared): if not compileTestCppWithEdg: headerUnitOptions.append(headerObjPath) - cmd = [test.cxx, '/exportHeader', '<{}>'.format(header), '/Fo{}'.format(headerObjPath)] + cmd = [test.cxx, *test.flags, *test.compileFlags, + '/exportHeader', '<{}>'.format(header), '/Fo{}'.format(headerObjPath)] yield TestStep(cmd, shared.execDir, shared.env, False) if compileTestCppWithEdg: test.compileFlags.append('/BE') shared.execFile = outputBase + '.exe' - cmd = [test.cxx, sourcePath, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, '/link', *test.linkFlags] + cmd = [test.cxx, sourcePath, *test.flags, *test.compileFlags, *headerUnitOptions, '/Fe' + shared.execFile, + '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) From f5d374caa588d2a193f8d9b580bbee486870fe61 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 10:40:40 -0700 Subject: [PATCH 17/56] Respect tests getting marked as unsupported --- tests/utils/stl/test/tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index f275b6bdc28..a63d77a52c0 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -124,6 +124,8 @@ def _configureExpectedResult(self, suite, litConfig): self.result = (lit.Test.SKIPPED, 'This test was explicitly marked as skipped') elif self.expectedResult.isFailure: self.xfails = ['*'] + elif self.config.unsupported: + self.result = (lit.Test.UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') def _handleEnvlst(self, litConfig, envlstEntry): envCompiler = envlstEntry.getEnvVal('PM_COMPILER', 'cl') From c332008455e85536d1b1514539e06ce1f633b26c Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 12:28:30 -0700 Subject: [PATCH 18/56] Fix .fail tests --- tests/utils/stl/test/format.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index aa0eab01335..974ddcbbd9f 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -198,7 +198,7 @@ def getBuildSteps(self, test, litConfig, shared): shouldFail = TestType.FAIL in test.testType if TestType.COMPILE in test.testType: cmd = [test.cxx, '/c', test.getSourcePath(), *test.flags, *test.compileFlags] - return TestStep(cmd, shared.execDir, shared.env, shouldFail) + 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] @@ -252,7 +252,7 @@ def execute(self, test, litConfig): buildSetupSteps, buildSteps, testSetupSteps, testSteps = self.getSteps(test, litConfig) - report = '' + report = 'Build setup steps:\n' for step in buildSetupSteps: cmd, out, err, rc = self.runStep(step, litConfig) @@ -266,6 +266,7 @@ def execute(self, test, litConfig): litConfig.note(report) return lit.Test.Result(failVar, report) + report += 'Build steps:\n' for step in buildSteps: cmd, out, err, rc = self.runStep(step, litConfig) @@ -279,6 +280,7 @@ def execute(self, test, litConfig): litConfig.note(report) return lit.Test.Result(failVar, report) + report += 'Test setup steps:\n' for step in testSetupSteps: cmd, out, err, rc = self.runStep(step, litConfig) @@ -292,6 +294,7 @@ def execute(self, test, litConfig): litConfig.note(report) return lit.Test.Result(failVar, report) + report += 'Test steps:\n' for step in testSteps: cmd, out, err, rc = self.runStep(step, litConfig) From d0cb477cf8048916d3c6b76732877bb3c1f5f707 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 14:49:35 -0700 Subject: [PATCH 19/56] STL_EDG_DROP at least does something now + other cleanups --- tests/libcxx/CMakeLists.txt | 1 + tests/libcxx/lit.cfg | 26 +- tests/libcxx/lit.site.cfg.in | 1 - tests/std/lit.cfg | 30 +-- .../custom_format.py | 13 +- .../custom_format.py | 11 +- .../P0607R0_inline_variables/custom_format.py | 13 +- .../custom_format.py | 10 +- .../custom_format.py | 7 + .../custom_format.py | 13 +- tests/tr1/lit.cfg | 30 +-- tests/utils/stl/compiler.py | 211 ---------------- tests/utils/stl/test/executor.py | 235 ------------------ tests/utils/stl/test/format.py | 8 +- tests/utils/stl/test/target_info.py | 45 ---- tests/utils/stl/test/tests.py | 23 +- tests/utils/stl/test/tracing.py | 41 --- 17 files changed, 69 insertions(+), 649 deletions(-) delete mode 100644 tests/utils/stl/compiler.py delete mode 100644 tests/utils/stl/test/executor.py delete mode 100644 tests/utils/stl/test/target_info.py delete mode 100644 tests/utils/stl/test/tracing.py diff --git a/tests/libcxx/CMakeLists.txt b/tests/libcxx/CMakeLists.txt index 215f9cedd27..7abdbdb40e0 100644 --- a/tests/libcxx/CMakeLists.txt +++ b/tests/libcxx/CMakeLists.txt @@ -10,5 +10,6 @@ configure_file( ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) set(LIBCXX_LIT_CONFIG_MAP "map_config(\"${LIBCXX_SOURCE_DIR}/test/lit.cfg.py\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") +string(APPEND LIBCXX_LIT_CONFIG_MAP "map_config(\"${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg\", \"${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg\")\n") set_property(GLOBAL APPEND_STRING PROPERTY STL_LIT_CONFIG_MAP ${LIBCXX_LIT_CONFIG_MAP}) set_property(GLOBAL APPEND PROPERTY STL_LIT_TEST_DIRS "${LIBCXX_SOURCE_DIR}/test/std") diff --git a/tests/libcxx/lit.cfg b/tests/libcxx/lit.cfg index bd6e637ee27..e97953f5b8b 100644 --- a/tests/libcxx/lit.cfg +++ b/tests/libcxx/lit.cfg @@ -1,25 +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")) - -config.name = 'libc++' -config.suffixes = ['.pass.cpp', '.fail.cpp'] - -config.test_exec_root = getattr(config, 'test_exec_root', None) - -if not config.test_exec_root: - import tempfile - config.test_exec_root = tempfile.mkdtemp(prefix=config.name + '-testsuite-') - lit_config.note('Creating temporary directory for tests: %s' % config.test_exec_root) - -config_module_name = getattr(config, 'config_module_name', 'stl.test.config') -config_module = importlib.import_module(config_module_name) - -configuration = config_module.Configuration(lit_config, config) -configuration.configure() -config.test_format = configuration.get_test_format() +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index bae25803316..f88f8670e36 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -16,7 +16,6 @@ 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.expected_results = getattr(lit_config, 'expected_results', dict()) lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) diff --git a/tests/std/lit.cfg b/tests/std/lit.cfg index fc5389e0361..e97953f5b8b 100644 --- a/tests/std/lit.cfg +++ b/tests/std/lit.cfg @@ -1,29 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path -import importlib -import site - -site.addsitedir(str(Path(__file__).parents[1] / "utils")) -site.addsitedir(str(Path(__file__).parent / "tests")) - -config.name = 'std' -config.suffixes.add('test.cpp') - -if config.test_source_root is None: - config.test_source_root = str(Path(__file__).parent) - -config.test_exec_root = getattr(config, 'test_exec_root', None) - -if not config.test_exec_root: - import tempfile - config.test_exec_root = tempfile.mkdtemp(prefix=config.name + '-testsuite-') - lit_config.note('Creating temporary directory for tests: %s' % config.test_exec_root) - -config_module_name = getattr(config, 'config_module_name', 'stl.test.config') -config_module = importlib.import_module(config_module_name) - -configuration = config_module.Configuration(lit_config, config) -configuration.configure() -config.test_format = configuration.get_test_format() +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py index 2c34a4c7020..be002a039f1 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py @@ -4,6 +4,7 @@ import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): @@ -13,13 +14,13 @@ def getBuildSteps(self, test, litConfig, shared): outputDir, outputBase = test.getTempPaths() - if litConfig.edg_drop is not None: - isenseRspPath = outputBase + '.isense.rsp' - test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) + 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] - 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) for step in self._handleIsenseRspFile(test, litConfig): diff --git a/tests/std/tests/GH_000545_include_compare/custom_format.py b/tests/std/tests/GH_000545_include_compare/custom_format.py index 3affd95aeee..2d698f717b2 100644 --- a/tests/std/tests/GH_000545_include_compare/custom_format.py +++ b/tests/std/tests/GH_000545_include_compare/custom_format.py @@ -4,6 +4,7 @@ import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): @@ -16,7 +17,11 @@ def getBuildSteps(self, test, litConfig, shared): if filename.endswith('.cpp'): sourceFiles.append(os.path.join(exeSourceDir, filename)) - shared.execFile = outputBase + '.exe' - cmd = [test.cxx, *sourceFiles, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, - '/link', *test.linkFlags] + 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.execDir, shared.env, False) diff --git a/tests/std/tests/P0607R0_inline_variables/custom_format.py b/tests/std/tests/P0607R0_inline_variables/custom_format.py index 2c34a4c7020..be002a039f1 100644 --- a/tests/std/tests/P0607R0_inline_variables/custom_format.py +++ b/tests/std/tests/P0607R0_inline_variables/custom_format.py @@ -4,6 +4,7 @@ import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): @@ -13,13 +14,13 @@ def getBuildSteps(self, test, litConfig, shared): outputDir, outputBase = test.getTempPaths() - if litConfig.edg_drop is not None: - isenseRspPath = outputBase + '.isense.rsp' - test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) + 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] - 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) for step in self._handleIsenseRspFile(test, litConfig): diff --git a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py index dbbf566e04c..3c7acccbe55 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py +++ b/tests/std/tests/P1502R1_standard_library_header_units/custom_format.py @@ -5,6 +5,7 @@ import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): @@ -114,8 +115,11 @@ def getBuildSteps(self, test, litConfig, shared): if compileTestCppWithEdg: test.compileFlags.append('/BE') - shared.execFile = outputBase + '.exe' - cmd = [test.cxx, sourcePath, *test.flags, *test.compileFlags, *headerUnitOptions, '/Fe' + shared.execFile, - '/link', *test.linkFlags] + 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] yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py b/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py index a35ed2fd2f5..0f08a5e0183 100644 --- a/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py +++ b/tests/std/tests/VSO_0000000_any_calling_conventions/custom_format.py @@ -34,4 +34,11 @@ def getBuildSteps(self, test, litConfig, shared): cmd = [test.cxx, exeSource, aObj, test.callingConventionB, *test.flags, *test.compileFlags, '/Fe' + shared.execFile, '/link', *test.linkFlags] + if TestType.COMPILE in test.testType: + cmd = [test.cxx, '/c', exeSource, aObj, test.callingConventionB, *test.flags, *test.compileFlags] + elif TestType.RUN in test.testType: + shared.execFile = outputBase + '.exe' + cmd = [test.cxx, exeSource, aObj, test.callingConventionB, *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags] + yield TestStep(cmd, shared.execDir, shared.env, False) diff --git a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py index 2c34a4c7020..be002a039f1 100644 --- a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py +++ b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py @@ -4,6 +4,7 @@ import os from stl.test.format import STLTestFormat, TestStep +from stl.test.tests import TestType class CustomTestFormat(STLTestFormat): @@ -13,13 +14,13 @@ def getBuildSteps(self, test, litConfig, shared): outputDir, outputBase = test.getTempPaths() - if litConfig.edg_drop is not None: - isenseRspPath = outputBase + '.isense.rsp' - test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) + 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] - 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) for step in self._handleIsenseRspFile(test, litConfig): diff --git a/tests/tr1/lit.cfg b/tests/tr1/lit.cfg index 0b68aa9276d..e97953f5b8b 100644 --- a/tests/tr1/lit.cfg +++ b/tests/tr1/lit.cfg @@ -1,29 +1,7 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -from pathlib import Path -import importlib -import site - -site.addsitedir(str(Path(__file__).parents[1] / "utils")) -site.addsitedir(str(Path(__file__).parent / "tests")) - -config.name = 'tr1' -config.suffixes.add('test.cpp') - -if config.test_source_root is None: - config.test_source_root = str(Path(__file__).parent) - -config.test_exec_root = getattr(config, 'test_exec_root', None) - -if not config.test_exec_root: - import tempfile - config.test_exec_root = tempfile.mkdtemp(prefix=config.name + '-testsuite-') - lit_config.note('Creating temporary directory for tests: %s' % config.test_exec_root) - -config_module_name = getattr(config, 'config_module_name', 'stl.test.config') -config_module = importlib.import_module(config_module_name) - -configuration = config_module.Configuration(lit_config, config) -configuration.configure() -config.test_format = configuration.get_test_format() +lit_config.fatal( + "You seem to be running Lit directly -- you should be running Lit through " + "/tests/utils/stl-lit/stl-lit.py, which will ensure that the right Lit configuration " + "file is used.") diff --git a/tests/utils/stl/compiler.py b/tests/utils/stl/compiler.py deleted file mode 100644 index ff5d4ef3bdd..00000000000 --- a/tests/utils/stl/compiler.py +++ /dev/null @@ -1,211 +0,0 @@ -#===----------------------------------------------------------------------===## -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===## - -from itertools import chain -from pathlib import Path -from typing import List -import os - -import stl.util - - -class CXXCompiler: - CM_Default = 0 - CM_PreProcess = 1 - CM_Compile = 2 - CM_Link = 3 - CM_Analyze = 4 - - def __init__(self, path, flags=None, compile_flags=None, - link_flags=None, compile_env=None, edg_drop=None): - self.path = path - if path is not None: - self.name = os.path.basename(path).split('.')[0] - else: - self.name = None - - self.compile_flags = compile_flags or [] - self.flags = flags or [] - self.link_flags = link_flags or [] - - self.compile_env = compile_env - self.edg_drop = edg_drop - - def _basicCmd(self, source_files: List[Path], out: Path, - mode=CM_Default, flags=[], compile_flags=[], link_flags=[], - skip_mode_flags=False): - out_files = [] - cmd = [] - - if out is not None: - out_files.append(out) - - cmd.append(self.path) - - if mode == self.CM_PreProcess: - if out is not None: - cmd.extend(('/P', '/Fi' + str(out))) - else: - cmd.append('/EP') - elif mode == self.CM_Compile: - if not skip_mode_flags: - cmd.append('/c') - if out is not None and len(source_files) <= 1: - cmd.append('/Fo' + str(out)) - else: - for source_file in source_files: - out_files.append( - Path(source_file.name.rsplit('.', 1)[0] + '.obj')) - elif mode == self.CM_Analyze: - if not skip_mode_flags: - cmd.append('/analyze:only') - if out is not None: - cmd.append('/analyze:log' + str(out)) - else: - for source_file in source_files: - out_files.append( - Path(source_file.name.rsplit('.', 1)[0] + - '.nativecodeanalysis.xml')) - elif out is not None: - cmd.append('/Fe' + str(out)) - - if len(source_files) <= 1: - out_obj = str(out).rsplit('.', 1)[0] + '.obj' - cmd.append('/Fo' + out_obj) - out_files.append(Path(out_obj)) - else: - for source_file in source_files: - out_files.append( - Path(source_file.name.rsplit('.', 1)[0] + '.obj')) - - if mode in (self.CM_Analyze, self.CM_Compile, self.CM_Default): - cmd.extend(self.compile_flags) - cmd.extend(compile_flags) - - cmd.extend(self.flags) - cmd.extend(flags) - cmd.extend([str(file) for file in source_files]) - - if mode in (self.CM_Default, self.CM_Link): - cmd.append('/link') - cmd.extend(self.link_flags) - cmd.extend(link_flags) - - return cmd, out_files - - def executeBasedOnFlagsCmd(self, source_files, out_dir, cwd=None, - out_base=None, flags=[], compile_flags=[], - link_flags=[]): - mode = self.CM_Default - exec_file = None - output_file = None - - if out_base is None: - out_base = source_files[0].name.rsplit('.', 1)[0] - - add_analyze_output = False - for flag in chain(flags, self.flags): - flag = flag[1:] - - if flag == 'c': - mode = self.CM_Compile - exec_file = None - output_file = out_dir / (out_base + '.obj') - elif flag.startswith('Fe'): - output_file = Path(flag[2:]) - exec_file = output_file - elif flag == 'analyze:only': - mode = self.CM_Analyze - output_file = out_dir / (out_base + '.nativecodeanalysis.xml') - exec_file = None - elif flag.startswith('analyze') and flag[-1] != '-': - add_analyze_output = True - - if mode is self.CM_Default and output_file is None: - output_file = out_dir / (out_base + '.exe') - exec_file = output_file - - if add_analyze_output and mode != self.CM_Analyze: - flags.append('/analyze:log' + - str(out_dir / (out_base + '.nativecodeanalysis.xml'))) - - cmd, out_files = self._basicCmd(source_files, output_file, mode, flags, - compile_flags, link_flags, True) - return cmd, out_files, exec_file - - def executeBasedOnFlags(self, source_files, out_dir, cwd=None, - out_base=None, flags=[], compile_flags=[], - link_flags=[]): - cmd, out_files, exec_file = \ - self.executeBasedOnFlagsCmd(source_files, out_dir, cwd, out_base, - flags, compile_flags, link_flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc, out_files, exec_file - - def preprocessCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[], mode=self.CM_PreProcess) - - def compileCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[], mode=self.CM_Compile) - - def linkCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[], mode=self.CM_Link) - - def compileLinkCmd(self, source_files, out=None, flags=[]): - return self._basicCmd(source_files, out, flags=flags, compile_flags=[], - link_flags=[]) - - def preprocess(self, source_files, out=None, flags=[], cwd=None): - cmd, _ = self.preprocessCmd(source_files, out, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def compile(self, source_files, out=None, flags=[], cwd=None): - cmd, _ = self.compileCmd(source_files, out, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def link(self, source_files, exec_path=None, flags=[], cwd=None): - cmd, _ = self.linkCmd(source_files, exec_path, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def compileLink(self, source_files, exec_path=None, flags=[], - cwd=None): - cmd, _ = self.compileLinkCmd(source_files, exec_path, flags) - out, err, rc = stl.util.executeCommand(cmd, env=self.compile_env, - cwd=cwd) - return cmd, out, err, rc - - def compileLinkTwoSteps(self, source_file, out=None, object_file=None, - flags=[], cwd=None): - if not isinstance(source_file, str): - raise TypeError('This function only accepts a single input file') - if object_file is None: - # Create, use, and delete a temporary object file if none is given. - def with_fn(): return stl.util.guardedTempFilename(suffix='.obj') - else: - # Otherwise wrap the filename in a context manager function. - def with_fn(): return stl.util.nullContext(object_file) - with with_fn() as object_file: - cc_cmd, cc_stdout, cc_stderr, rc = self.compile( - source_file, object_file, flags=flags, cwd=cwd) - if rc != 0: - return cc_cmd, cc_stdout, cc_stderr, rc - - link_cmd, link_stdout, link_stderr, rc = self.link( - object_file, exec_path=out, flags=flags, cwd=cwd) - return (cc_cmd + ['&'] + link_cmd, cc_stdout + link_stdout, - cc_stderr + link_stderr, rc) diff --git a/tests/utils/stl/test/executor.py b/tests/utils/stl/test/executor.py deleted file mode 100644 index cee2b71bf7f..00000000000 --- a/tests/utils/stl/test/executor.py +++ /dev/null @@ -1,235 +0,0 @@ -#===----------------------------------------------------------------------===## -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===## - -import platform -import os -import posixpath -import ntpath - -from stl.test import tracing -from stl.util import executeCommand - - -class Executor: - def __init__(self): - self.target_info = None - - def run(self, cmd, local_cwd, file_deps=None, env=None): - """Execute a command. - Be very careful not to change shared state in this function. - Executor objects are shared between python processes in `lit -jN`. - Args: - cmd: [str]: subprocess.call style command - local_cwd: str: Local path to the working directory - file_deps: [str]: Files required by the cmd - env: {str: str}: Environment variables to execute under - Returns: - cmd, out, err, exitCode - """ - raise NotImplementedError - - def merge_environments(self, current_env, updated_env): - """Merges two execution environments. - - If both environments contain the PATH variables, they are also merged - using the proper separator. - """ - result_env = dict(current_env) - for k, v in updated_env.items(): - if k == 'PATH' and self.target_info: - self.target_info.add_path(result_env, v) - else: - result_env[k] = v - return result_env - - -class LocalExecutor(Executor): - def __init__(self): - super(LocalExecutor, self).__init__() - self.is_windows = platform.system() == 'Windows' - - def run(self, cmd, work_dir='.', file_deps=None, env=None): - if str(work_dir) == '.': - work_dir = os.getcwd() - - if env: - env = self.merge_environments(os.environ, env) - - out, err, rc = executeCommand(cmd, cwd=work_dir, env=env) - return (cmd, out, err, rc) - - -class PrefixExecutor(Executor): - """Prefix an executor with some other command wrapper. - - Most useful for setting ulimits on commands, or running an emulator like - qemu and valgrind. - """ - def __init__(self, commandPrefix, chain): - super(PrefixExecutor, self).__init__() - - self.commandPrefix = commandPrefix - self.chain = chain - - def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): - cmd = cmd or [exe_path] - return self.chain.run(exe_path, self.commandPrefix + cmd, work_dir, - file_deps, env=env) - - -class PostfixExecutor(Executor): - """Postfix an executor with some args.""" - def __init__(self, commandPostfix, chain): - super(PostfixExecutor, self).__init__() - - self.commandPostfix = commandPostfix - self.chain = chain - - def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): - cmd = cmd or [exe_path] - return self.chain.run(cmd + self.commandPostfix, work_dir, file_deps, - env=env) - - -class RemoteExecutor(Executor): - def __init__(self): - super(RemoteExecutor, self).__init__() - self.local_run = executeCommand - - def remote_temp_dir(self): - return self._remote_temp(True) - - def remote_temp_file(self): - return self._remote_temp(False) - - def _remote_temp(self, is_dir): - raise NotImplementedError() - - def copy_in(self, local_srcs, remote_dsts): - # This could be wrapped up in a tar->scp->untar for performance - # if there are lots of files to be copied/moved - for src, dst in zip(local_srcs, remote_dsts): - self._copy_in_file(src, dst) - - def _copy_in_file(self, src, dst): - raise NotImplementedError() - - def delete_remote(self, remote): - try: - self._execute_command_remote(['rm', '-rf', remote]) - except OSError: - # TRANSITION: Log failure to delete? - pass - - def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None): - target_exe_path = None - target_cwd = None - try: - target_cwd = self.remote_temp_dir() - executable_name = 'libcxx_test.exe' - if self.target_info.is_windows(): - target_exe_path = ntpath.join(target_cwd, executable_name) - else: - target_exe_path = posixpath.join(target_cwd, executable_name) - - if cmd: - # Replace exe_path with target_exe_path. - cmd = [c if c != exe_path else target_exe_path for c in cmd] - else: - cmd = [target_exe_path] - - srcs = [exe_path] - dsts = [target_exe_path] - if file_deps is not None: - dev_paths = [os.path.join(target_cwd, os.path.basename(f)) - for f in file_deps] - srcs.extend(file_deps) - dsts.extend(dev_paths) - self.copy_in(srcs, dsts) - - # When testing executables that were cross-compiled on Windows for - # Linux, we may need to explicitly set the execution permission to - # avoid the 'Permission denied' error: - chmod_cmd = ['chmod', '+x', target_exe_path] - - return self._execute_command_remote(chmod_cmd + ['&&'] + cmd, - target_cwd, - env) - finally: - if target_cwd: - self.delete_remote(target_cwd) - - def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): - raise NotImplementedError() - - -class SSHExecutor(RemoteExecutor): - def __init__(self, host, username=None): - super(SSHExecutor, self).__init__() - - self.user_prefix = username + '@' if username else '' - self.host = host - self.scp_command = 'scp' - self.ssh_command = 'ssh' - - if False: - self.local_run = tracing.trace_function( - self.local_run, log_calls=True, log_results=True, - label='ssh_local') - - def _remote_temp(self, is_dir): - # TRANSITION: detect what the target system is, and use the correct - # mktemp command for it. (linux and darwin differ here, and I'm - # sure windows has another way to do it) - - # Not sure how to do suffix on osx yet - dir_arg = '-d' if is_dir else '' - cmd = 'mktemp -q {} /tmp/stl.XXXXXXXXXX'.format(dir_arg) - _, temp_path, err, exitCode = self._execute_command_remote([cmd]) - temp_path = temp_path.strip() - if exitCode != 0: - raise RuntimeError(err) - return temp_path - - def _copy_in_file(self, src, dst): - scp = self.scp_command - remote = self.host - remote = self.user_prefix + remote - cmd = [scp, '-p', src, remote + ':' + dst] - self.local_run(cmd) - - def _export_command(self, env): - if not env: - return [] - - export_cmd = ['export'] - - for k, v in env.items(): - v = v.replace('\\', '\\\\') - if k == 'PATH': - # Pick up the existing paths, so we don't lose any commands - if self.target_info and self.target_info.is_windows(): - export_cmd.append('PATH="%s;%PATH%"' % v) - else: - export_cmd.append('PATH="%s:$PATH"' % v) - else: - export_cmd.append('"%s"="%s"' % (k, v)) - - return export_cmd - - def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): - remote = self.user_prefix + self.host - ssh_cmd = [self.ssh_command, '-oBatchMode=yes', remote] - export_cmd = self._export_command(env) - remote_cmd = ' '.join(cmd) - if export_cmd: - remote_cmd = ' '.join(export_cmd) + ' && ' + remote_cmd - if remote_work_dir != '.': - remote_cmd = 'cd ' + remote_work_dir + ' && ' + remote_cmd - out, err, rc = self.local_run(ssh_cmd + [remote_cmd]) - return (remote_cmd, out, err, rc) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 974ddcbbd9f..fc2fbedcd96 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -129,8 +129,8 @@ def _parseScript(self, test): test.fileDependencies.extend(fileDependencies) def _handleIsenseRspFile(self, test, litConfig): - if litConfig.edg_drop is not None: - with open(isenseRspPath) as f: + 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 @@ -191,10 +191,6 @@ def getBuildSteps(self, test, litConfig, shared): filename = test.path_in_suite[-1] _, tmpBase = test.getTempPaths() - if litConfig.edg_drop is not None: - isenseRspPath = tmpBase + '.isense.rsp' - test.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + isenseRspPath]) - shouldFail = TestType.FAIL in test.testType if TestType.COMPILE in test.testType: cmd = [test.cxx, '/c', test.getSourcePath(), *test.flags, *test.compileFlags] diff --git a/tests/utils/stl/test/target_info.py b/tests/utils/stl/test/target_info.py deleted file mode 100644 index 3c8dce3e337..00000000000 --- a/tests/utils/stl/test/target_info.py +++ /dev/null @@ -1,45 +0,0 @@ -#===----------------------------------------------------------------------===// -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===// - -import locale - - -def _test_locale(loc): - assert loc is not None - default_locale = locale.setlocale(locale.LC_ALL) - try: - locale.setlocale(locale.LC_ALL, loc) - return True - except locale.Error: - return False - finally: - locale.setlocale(locale.LC_ALL, default_locale) - - -class WindowsLocalTI: - def __init__(self, lit_config): - self.features = set() - self._add_common_locales(lit_config) - - def _add_common_locales(self, lit_config): - locales = [ - ('en_US.UTF-8', 'English_United States.1252'), - ('fr_FR.UTF-8', 'French_France.1252'), - ('ru_RU.UTF-8', 'Russian_Russia.1251'), - ('zh_CN.UTF-8', 'Chinese_China.936'), - ('fr_CA.ISO8859-1', 'French_Canada.1252'), - ('cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250') - ] - - for loc_id, loc_name in locales: - if _test_locale(loc_name): - self.features.add('locale.{0}'.format(loc_id)) - else: - lit_config.note('The locale {0} is not supported by ' - 'your platform. Some tests will be ' - 'unsupported.'.format(loc_name)) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index a63d77a52c0..2eefe92ef59 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -9,18 +9,14 @@ from enum import Flag, auto from itertools import chain -from pathlib import Path import copy import os -import pipes import shutil from lit.Test import SKIPPED, Test, UNRESOLVED, UNSUPPORTED from libcxx.test.dsl import Feature import lit -from stl.compiler import CXXCompiler - _compilerPathCache = dict() @@ -41,10 +37,10 @@ def __init__(self, suite, pathInSuite, litConfig, testConfig, self.envNum = envNum self.fileDependencies = [] self.flags = [] + self.isenseRspPath = None self.linkFlags = [] self.testType = None - Test.__init__(self, suite, pathInSuite, copy.deepcopy(testConfig), - None) + Test.__init__(self, suite, pathInSuite, copy.deepcopy(testConfig), None) self._configureExpectedResult(suite, litConfig) if self.result: @@ -109,13 +105,11 @@ def _configureExpectedResult(self, suite, litConfig): self.expectedResult = litConfig.expected_results[self.config.name][testName] else: currentPrefix = "" - for prefix, result in \ - litConfig.expected_results.get(self.config.name, dict()).items(): + 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): + elif testName.startswith(prefix) and len(prefix) > len(currentPrefix): currentPrefix = prefix self.expectedResult = result @@ -184,8 +178,13 @@ def _handleEnvlst(self, litConfig, envlstEntry): Feature('c++14').enableIn(self.config) self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17= ') - if 'edg_drop' in self.config.available_features and not 'edg' in self.requires: - self.result = lit.Test.Result(UNSUPPORTED, "We only run /BE tests with the edg drop") + if 'edg_drop' in self.config.available_features: + if not 'edg' in self.requires: + self.result = lit.Test.Result(UNSUPPORTED, "We only run /BE tests with the edg drop") + else: + _, tmpBase = self.getTempPaths() + self.isenseRspPath = tmpBase + '.isense.rsp' + self.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + self.isenseRspPath]) class LibcxxTest(STLTest): diff --git a/tests/utils/stl/test/tracing.py b/tests/utils/stl/test/tracing.py deleted file mode 100644 index 8871c7ef638..00000000000 --- a/tests/utils/stl/test/tracing.py +++ /dev/null @@ -1,41 +0,0 @@ -#===----------------------------------------------------------------------===## -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===----------------------------------------------------------------------===## - -import inspect - - -def trace_function(function, log_calls, log_results, label=''): - def wrapper(*args, **kwargs): - kwarg_strs = ['{}={}'.format(k, v) for (k, v) in kwargs] - arg_str = ', '.join([str(a) for a in args] + kwarg_strs) - call_str = '{}({})'.format(function.__name__, arg_str) - - # Perform the call itself, logging before, after, and anything thrown. - try: - if log_calls: - print('{}: Calling {}'.format(label, call_str)) - res = function(*args, **kwargs) - if log_results: - print('{}: {} -> {}'.format(label, call_str, res)) - return res - except Exception as ex: - if log_results: - print('{}: {} raised {}'.format(label, call_str, type(ex))) - raise ex - - return wrapper - - -def trace_object(obj, log_calls, log_results, label=''): - for name, member in inspect.getmembers(obj): - if inspect.ismethod(member): - # Skip meta-functions, decorate everything else - if not member.__name__.startswith('__'): - setattr(obj, name, trace_function(member, log_calls, - log_results, label)) - return obj From 9f400b0b2d2f141ebed15c9ff0fe42daaa5bc8d2 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 15:07:13 -0700 Subject: [PATCH 20/56] Make handling the intellisense response file its own step type --- .../custom_format.py | 3 --- .../P0607R0_inline_variables/custom_format.py | 3 --- .../custom_format.py | 3 --- tests/utils/stl/test/format.py | 23 +++++++++++++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py index be002a039f1..fa2efc4372f 100644 --- a/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py +++ b/tests/std/tests/Dev09_172666_tr1_tuple_odr/custom_format.py @@ -22,6 +22,3 @@ def getBuildSteps(self, test, litConfig, shared): '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - - for step in self._handleIsenseRspFile(test, litConfig): - yield step diff --git a/tests/std/tests/P0607R0_inline_variables/custom_format.py b/tests/std/tests/P0607R0_inline_variables/custom_format.py index be002a039f1..fa2efc4372f 100644 --- a/tests/std/tests/P0607R0_inline_variables/custom_format.py +++ b/tests/std/tests/P0607R0_inline_variables/custom_format.py @@ -22,6 +22,3 @@ def getBuildSteps(self, test, litConfig, shared): '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - - for step in self._handleIsenseRspFile(test, litConfig): - yield step diff --git a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py index be002a039f1..fa2efc4372f 100644 --- a/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py +++ b/tests/std/tests/VSO_0000000_matching_npos_address/custom_format.py @@ -22,6 +22,3 @@ def getBuildSteps(self, test, litConfig, shared): '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - - for step in self._handleIsenseRspFile(test, litConfig): - yield step diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index fc2fbedcd96..edf9b2504c1 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -128,7 +128,7 @@ def _parseScript(self, test): test.compileFlags.extend(additionalCompileFlags) test.fileDependencies.extend(fileDependencies) - def _handleIsenseRspFile(self, test, litConfig): + def _handleIsenseRspFile(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] @@ -177,6 +177,7 @@ class SharedState: return \ self.getBuildSetupSteps(test, litConfig, shared), \ self.getBuildSteps(test, litConfig, shared), \ + self._handleIsenseRspFile(test, litConfig, shared), \ self.getTestSetupSteps(test, litConfig, shared), \ self.getTestSteps(test, litConfig, shared) @@ -209,9 +210,6 @@ def getBuildSteps(self, test, litConfig, shared): '/Fe' + shared.execFile, '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - for step in self._handleIsenseRspFile(test, litConfig): - yield step - def getTestSetupSteps(self, test, litConfig, shared): if TestType.RUN in test.testType: for dependency in test.fileDependencies: @@ -246,7 +244,8 @@ def execute(self, test, litConfig): failVar = lit.Test.FAIL passVar = lit.Test.PASS - buildSetupSteps, buildSteps, testSetupSteps, testSteps = self.getSteps(test, litConfig) + buildSetupSteps, buildSteps, handleIsenseRspFile, testSetupSteps, testSteps = \ + self.getSteps(test, litConfig) report = 'Build setup steps:\n' for step in buildSetupSteps: @@ -276,6 +275,20 @@ def execute(self, test, litConfig): litConfig.note(report) return lit.Test.Result(failVar, report) + # The following block is for internal use only + if litConfig.edg_drop: + report += 'Intellisense response file steps:\n' + for step in handleIsenseRspFile: + if step.shouldFail and rc == 0: + report += 'Intellisense response step succeeded unexpectedly.\n' + elif rc != 0: + report += 'Intellisense response 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): + litConfig.note(report) + return lit.Test.Result(failVar, report) + report += 'Test setup steps:\n' for step in testSetupSteps: cmd, out, err, rc = self.runStep(step, litConfig) From dd9a2a2e5c281610cc8e3acd005702588b2e5d4c Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 15:46:11 -0700 Subject: [PATCH 21/56] Make all compile-only tests compile only --- .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../Dev11_0272959_make_signed/{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../tests/Dev11_0704582_ratio/{test.cpp => test.compile.pass.cpp} | 0 .../GH_000890_pow_template/{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../P0896R4_ranges_subrange/{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../tests/VSO_0180469_ptr_cat/{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../VSO_0493909_is_aggregate/{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 .../{test.cpp => test.compile.pass.cpp} | 0 38 files changed, 0 insertions(+), 0 deletions(-) rename tests/std/tests/Dev08_527068_scl_no_exceptions/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev10_609053_ctype_char_table_size/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev10_709168_marking_iterators_as_checked/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0000000_include_each_header_alone/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0272959_make_signed/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0437519_container_requirements/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0453373_codecvt_compiles/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0483851_vector_debug_allocator_use/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/Dev11_0704582_ratio/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/GH_000890_pow_template/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0758R1_is_nothrow_convertible/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0896R4_ranges_algorithm_machinery/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0896R4_ranges_subrange/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P0896R4_ranges_test_machinery/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/P1423R3_char8_t_remediation/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_fancy_pointers/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_containers/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_cvt/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_iterators_misc/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_instantiate_type_traits/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0000000_strengthened_noexcept/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0157762_feature_test_macros/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0180469_ptr_cat/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0191296_allocator_construct/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0493909_is_aggregate/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0527559_pragma_managed/{test.cpp => test.compile.pass.cpp} (100%) rename tests/std/tests/VSO_0938757_attribute_order/{test.cpp => test.compile.pass.cpp} (100%) diff --git a/tests/std/tests/Dev08_527068_scl_no_exceptions/test.cpp b/tests/std/tests/Dev08_527068_scl_no_exceptions/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev08_527068_scl_no_exceptions/test.cpp rename to tests/std/tests/Dev08_527068_scl_no_exceptions/test.compile.pass.cpp diff --git a/tests/std/tests/Dev10_609053_ctype_char_table_size/test.cpp b/tests/std/tests/Dev10_609053_ctype_char_table_size/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev10_609053_ctype_char_table_size/test.cpp rename to tests/std/tests/Dev10_609053_ctype_char_table_size/test.compile.pass.cpp diff --git a/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.cpp b/tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.cpp rename to tests/std/tests/Dev10_709168_marking_iterators_as_checked/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0000000_include_each_header_alone/test.cpp b/tests/std/tests/Dev11_0000000_include_each_header_alone/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0000000_include_each_header_alone/test.cpp rename to tests/std/tests/Dev11_0000000_include_each_header_alone/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0272959_make_signed/test.cpp b/tests/std/tests/Dev11_0272959_make_signed/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0272959_make_signed/test.cpp rename to tests/std/tests/Dev11_0272959_make_signed/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0437519_container_requirements/test.cpp b/tests/std/tests/Dev11_0437519_container_requirements/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0437519_container_requirements/test.cpp rename to tests/std/tests/Dev11_0437519_container_requirements/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0453373_codecvt_compiles/test.cpp b/tests/std/tests/Dev11_0453373_codecvt_compiles/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0453373_codecvt_compiles/test.cpp rename to tests/std/tests/Dev11_0453373_codecvt_compiles/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.cpp b/tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.cpp rename to tests/std/tests/Dev11_0483851_vector_debug_allocator_use/test.compile.pass.cpp diff --git a/tests/std/tests/Dev11_0704582_ratio/test.cpp b/tests/std/tests/Dev11_0704582_ratio/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/Dev11_0704582_ratio/test.cpp rename to tests/std/tests/Dev11_0704582_ratio/test.compile.pass.cpp diff --git a/tests/std/tests/GH_000890_pow_template/test.cpp b/tests/std/tests/GH_000890_pow_template/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/GH_000890_pow_template/test.cpp rename to tests/std/tests/GH_000890_pow_template/test.compile.pass.cpp diff --git a/tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.cpp b/tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.cpp rename to tests/std/tests/P0357R3_supporting_incomplete_types_in_reference_wrapper/test.compile.pass.cpp diff --git a/tests/std/tests/P0758R1_is_nothrow_convertible/test.cpp b/tests/std/tests/P0758R1_is_nothrow_convertible/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0758R1_is_nothrow_convertible/test.cpp rename to tests/std/tests/P0758R1_is_nothrow_convertible/test.compile.pass.cpp diff --git a/tests/std/tests/P0896R4_ranges_algorithm_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_algorithm_machinery/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0896R4_ranges_algorithm_machinery/test.cpp rename to tests/std/tests/P0896R4_ranges_algorithm_machinery/test.compile.pass.cpp diff --git a/tests/std/tests/P0896R4_ranges_subrange/test.cpp b/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0896R4_ranges_subrange/test.cpp rename to tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp diff --git a/tests/std/tests/P0896R4_ranges_test_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P0896R4_ranges_test_machinery/test.cpp rename to tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp diff --git a/tests/std/tests/P1423R3_char8_t_remediation/test.cpp b/tests/std/tests/P1423R3_char8_t_remediation/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/P1423R3_char8_t_remediation/test.cpp rename to tests/std/tests/P1423R3_char8_t_remediation/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_fancy_pointers/test.cpp b/tests/std/tests/VSO_0000000_fancy_pointers/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_fancy_pointers/test.cpp rename to tests/std/tests/VSO_0000000_fancy_pointers/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_16_difference_type_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_32_difference_type_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_64_difference_type_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_int_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_int_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_1/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.cpp b/tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_algorithms_nontrivial_2/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_containers/test.cpp b/tests/std/tests/VSO_0000000_instantiate_containers/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_containers/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_containers/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_cvt/test.cpp b/tests/std/tests/VSO_0000000_instantiate_cvt/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_cvt/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_cvt/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.cpp b/tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_iterators_misc/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_instantiate_type_traits/test.cpp b/tests/std/tests/VSO_0000000_instantiate_type_traits/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_instantiate_type_traits/test.cpp rename to tests/std/tests/VSO_0000000_instantiate_type_traits/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0000000_strengthened_noexcept/test.cpp b/tests/std/tests/VSO_0000000_strengthened_noexcept/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0000000_strengthened_noexcept/test.cpp rename to tests/std/tests/VSO_0000000_strengthened_noexcept/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0157762_feature_test_macros/test.cpp rename to tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp b/tests/std/tests/VSO_0180469_ptr_cat/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0180469_ptr_cat/test.cpp rename to tests/std/tests/VSO_0180469_ptr_cat/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0191296_allocator_construct/test.cpp b/tests/std/tests/VSO_0191296_allocator_construct/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0191296_allocator_construct/test.cpp rename to tests/std/tests/VSO_0191296_allocator_construct/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0493909_is_aggregate/test.cpp b/tests/std/tests/VSO_0493909_is_aggregate/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0493909_is_aggregate/test.cpp rename to tests/std/tests/VSO_0493909_is_aggregate/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0527559_pragma_managed/test.cpp b/tests/std/tests/VSO_0527559_pragma_managed/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0527559_pragma_managed/test.cpp rename to tests/std/tests/VSO_0527559_pragma_managed/test.compile.pass.cpp diff --git a/tests/std/tests/VSO_0938757_attribute_order/test.cpp b/tests/std/tests/VSO_0938757_attribute_order/test.compile.pass.cpp similarity index 100% rename from tests/std/tests/VSO_0938757_attribute_order/test.cpp rename to tests/std/tests/VSO_0938757_attribute_order/test.compile.pass.cpp From 331017e9ea825fd0b340383894b0ef109da7da06 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Fri, 23 Oct 2020 15:47:45 -0700 Subject: [PATCH 22/56] Actually find tests with new suffix --- tests/std/lit.site.cfg.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/lit.site.cfg.in b/tests/std/lit.site.cfg.in index d23187382e1..9a2de0aa09b 100644 --- a/tests/std/lit.site.cfg.in +++ b/tests/std/lit.site.cfg.in @@ -12,7 +12,7 @@ import stl.test.format import stl.test.params config.name = 'std' -config.suffixes = ['test[.]cpp$'] +config.suffixes = ['test[.]cpp$', 'test[.]compile[.]pass[.]cpp$'] config.test_exec_root = "@STD_TEST_OUTPUT_DIR@" config.test_format = stl.test.format.STLTestFormat() From 74660fd7ba6b2f33098cec0654038350914b4b41 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Thu, 29 Oct 2020 07:21:20 -0700 Subject: [PATCH 23/56] Update format.py --- tests/utils/stl/test/format.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index edf9b2504c1..4c8c6fc60a7 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -279,6 +279,8 @@ def execute(self, test, litConfig): if litConfig.edg_drop: report += 'Intellisense response file steps:\n' for step in handleIsenseRspFile: + cmd, out, err, rc = self.runStep(step, litConfig) + if step.shouldFail and rc == 0: report += 'Intellisense response step succeeded unexpectedly.\n' elif rc != 0: From be7e4a44f73d7c8e9ea4a12fa86bd9c3866683ce Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Sat, 31 Oct 2020 22:35:40 -0700 Subject: [PATCH 24/56] Fix a bug that STL found --- tests/libcxx/lit.site.cfg.in | 1 + tests/utils/stl/test/format.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index f88f8670e36..85638dae992 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -16,6 +16,7 @@ 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/std' lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 4c8c6fc60a7..b476e31477f 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -101,7 +101,6 @@ def getTestsInDirectory(self, testSuite, pathInSuite, litConfig, localConfig, te litConfig.fatal("Could not find an env.lst file.") for envEntry, envNum in zip(envEntries, itertools.count()): - yield testClass(testSuite, pathInSuite + (filename,), litConfig, localConfig, envEntry, formatString.format(envNum)) From bad25da0f0db01085be563e8d642949b0fd6fd7f Mon Sep 17 00:00:00 2001 From: Ben Craig Date: Sun, 1 Nov 2020 15:22:13 -0600 Subject: [PATCH 25/56] Rebasing kernel harness on new test infrastructure --- CMakeLists.txt | 1 + tests/CMakeLists.txt | 3 + tests/libcxx/lit.site.cfg.in | 7 + tests/std/lit.site.cfg.in | 7 + tests/tr1/lit.site.cfg.in | 7 + tests/utils/kernel/CMakeLists.txt | 45 +++++ tests/utils/kernel/generateMsvcCert.ps1 | 27 +++ tests/utils/kernel/inc/assert.h | 4 + tests/utils/kernel/inc/cassert | 21 +++ .../inc/stl_kernel/kernel_test_constants.h | 8 + .../utils/kernel/inc/stl_kernel/stl_kernel.h | 19 ++ .../utils/kernel/src/stl_kernel/doAssert.cpp | 34 ++++ .../kernel/src/stl_kernel/stl_kernel.cpp | 168 ++++++++++++++++++ .../utils/kernel/src/stl_kernel/test_decls.h | 11 ++ .../kernel/src/stl_kernel_loader/install.cpp | 116 ++++++++++++ .../kernel/src/stl_kernel_loader/install.h | 33 ++++ .../kernel/src/stl_kernel_loader/testapp.cpp | 91 ++++++++++ tests/utils/stl/test/config.py | 15 ++ tests/utils/stl/test/format.py | 58 +++++- 19 files changed, 670 insertions(+), 5 deletions(-) create mode 100644 tests/utils/kernel/CMakeLists.txt create mode 100644 tests/utils/kernel/generateMsvcCert.ps1 create mode 100644 tests/utils/kernel/inc/assert.h create mode 100644 tests/utils/kernel/inc/cassert create mode 100644 tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h create mode 100644 tests/utils/kernel/inc/stl_kernel/stl_kernel.h create mode 100644 tests/utils/kernel/src/stl_kernel/doAssert.cpp create mode 100644 tests/utils/kernel/src/stl_kernel/stl_kernel.cpp create mode 100644 tests/utils/kernel/src/stl_kernel/test_decls.h create mode 100644 tests/utils/kernel/src/stl_kernel_loader/install.cpp create mode 100644 tests/utils/kernel/src/stl_kernel_loader/install.h create mode 100644 tests/utils/kernel/src/stl_kernel_loader/testapp.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5029bd03aec..233c45a108b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ if("${Boost_VERSION}" VERSION_LESS "${VCLIBS_MIN_BOOST_VERSION}") endif() option(BUILD_TESTING "Enable testing" ON) +option(STL_IS_KERNEL "Enable kernel testing" OFF) set(VCLIBS_SUFFIX "_oss" CACHE STRING "suffix for built DLL names to avoid conflicts with distributed DLLs") if(NOT DEFINED VCLIBS_TARGET_ARCHITECTURE) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fab5573e6b1..0c99e748c9b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,9 @@ set(LIBCXX_SOURCE_DIR "${LLVM_PROJECT_SOURCE_DIR}/libcxx" CACHE PATH add_subdirectory(libcxx) add_subdirectory(std) add_subdirectory(tr1) +if(STL_IS_KERNEL) + add_subdirectory(utils/kernel) +endif() # Add the stl-lit subdirectory last so all the test directories have had a # chance to add to the config map and test directory global properties. diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index f88f8670e36..5dadc7cd6e2 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -30,6 +30,13 @@ 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@' +lit_config.is_kernel = '@STL_IS_KERNEL@'.lower() in ['1', 'true', 'on'] +if lit_config.is_kernel: + lit_config.wdk_include = "@WDK_INCLUDE_DIRECTORY@" + lit_config.wdk_lib = "@WDK_LIB_DIRECTORY@" + lit_config.wdk_bin = "@WDK_BIN_DIRECTORY@" + lit_config.utils_dir = "@STL_TEST_UTILS_DIR@" + # Add parameters and features to the config stl.test.config.configure( stl.test.params.getDefaultParameters(config, lit_config), diff --git a/tests/std/lit.site.cfg.in b/tests/std/lit.site.cfg.in index 9a2de0aa09b..0e066aec55e 100644 --- a/tests/std/lit.site.cfg.in +++ b/tests/std/lit.site.cfg.in @@ -33,6 +33,13 @@ lit_config.cxx_headers = '@STL_TESTED_HEADERS_DIR@' lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' +lit_config.is_kernel = '@STL_IS_KERNEL@'.lower() in ['1', 'true', 'on'] +if lit_config.is_kernel: + lit_config.wdk_include = "@WDK_INCLUDE_DIRECTORY@" + lit_config.wdk_lib = "@WDK_LIB_DIRECTORY@" + lit_config.wdk_bin = "@WDK_BIN_DIRECTORY@" + lit_config.utils_dir = "@STL_TEST_UTILS_DIR@" + # Add parameters and features to the config stl.test.config.configure( stl.test.params.getDefaultParameters(config, lit_config), diff --git a/tests/tr1/lit.site.cfg.in b/tests/tr1/lit.site.cfg.in index c2879998983..0d69b401841 100644 --- a/tests/tr1/lit.site.cfg.in +++ b/tests/tr1/lit.site.cfg.in @@ -32,6 +32,13 @@ lit_config.test_subdirs[config.name] = \ lit_config.cxx_runtime = '@CMAKE_RUNTIME_OUTPUT_DIRECTORY@' lit_config.target_arch = '@VCLIBS_TARGET_ARCHITECTURE@' +lit_config.is_kernel = '@STL_IS_KERNEL@'.lower() in ['1', 'true', 'on'] +if lit_config.is_kernel: + lit_config.wdk_include = "@WDK_INCLUDE_DIRECTORY@" + lit_config.wdk_lib = "@WDK_LIB_DIRECTORY@" + lit_config.wdk_bin = "@WDK_BIN_DIRECTORY@" + lit_config.utils_dir = "@STL_TEST_UTILS_DIR@" + # Add parameters and features to the config stl.test.config.configure( stl.test.params.getDefaultParameters(config, lit_config), diff --git a/tests/utils/kernel/CMakeLists.txt b/tests/utils/kernel/CMakeLists.txt new file mode 100644 index 00000000000..fd6288eb5c8 --- /dev/null +++ b/tests/utils/kernel/CMakeLists.txt @@ -0,0 +1,45 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set(STL_KERNEL_LOADER_SOURCES + ${CMAKE_CURRENT_LIST_DIR}/src/stl_kernel_loader/testapp.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/stl_kernel_loader/install.cpp +) + +set(STL_KERNEL_SOURCES + ${CMAKE_CURRENT_LIST_DIR}/src/stl_kernel/doAssert.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/stl_kernel/stl_kernel.cpp +) + +add_library(stl_kernel STATIC ${STL_KERNEL_SOURCES}) +set_target_properties(stl_kernel PROPERTIES LINKER_LANGUAGE CXX) +target_compile_definitions(stl_kernel PRIVATE "__STL_IS_KERNEL") + +# ${WDK_INCLUDE_DIRECTORY}/km/crt isn't in the files under test include paths. +# doAssert.cpp wants to use RtlStringCbPrintfExA, and that requires pulling in +# km/crt. If we don't pull in km/crt here, we erroneously pull in user mode +# crt headers, and that gets us linker errors dealing with missing user mode +# symbols in this kernel mode binary. +target_include_directories(stl_kernel PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/inc + ${WDK_INCLUDE_DIRECTORY}/km + ${WDK_INCLUDE_DIRECTORY}/km/crt + ${WDK_INCLUDE_DIRECTORY}/shared +) +target_compile_options(stl_kernel PRIVATE /kernel) + +add_executable(stl_kernel_loader ${STL_KERNEL_LOADER_SOURCES}) +target_include_directories(stl_kernel_loader PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/inc + ${WDK_INCLUDE_DIRECTORY}/ucrt + ${WDK_INCLUDE_DIRECTORY}/um + ${WDK_INCLUDE_DIRECTORY}/shared +) +target_compile_options(stl_kernel_loader PRIVATE /EHsc) +target_link_libraries(stl_kernel_loader PRIVATE + msvcrt.lib + kernel32.lib + ucrt.lib + AdvApi32.lib +) + diff --git a/tests/utils/kernel/generateMsvcCert.ps1 b/tests/utils/kernel/generateMsvcCert.ps1 new file mode 100644 index 00000000000..3af7f504eaa --- /dev/null +++ b/tests/utils/kernel/generateMsvcCert.ps1 @@ -0,0 +1,27 @@ +param([string]$out="MsvcStlTestingCert.pfx",[string]$pass="foo") + +$ErrorActionPreference = 'Stop' +# Clean up old certificates +Get-ChildItem cert:\localmachine\My | +Where-Object { $_.Subject -eq 'CN=MsvcStlTestingCert' } | +Remove-Item + +Get-ChildItem cert:\localmachine\root | +Where-Object { $_.Subject -eq 'CN=MsvcStlTestingCert' } | +Remove-Item + +Get-ChildItem cert:\localmachine\trustedpublisher | +Where-Object { $_.Subject -eq 'CN=MsvcStlTestingCert' } | +Remove-Item + +#Make the new cert +$cert = New-SelfSignedCertificate -Type CodeSigningCert -DnsName "MsvcStlTestingCert" -certstorelocation cert:\localmachine\my -NotAfter (Get-Date).AddDays(2) +$path = 'cert:\localMachine\my\' + $cert.thumbprint +$pwd = ConvertTo-SecureString -String $pass -Force -AsPlainText +Export-PfxCertificate -cert $path -FilePath $out -Password $pwd + +# install the cert so that we can load our drivers +Import-PfxCertificate -FilePath $out -CertStoreLocation cert:\localmachine\root -Password $pwd +Import-PfxCertificate -FilePath $out -CertStoreLocation cert:\localmachine\trustedpublisher -Password $pwd + + diff --git a/tests/utils/kernel/inc/assert.h b/tests/utils/kernel/inc/assert.h new file mode 100644 index 00000000000..d06c78007ad --- /dev/null +++ b/tests/utils/kernel/inc/assert.h @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include diff --git a/tests/utils/kernel/inc/cassert b/tests/utils/kernel/inc/cassert new file mode 100644 index 00000000000..d37512e2ec6 --- /dev/null +++ b/tests/utils/kernel/inc/cassert @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern volatile long *g_test_failures; +extern char *g_output_buffer; +extern size_t g_space_available; +void doAssert(const char *file, int line, const char *expr); + +#undef assert +#define assert(x) \ + if(!(x)) { doAssert(__FILE__, __LINE__, #x); } + +#ifdef __cplusplus +} +#endif diff --git a/tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h b/tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h new file mode 100644 index 00000000000..fa7b40a9596 --- /dev/null +++ b/tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// This header is intended to be force included into the .cpp under test. +// KERNEL_TEST_NAME will then be provided as a /D switch and preprocessor +// concatenated into one big string literal. +extern const wchar_t * const STL_KERNEL_NT_DEVICE_NAME = L"\\Device\\" KERNEL_TEST_NAME; +extern const wchar_t * const STL_KERNEL_DOS_DEVICE_NAME = L"\\DosDevices\\" KERNEL_TEST_NAME; diff --git a/tests/utils/kernel/inc/stl_kernel/stl_kernel.h b/tests/utils/kernel/inc/stl_kernel/stl_kernel.h new file mode 100644 index 00000000000..9624adf7437 --- /dev/null +++ b/tests/utils/kernel/inc/stl_kernel/stl_kernel.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#ifdef __STL_IS_KERNEL + #include +#else + #include +#endif + +#define IOCTL_SIOCTL_METHOD_RUN_TEST \ + CTL_CODE( 40000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS ) + +typedef struct TestResults { + int main_return; + long tests_failed; + char output[4088]; +} TestResults; diff --git a/tests/utils/kernel/src/stl_kernel/doAssert.cpp b/tests/utils/kernel/src/stl_kernel/doAssert.cpp new file mode 100644 index 00000000000..d0f14b180c5 --- /dev/null +++ b/tests/utils/kernel/src/stl_kernel/doAssert.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "test_decls.h" +#include +#include + +KGUARDED_MUTEX g_assert_mutex; +extern "C" { + long *g_test_failures; + char *g_output_buffer; + size_t g_space_available; +} + +static const char ASSERTION_FAILED[] = "assertion failed "; +static const size_t ASSERTION_FAILED_LEN = sizeof(ASSERTION_FAILED) - 1; +extern "C" void doAssert(const char *file, int line, const char *expr) +{ + KeAcquireGuardedMutex(&g_assert_mutex); + ++(*g_test_failures); + + RtlStringCbPrintfExA( + g_output_buffer, + g_space_available, + &g_output_buffer, + &g_space_available, + 0, //flags + "assertion failed %s(%d): %s\n", + file, + line, + expr); + + KeReleaseGuardedMutex (&g_assert_mutex); +} diff --git a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp new file mode 100644 index 00000000000..3a8081d56bd --- /dev/null +++ b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp @@ -0,0 +1,168 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "test_decls.h" +#include + +#include + +// This isn't the "real" cassert, but our interposed header. We want to get +// at the globals that have the error text and the failure count +#include + +struct device_handle { + DEVICE_OBJECT *h = nullptr; + + device_handle() = default; + ~device_handle() { + if(h) { + IoDeleteDevice(h); + } + } + + DEVICE_OBJECT *release() { + DEVICE_OBJECT *retval = h; + h = nullptr; + return retval; + } +}; + +class irp_sentry { +private: + IRP *irp; + NTSTATUS &status; +public: + irp_sentry(IRP *irp, NTSTATUS &status) : irp(irp), status(status) {} + ~irp_sentry() { + irp->IoStatus.Status = status; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + } + irp_sentry(const irp_sentry &) = delete; + irp_sentry &operator=(const irp_sentry &) = delete; +}; + +extern "C" { +// Device driver routine declarations. +DRIVER_INITIALIZE DriverEntry; + +_Dispatch_type_(IRP_MJ_CREATE) +_Dispatch_type_(IRP_MJ_CLOSE) +DRIVER_DISPATCH StlKernelCreateClose; + +_Dispatch_type_(IRP_MJ_DEVICE_CONTROL) +DRIVER_DISPATCH StlKernelDeviceControl; + +DRIVER_UNLOAD PAGE, StlKernelUnloadDriver; + +#pragma alloc_text( INIT, DriverEntry ) +#pragma alloc_text( PAGE, StlKernelCreateClose) +#pragma alloc_text( PAGE, StlKernelDeviceControl) +#pragma alloc_text( PAGE, StlKernelUnloadDriver) + +NTSTATUS DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING * /*reg_path*/) +{ + UNICODE_STRING nt_name; + RtlInitUnicodeString( &nt_name, STL_KERNEL_NT_DEVICE_NAME ); + + device_handle device; + NTSTATUS status = IoCreateDevice( + driver, + 0, // DeviceExtensionSize + &nt_name, + FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, + FALSE, // BOOLEAN Exclusive + &device.h ); + + if ( !NT_SUCCESS( status ) ) + { + DbgPrint("stl_kernel: Couldn't create the device object\n"); + return status; + } + + driver->MajorFunction[IRP_MJ_CREATE] = StlKernelCreateClose; + driver->MajorFunction[IRP_MJ_CLOSE] = StlKernelCreateClose; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = StlKernelDeviceControl; + driver->DriverUnload = StlKernelUnloadDriver; + + UNICODE_STRING dos_name; + RtlInitUnicodeString( &dos_name, STL_KERNEL_DOS_DEVICE_NAME ); + + status = IoCreateSymbolicLink( &dos_name, &nt_name ); + + if ( !NT_SUCCESS( status ) ) + { + DbgPrint("stl_kernel: Couldn't create symbolic link\n"); + return status; + } + + KeInitializeGuardedMutex(&g_assert_mutex); + + device.release(); // everything worked, so "commit" the operation. + return status; +} + +NTSTATUS StlKernelCreateClose(DEVICE_OBJECT *, IRP *irp) +{ + PAGED_CODE(); + + irp->IoStatus.Status = STATUS_SUCCESS; + irp->IoStatus.Information = 0; + + IoCompleteRequest( irp, IO_NO_INCREMENT ); + + return STATUS_SUCCESS; +} + +void StlKernelUnloadDriver(DRIVER_OBJECT *driver) +{ + PAGED_CODE(); + + device_handle dev; + dev.h = driver->DeviceObject; + + UNICODE_STRING dos_name; + RtlInitUnicodeString( &dos_name, STL_KERNEL_DOS_DEVICE_NAME ); + IoDeleteSymbolicLink( &dos_name ); +} + +NTSTATUS StlKernelDeviceControl(DEVICE_OBJECT *, IRP *irp) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( irp ); + ULONG outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; + irp_sentry sentry(irp, status); + + if (outBufLength < sizeof(TestResults)) + { + status = STATUS_INVALID_PARAMETER; + return status; + } + + auto control_code = irpSp->Parameters.DeviceIoControl.IoControlCode; + if ( control_code != IOCTL_SIOCTL_METHOD_RUN_TEST) + { + status = STATUS_INVALID_DEVICE_REQUEST; + DbgPrint("stl_kernel ERROR: unrecognized IOCTL %x\n", control_code); + return status; + } + + TestResults *outBuf = static_cast(irp->AssociatedIrp.SystemBuffer); + + // set up the assertion framework + g_test_failures = &outBuf->tests_failed; + g_output_buffer = outBuf->output; + g_space_available = sizeof(outBuf->output); + + // This is where the magic happens + outBuf->main_return = main(); + + irp->IoStatus.Information = sizeof(TestResults); + + return status; +} + +} // extern "C" diff --git a/tests/utils/kernel/src/stl_kernel/test_decls.h b/tests/utils/kernel/src/stl_kernel/test_decls.h new file mode 100644 index 00000000000..a4406a2ab79 --- /dev/null +++ b/tests/utils/kernel/src/stl_kernel/test_decls.h @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#include + +extern const wchar_t * const STL_KERNEL_NT_DEVICE_NAME; +extern const wchar_t * const STL_KERNEL_DOS_DEVICE_NAME; +extern KGUARDED_MUTEX g_assert_mutex; + +extern "C" int main(); diff --git a/tests/utils/kernel/src/stl_kernel_loader/install.cpp b/tests/utils/kernel/src/stl_kernel_loader/install.cpp new file mode 100644 index 00000000000..dcf7b3546f0 --- /dev/null +++ b/tests/utils/kernel/src/stl_kernel_loader/install.cpp @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "install.h" +#include +#include +#include + +[[noreturn]] void throw_get_last_error(const char *routine) { + auto gle = GetLastError(); + char error_buffer[1024] ={0}; + + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, //lpSource + gle, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + error_buffer, + static_cast(std::size(error_buffer)), + nullptr /* va_list arguments */); + + std::string err_text = "Error: "; + err_text += routine; + err_text += " failed. GetLastError = " + std::to_string(GetLastError()); + err_text += "\n"; + err_text += error_buffer; + throw std::runtime_error(err_text); +} + +scm_handle::scm_handle() + : h(OpenSCManager( + nullptr /* lpMachineName */, + nullptr /* lpDatabaseName */, + SC_MANAGER_ALL_ACCESS)) +{ + if (!h) { + throw_get_last_error(__FUNCTION__); + } +} + +scm_handle::~scm_handle() +{ + CloseServiceHandle(h); +} + +struct service_handle { + SC_HANDLE h; + + service_handle(SC_HANDLE scm, const char *name) noexcept + : h(OpenService(scm, name, SERVICE_ALL_ACCESS)) + {} + service_handle() noexcept : h(nullptr) {} + + void attach(SC_HANDLE new_h) noexcept { + if(h) CloseServiceHandle(h); + h = new_h; + } + + ~service_handle() + { + if(h) CloseServiceHandle(h); + } +}; + +static void stop_and_remove_driver(SC_HANDLE scm, const char *name) noexcept { + service_handle driver(scm, name); + + if (driver.h == nullptr) { + // already gone. Post-condition met + return; + } + // ignore the returns, as there isn't anything we can do if the delete fails + SERVICE_STATUS serviceStatus; + ControlService(driver.h, SERVICE_CONTROL_STOP, &serviceStatus); + DeleteService(driver.h); +} + +static void install_and_start_driver(SC_HANDLE scm, const char *path, const char *name) { + service_handle driver; + driver.attach( + CreateService(scm, + name, // lpServiceName + name, // lpDisplayName + SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + path, + nullptr, // lpLoadOrderGroup + nullptr, // lpdwTagId + nullptr, // lpDependencies + nullptr, // lpServiceStartName + nullptr // lpServiceStartName + )); + + if (driver.h == nullptr) { + throw_get_last_error("CreateService"); + } + + auto success = StartService(driver.h, 0 /*num args*/, nullptr /*args*/); + if (!success) { + throw_get_last_error("StartService"); + } +} + +driver_loader::driver_loader(const char *path, const char *name) + : driver_name(name) +{ + // clean up any previous runs in case something went horribly wrong + stop_and_remove_driver(sc_handle.get(), driver_name.c_str()); + install_and_start_driver(sc_handle.get(), path, name); +} + +driver_loader::~driver_loader() { + stop_and_remove_driver(sc_handle.get(), driver_name.c_str()); +} diff --git a/tests/utils/kernel/src/stl_kernel_loader/install.h b/tests/utils/kernel/src/stl_kernel_loader/install.h new file mode 100644 index 00000000000..fe314475222 --- /dev/null +++ b/tests/utils/kernel/src/stl_kernel_loader/install.h @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once + +#include +#include + +class scm_handle { +private: + SC_HANDLE h; +public: + scm_handle(); + ~scm_handle(); + scm_handle(const scm_handle &) = delete; + scm_handle &operator=(const scm_handle &) = delete; + + SC_HANDLE get() {return h;} +}; + +class driver_loader { +private: + scm_handle sc_handle; + std::string driver_name; +public: + driver_loader(const char *path, const char *name); + ~driver_loader(); + + driver_loader(const scm_handle &) = delete; + driver_loader &operator=(const scm_handle &) = delete; +}; + +[[noreturn]] void throw_get_last_error(const char *routine); diff --git a/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp b/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp new file mode 100644 index 00000000000..6a4df40fe70 --- /dev/null +++ b/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "install.h" +#include +#include +#include +#include +#include +#include + +struct DeviceOpener { + HANDLE h = INVALID_HANDLE_VALUE; + explicit DeviceOpener(const char *driverName) + { + std::string dosName = "\\\\.\\"; + dosName += driverName; + h = CreateFile( dosName.c_str(), + GENERIC_READ | GENERIC_WRITE, + 0, + nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + nullptr); + + if ( h == INVALID_HANDLE_VALUE ){ + throw_get_last_error(__FUNCTION__); + } + } + ~DeviceOpener() {CloseHandle ( h );} +}; + +// returns true if the test passed +bool do_test(const char *path) +{ + // We have a secret handshake with the driver and the build system. + // The DOS name of the driver is the same as the absolute path, + // except the \ and : are replaced with ".". Shhh. Don't tell anyone. + std::string driverName = path; + std::replace_if( + driverName.begin(), + driverName.end(), + [](char c) {return c == '\\' || c == ':';}, + '.'); + + driver_loader sentry(path, driverName.c_str()); + DeviceOpener dev(driverName.c_str()); + + ULONG bytesReturned = 0; + char InputBuffer[1]; + TestResults OutputBuffer; + + auto success = DeviceIoControl ( dev.h, + (DWORD) IOCTL_SIOCTL_METHOD_RUN_TEST, + &InputBuffer, + sizeof(InputBuffer), + &OutputBuffer, + sizeof( OutputBuffer), + &bytesReturned, + nullptr + ); + + if ( !success ) { + throw_get_last_error(__FUNCTION__); + } + + if(OutputBuffer.main_return != 0 || OutputBuffer.tests_failed != 0) { + printf("retval: %d\ntests failed: %d\noutput =\n%s\n", + OutputBuffer.main_return, + OutputBuffer.tests_failed, + OutputBuffer.output); + return false; + } + return true; +} + +int __cdecl main(int argc, char *argv[]) +{ + if(argc < 2) { + printf( "Usage: %s \n", argv[0]); + return 2; + } + try { + bool result = do_test(argv[1]); + return result ? 0 : 1; + } + catch(const std::exception &e) { + printf("%s\n", e.what()); + } + return 2; +} diff --git a/tests/utils/stl/test/config.py b/tests/utils/stl/test/config.py index a02e8038c68..6b04a2ee052 100644 --- a/tests/utils/stl/test/config.py +++ b/tests/utils/stl/test/config.py @@ -7,6 +7,8 @@ #===----------------------------------------------------------------------===## import os +import secrets +import stl.util def configure(parameters, features, config, lit_config): # Apply parameters to the configuration first, since parameters are things @@ -45,3 +47,16 @@ def configure(parameters, features, config, lit_config): ['/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)} + + if lit_config.is_kernel: + lit_config.cert_pass = secrets.token_hex(64) + lit_config.cert_path = lit_config.cxx_runtime + '/MsvcStlTestingCert.pfx' + cmd = ['powershell', '-ExecutionPolicy', 'Bypass', + '-File', lit_config.utils_dir + '/kernel/generateMsvcCert.ps1', + '-out', lit_config.cert_path, + '-pass', lit_config.cert_pass] + + out, err, rc = stl.util.executeCommand(cmd) + if rc != 0: + report = stl.util.makeReport(cmd, out, err, rc) + raise RuntimeError(report) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index edf9b2504c1..27657beaf59 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -206,9 +206,53 @@ def getBuildSteps(self, test, litConfig, shared): 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) + if not litConfig.is_kernel: + cmd = [test.cxx, test.getSourcePath(), *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags] + yield TestStep(cmd, shared.execDir, shared.env, False) + + if litConfig.is_kernel: + name = str(shared.execFile).replace('\\','.').replace(':','.') + + customKernelCompileFlags = [ + '/DKERNEL_TEST_NAME=L"' + name + '"', + '/FIstl_kernel/kernel_test_constants.h', + '/I' + litConfig.utils_dir + '/kernel/inc', + '/I' + litConfig.wdk_include + '/km', + #'/I' + litConfig.wdk_include + '/km/crt', #causes vadefs.h conflicts + '/I' + litConfig.wdk_include + '/shared', + ] + customKernelLinkFlags = [ + '/LIBPATH:' + litConfig.wdk_lib + '/km/' + litConfig.target_arch, + '/IGNORE:4210', + '/machine:'+litConfig.target_arch, + '/entry:DriverEntry', + '/subsystem:native', + '/nodefaultlib', + 'stl_kernel.lib', + 'BufferOverflowFastFailK.lib', + 'ntoskrnl.lib', + 'hal.lib', + 'wmilib.lib', + 'Ntstrsafe.lib', + 'libcpmt.lib', + 'libcmt.lib', + ] + cmd = [test.cxx, test.getSourcePath(), + *customKernelCompileFlags, + *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags, + *customKernelLinkFlags, + ] + yield TestStep(cmd, shared.execDir, shared.env, False) + + + # sign the binary + cmd = [litConfig.wdk_bin + '/x86/signtool.exe', 'sign', + '/f', litConfig.cert_path, + '/p', litConfig.cert_pass, + shared.execFile] + yield TestStep(cmd, shared.execDir, shared.env, shouldFail=False) def getTestSetupSteps(self, test, litConfig, shared): if TestType.RUN in test.testType: @@ -225,7 +269,11 @@ def getTestSteps(self, test, litConfig, shared): return shouldFail = TestType.FAIL in test.testType - yield TestStep([shared.execFile], shared.execDir, shared.env, shouldFail) + if litConfig.is_kernel: + cmd = [litConfig.cxx_runtime + "/stl_kernel_loader.exe", shared.execFile] + else: + cmd = [shared.execFile] + yield TestStep(cmd, shared.execDir, shared.env, shouldFail) def execute(self, test, litConfig): try: @@ -320,7 +368,7 @@ def execute(self, test, litConfig): return lit.Test.Result(passVar, report) except Exception as e: - lit_config.warning(repr(e)) + litConfig.warning(repr(e)) class LibcxxTestFormat(STLTestFormat): From 2fab494726c6dea9af1217f4ec7bdcc8712ee666 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 1 Nov 2020 19:48:11 -0800 Subject: [PATCH 26/56] Code review feedback. --- tests/libcxx/expected_results.txt | 15 --------------- tests/libcxx/skipped_tests.txt | 15 --------------- tests/tr1/lit.site.cfg.in | 2 +- tests/utils/stl/test/params.py | 2 +- 4 files changed, 2 insertions(+), 32 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 7750b84573e..f4855a8b0cb 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -507,21 +507,6 @@ std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp FAIL std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp FAIL -# C++20 P0784R7 "More constexpr containers" -std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp FAIL -std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp FAIL -std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp FAIL -std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp FAIL -std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp FAIL -std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp FAIL - # C++20 P0896R4 "" std/language.support/support.limits/support.limits.general/algorithm.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/functional.version.pass.cpp FAIL diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index b358068d7af..c5c7960848f 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -507,21 +507,6 @@ utilities\memory\specialized.algorithms\specialized.destroy\destroy.pass.cpp utilities\memory\specialized.algorithms\specialized.destroy\destroy_at.pass.cpp utilities\memory\specialized.algorithms\specialized.destroy\destroy_n.pass.cpp -# C++20 P0784R7 "More constexpr containers" -utilities\memory\allocator.traits\allocator.traits.members\allocate.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\allocate_hint.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\construct.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\deallocate.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\destroy.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\max_size.pass.cpp -utilities\memory\allocator.traits\allocator.traits.members\select_on_container_copy_construction.pass.cpp -utilities\memory\default.allocator\allocator.globals\eq.pass.cpp -utilities\memory\default.allocator\allocator.members\allocate.pass.cpp -utilities\memory\specialized.algorithms\specialized.construct\construct_at.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy_at.pass.cpp -utilities\memory\specialized.algorithms\specialized.destroy\destroy_n.pass.cpp - # C++20 P0896R4 "" language.support\support.limits\support.limits.general\algorithm.version.pass.cpp language.support\support.limits\support.limits.general\functional.version.pass.cpp diff --git a/tests/tr1/lit.site.cfg.in b/tests/tr1/lit.site.cfg.in index c2879998983..979944d0d5c 100644 --- a/tests/tr1/lit.site.cfg.in +++ b/tests/tr1/lit.site.cfg.in @@ -23,7 +23,7 @@ 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@', '@LIBCXX_SOURCE_DIR@/test/support', '@STL_SOURCE_DIR@/tests/std/include', '@STL_SOURCE_DIR@/tests/tr1/include'] + ['@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 \ diff --git a/tests/utils/stl/test/params.py b/tests/utils/stl/test/params.py index f082f3d1532..e57ddaf0cde 100644 --- a/tests/utils/stl/test/params.py +++ b/tests/utils/stl/test/params.py @@ -11,7 +11,7 @@ def getDefaultParameters(config, litConfig): DEFAULT_PARAMETERS = [ Parameter(name='long_tests', choices=[True, False], type=bool, default=True, - help="Whether to tests that take longer to run. This can be useful when running on a very slow device.", + 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), ] From 73e08c691dec01e889ed425bc230319e6ea23914 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Mon, 2 Nov 2020 10:49:23 -0800 Subject: [PATCH 27/56] Fix issue with expected results file. Integrate @ben-craig's suggestions --- tests/libcxx/lit.site.cfg.in | 2 +- tests/utils/stl/test/format.py | 92 +++++++--------------------------- tests/utils/stl/test/tests.py | 8 +-- 3 files changed, 22 insertions(+), 80 deletions(-) diff --git a/tests/libcxx/lit.site.cfg.in b/tests/libcxx/lit.site.cfg.in index 85638dae992..fb530312e8a 100644 --- a/tests/libcxx/lit.site.cfg.in +++ b/tests/libcxx/lit.site.cfg.in @@ -16,7 +16,7 @@ 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/std' +config.test_source_root = '@LIBCXX_SOURCE_DIR@/test' lit_config.expected_results = getattr(lit_config, 'expected_results', dict()) lit_config.include_dirs = getattr(lit_config, 'include_dirs', dict()) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index b476e31477f..170a3c8acc0 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -127,7 +127,7 @@ def _parseScript(self, test): test.compileFlags.extend(additionalCompileFlags) test.fileDependencies.extend(fileDependencies) - def _handleIsenseRspFile(self, test, litConfig, shared): + 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] @@ -159,7 +159,7 @@ def runStep(self, testStep, litConfig): return testStep.cmd, *stl.util.executeCommand(testStep.cmd, cwd=testStep.workDir, env=env) - def getSteps(self, test, litConfig): + def getStages(self, test, litConfig): @dataclass class SharedState: execFile: Optional[os.PathLike] = field(default=None) @@ -173,12 +173,12 @@ class SharedState: shared.env['TMPDIR'] = execDir shared.env['TEMPDIR'] = execDir - return \ - self.getBuildSetupSteps(test, litConfig, shared), \ - self.getBuildSteps(test, litConfig, shared), \ - self._handleIsenseRspFile(test, litConfig, shared), \ - self.getTestSetupSteps(test, litConfig, shared), \ - self.getTestSteps(test, litConfig, shared) + 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))] def getBuildSetupSteps(self, test, litConfig, shared): shutil.rmtree(shared.execDir, ignore_errors=True) @@ -243,85 +243,27 @@ def execute(self, test, litConfig): failVar = lit.Test.FAIL passVar = lit.Test.PASS - buildSetupSteps, buildSteps, handleIsenseRspFile, testSetupSteps, testSteps = \ - self.getSteps(test, litConfig) - - report = 'Build setup steps:\n' - for step in buildSetupSteps: - cmd, out, err, rc = self.runStep(step, litConfig) - - if step.shouldFail and rc == 0: - report += 'Build setup step succeeded unexpectedly.\n' - elif rc != 0: - report += 'Build setup 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): - litConfig.note(report) - return lit.Test.Result(failVar, report) - - report += 'Build steps:\n' - for step in buildSteps: - cmd, out, err, rc = self.runStep(step, litConfig) - - if step.shouldFail and rc == 0: - report += 'Build step succeeded unexpectedly.\n' - elif rc != 0: - report += 'Build 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): - litConfig.note(report) - return lit.Test.Result(failVar, report) - - # The following block is for internal use only - if litConfig.edg_drop: - report += 'Intellisense response file steps:\n' - for step in handleIsenseRspFile: + 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 += 'Intellisense response step succeeded unexpectedly.\n' + report += stageName + ' step succeeded unxexpectedly.\n' elif rc != 0: - report += 'Intellisense response step failed unexpectedly.\n' + 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): - litConfig.note(report) return lit.Test.Result(failVar, report) - report += 'Test setup steps:\n' - for step in testSetupSteps: - cmd, out, err, rc = self.runStep(step, litConfig) - - if step.shouldFail and rc == 0: - report += 'Test setup step succeeded unexpectedly.\n' - elif rc != 0: - report += 'Test setup 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): - litConfig.note(report) - return lit.Test.Result(failVar, report) - - report += 'Test steps:\n' - for step in testSteps: - cmd, out, err, rc = self.runStep(step, litConfig) - - if step.shouldFail 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.shouldFail and rc == 0) or (not step.shouldFail and rc != 0): - litConfig.note(report) - return lit.Test.Result(failVar, report) - return lit.Test.Result(passVar, report) except Exception as e: - lit_config.warning(repr(e)) + litConfig.error(repr(e)) class LibcxxTestFormat(STLTestFormat): diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index 2eefe92ef59..fad62453bbd 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -13,7 +13,7 @@ import os import shutil -from lit.Test import SKIPPED, Test, UNRESOLVED, UNSUPPORTED +from lit.Test import SKIPPED, Result, Test, UNRESOLVED, UNSUPPORTED from libcxx.test.dsl import Feature import lit @@ -115,11 +115,11 @@ def _configureExpectedResult(self, suite, litConfig): if self.expectedResult is not None: if self.expectedResult == SKIPPED: - self.result = (lit.Test.SKIPPED, 'This test was explicitly marked as skipped') + self.result = Result(SKIPPED, 'This test was explicitly marked as skipped') elif self.expectedResult.isFailure: self.xfails = ['*'] elif self.config.unsupported: - self.result = (lit.Test.UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') + self.result = Result(lit.Test.UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') def _handleEnvlst(self, litConfig, envlstEntry): envCompiler = envlstEntry.getEnvVal('PM_COMPILER', 'cl') @@ -180,7 +180,7 @@ def _handleEnvlst(self, litConfig, envlstEntry): if 'edg_drop' in self.config.available_features: if not 'edg' in self.requires: - self.result = lit.Test.Result(UNSUPPORTED, "We only run /BE tests with the edg drop") + self.result = Result(UNSUPPORTED, 'We only run /BE tests with the edg drop') else: _, tmpBase = self.getTempPaths() self.isenseRspPath = tmpBase + '.isense.rsp' From b91bb8b819359e0456a6b66ac335e451d4647638 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Mon, 2 Nov 2020 11:46:53 -0800 Subject: [PATCH 28/56] It might be deprecated but pickling a tuple is faster than pickling a user type. Also don't return the report on success. --- tests/utils/stl/test/format.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 170a3c8acc0..7cf907b9b15 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -258,9 +258,9 @@ def execute(self, test, litConfig): report += stl.util.makeReport(cmd, out, err, rc) if (step.shouldFail and rc == 0) or (not step.shouldFail and rc != 0): - return lit.Test.Result(failVar, report) + return (failVar, report) - return lit.Test.Result(passVar, report) + return (passVar, '') except Exception as e: litConfig.error(repr(e)) From 28f6864a25679af9233c1add5f1e0e96f982af94 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Mon, 2 Nov 2020 15:52:35 -0800 Subject: [PATCH 29/56] clang format and some other small cleanups --- .../inc/stl_kernel/kernel_test_constants.h | 4 +- .../utils/kernel/inc/stl_kernel/stl_kernel.h | 7 +- .../utils/kernel/src/stl_kernel/doAssert.cpp | 28 ++--- .../kernel/src/stl_kernel/stl_kernel.cpp | 104 ++++++++---------- .../utils/kernel/src/stl_kernel/test_decls.h | 4 +- .../kernel/src/stl_kernel_loader/install.cpp | 79 ++++++------- .../kernel/src/stl_kernel_loader/install.h | 19 ++-- .../kernel/src/stl_kernel_loader/testapp.cpp | 60 ++++------ tests/utils/stl/test/features.py | 3 + tests/utils/stl/test/format.py | 28 ++--- tests/utils/stl/test/tests.py | 4 + 11 files changed, 144 insertions(+), 196 deletions(-) diff --git a/tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h b/tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h index fa7b40a9596..c92d95e1cff 100644 --- a/tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h +++ b/tests/utils/kernel/inc/stl_kernel/kernel_test_constants.h @@ -4,5 +4,5 @@ // This header is intended to be force included into the .cpp under test. // KERNEL_TEST_NAME will then be provided as a /D switch and preprocessor // concatenated into one big string literal. -extern const wchar_t * const STL_KERNEL_NT_DEVICE_NAME = L"\\Device\\" KERNEL_TEST_NAME; -extern const wchar_t * const STL_KERNEL_DOS_DEVICE_NAME = L"\\DosDevices\\" KERNEL_TEST_NAME; +extern const wchar_t* const STL_KERNEL_NT_DEVICE_NAME = L"\\Device\\" KERNEL_TEST_NAME; +extern const wchar_t* const STL_KERNEL_DOS_DEVICE_NAME = L"\\DosDevices\\" KERNEL_TEST_NAME; diff --git a/tests/utils/kernel/inc/stl_kernel/stl_kernel.h b/tests/utils/kernel/inc/stl_kernel/stl_kernel.h index 9624adf7437..8fba45808f2 100644 --- a/tests/utils/kernel/inc/stl_kernel/stl_kernel.h +++ b/tests/utils/kernel/inc/stl_kernel/stl_kernel.h @@ -4,13 +4,12 @@ #pragma once #ifdef __STL_IS_KERNEL - #include +#include #else - #include +#include #endif -#define IOCTL_SIOCTL_METHOD_RUN_TEST \ - CTL_CODE( 40000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS ) +#define IOCTL_SIOCTL_METHOD_RUN_TEST CTL_CODE(40000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct TestResults { int main_return; diff --git a/tests/utils/kernel/src/stl_kernel/doAssert.cpp b/tests/utils/kernel/src/stl_kernel/doAssert.cpp index d0f14b180c5..f5f13012715 100644 --- a/tests/utils/kernel/src/stl_kernel/doAssert.cpp +++ b/tests/utils/kernel/src/stl_kernel/doAssert.cpp @@ -2,33 +2,25 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "test_decls.h" -#include #include +#include KGUARDED_MUTEX g_assert_mutex; extern "C" { - long *g_test_failures; - char *g_output_buffer; - size_t g_space_available; +long* g_test_failures; +char* g_output_buffer; +size_t g_space_available; } -static const char ASSERTION_FAILED[] = "assertion failed "; +static const char ASSERTION_FAILED[] = "assertion failed "; static const size_t ASSERTION_FAILED_LEN = sizeof(ASSERTION_FAILED) - 1; -extern "C" void doAssert(const char *file, int line, const char *expr) -{ +extern "C" void doAssert(const char* file, int line, const char* expr) { KeAcquireGuardedMutex(&g_assert_mutex); ++(*g_test_failures); - RtlStringCbPrintfExA( - g_output_buffer, - g_space_available, - &g_output_buffer, - &g_space_available, - 0, //flags - "assertion failed %s(%d): %s\n", - file, - line, - expr); + RtlStringCbPrintfExA(g_output_buffer, g_space_available, &g_output_buffer, &g_space_available, + 0, // flags + "assertion failed %s(%d): %s\n", file, line, expr); - KeReleaseGuardedMutex (&g_assert_mutex); + KeReleaseGuardedMutex(&g_assert_mutex); } diff --git a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp index 3a8081d56bd..89a1922f7f4 100644 --- a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp +++ b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp @@ -2,96 +2,87 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "test_decls.h" -#include - #include +#include // This isn't the "real" cassert, but our interposed header. We want to get // at the globals that have the error text and the failure count #include struct device_handle { - DEVICE_OBJECT *h = nullptr; + DEVICE_OBJECT* h = nullptr; device_handle() = default; ~device_handle() { - if(h) { + if (h) { IoDeleteDevice(h); } } - DEVICE_OBJECT *release() { - DEVICE_OBJECT *retval = h; - h = nullptr; + DEVICE_OBJECT* release() { + DEVICE_OBJECT* retval = h; + h = nullptr; return retval; } }; class irp_sentry { private: - IRP *irp; - NTSTATUS &status; + IRP* irp; + NTSTATUS& status; + public: - irp_sentry(IRP *irp, NTSTATUS &status) : irp(irp), status(status) {} + irp_sentry(IRP* irp, NTSTATUS& status) : irp(irp), status(status) {} ~irp_sentry() { irp->IoStatus.Status = status; - IoCompleteRequest( irp, IO_NO_INCREMENT ); + IoCompleteRequest(irp, IO_NO_INCREMENT); } - irp_sentry(const irp_sentry &) = delete; - irp_sentry &operator=(const irp_sentry &) = delete; + irp_sentry(const irp_sentry&) = delete; + irp_sentry& operator=(const irp_sentry&) = delete; }; extern "C" { // Device driver routine declarations. DRIVER_INITIALIZE DriverEntry; -_Dispatch_type_(IRP_MJ_CREATE) -_Dispatch_type_(IRP_MJ_CLOSE) -DRIVER_DISPATCH StlKernelCreateClose; +_Dispatch_type_(IRP_MJ_CREATE) _Dispatch_type_(IRP_MJ_CLOSE) DRIVER_DISPATCH StlKernelCreateClose; -_Dispatch_type_(IRP_MJ_DEVICE_CONTROL) -DRIVER_DISPATCH StlKernelDeviceControl; +_Dispatch_type_(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH StlKernelDeviceControl; DRIVER_UNLOAD PAGE, StlKernelUnloadDriver; -#pragma alloc_text( INIT, DriverEntry ) -#pragma alloc_text( PAGE, StlKernelCreateClose) -#pragma alloc_text( PAGE, StlKernelDeviceControl) -#pragma alloc_text( PAGE, StlKernelUnloadDriver) +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, StlKernelCreateClose) +#pragma alloc_text(PAGE, StlKernelDeviceControl) +#pragma alloc_text(PAGE, StlKernelUnloadDriver) -NTSTATUS DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING * /*reg_path*/) -{ +NTSTATUS DriverEntry(DRIVER_OBJECT* driver, UNICODE_STRING* /*reg_path*/) { UNICODE_STRING nt_name; - RtlInitUnicodeString( &nt_name, STL_KERNEL_NT_DEVICE_NAME ); + RtlInitUnicodeString(&nt_name, STL_KERNEL_NT_DEVICE_NAME); device_handle device; - NTSTATUS status = IoCreateDevice( - driver, + NTSTATUS status = IoCreateDevice(driver, 0, // DeviceExtensionSize - &nt_name, - FILE_DEVICE_UNKNOWN, - FILE_DEVICE_SECURE_OPEN, + &nt_name, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, // BOOLEAN Exclusive - &device.h ); + &device.h); - if ( !NT_SUCCESS( status ) ) - { + if (!NT_SUCCESS(status)) { DbgPrint("stl_kernel: Couldn't create the device object\n"); return status; } - driver->MajorFunction[IRP_MJ_CREATE] = StlKernelCreateClose; - driver->MajorFunction[IRP_MJ_CLOSE] = StlKernelCreateClose; + driver->MajorFunction[IRP_MJ_CREATE] = StlKernelCreateClose; + driver->MajorFunction[IRP_MJ_CLOSE] = StlKernelCreateClose; driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = StlKernelDeviceControl; - driver->DriverUnload = StlKernelUnloadDriver; + driver->DriverUnload = StlKernelUnloadDriver; UNICODE_STRING dos_name; - RtlInitUnicodeString( &dos_name, STL_KERNEL_DOS_DEVICE_NAME ); + RtlInitUnicodeString(&dos_name, STL_KERNEL_DOS_DEVICE_NAME); - status = IoCreateSymbolicLink( &dos_name, &nt_name ); + status = IoCreateSymbolicLink(&dos_name, &nt_name); - if ( !NT_SUCCESS( status ) ) - { + if (!NT_SUCCESS(status)) { DbgPrint("stl_kernel: Couldn't create symbolic link\n"); return status; } @@ -102,59 +93,54 @@ NTSTATUS DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING * /*reg_path*/) return status; } -NTSTATUS StlKernelCreateClose(DEVICE_OBJECT *, IRP *irp) -{ +NTSTATUS StlKernelCreateClose(DEVICE_OBJECT*, IRP* irp) { PAGED_CODE(); - irp->IoStatus.Status = STATUS_SUCCESS; + irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = 0; - IoCompleteRequest( irp, IO_NO_INCREMENT ); + IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } -void StlKernelUnloadDriver(DRIVER_OBJECT *driver) -{ +void StlKernelUnloadDriver(DRIVER_OBJECT* driver) { PAGED_CODE(); device_handle dev; dev.h = driver->DeviceObject; UNICODE_STRING dos_name; - RtlInitUnicodeString( &dos_name, STL_KERNEL_DOS_DEVICE_NAME ); - IoDeleteSymbolicLink( &dos_name ); + RtlInitUnicodeString(&dos_name, STL_KERNEL_DOS_DEVICE_NAME); + IoDeleteSymbolicLink(&dos_name); } -NTSTATUS StlKernelDeviceControl(DEVICE_OBJECT *, IRP *irp) -{ +NTSTATUS StlKernelDeviceControl(DEVICE_OBJECT*, IRP* irp) { PAGED_CODE(); NTSTATUS status = STATUS_SUCCESS; - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( irp ); - ULONG outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp); + ULONG outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; irp_sentry sentry(irp, status); - if (outBufLength < sizeof(TestResults)) - { + if (outBufLength < sizeof(TestResults)) { status = STATUS_INVALID_PARAMETER; return status; } auto control_code = irpSp->Parameters.DeviceIoControl.IoControlCode; - if ( control_code != IOCTL_SIOCTL_METHOD_RUN_TEST) - { + if (control_code != IOCTL_SIOCTL_METHOD_RUN_TEST) { status = STATUS_INVALID_DEVICE_REQUEST; DbgPrint("stl_kernel ERROR: unrecognized IOCTL %x\n", control_code); return status; } - TestResults *outBuf = static_cast(irp->AssociatedIrp.SystemBuffer); + TestResults* outBuf = static_cast(irp->AssociatedIrp.SystemBuffer); // set up the assertion framework - g_test_failures = &outBuf->tests_failed; - g_output_buffer = outBuf->output; + g_test_failures = &outBuf->tests_failed; + g_output_buffer = outBuf->output; g_space_available = sizeof(outBuf->output); // This is where the magic happens diff --git a/tests/utils/kernel/src/stl_kernel/test_decls.h b/tests/utils/kernel/src/stl_kernel/test_decls.h index a4406a2ab79..630442afe83 100644 --- a/tests/utils/kernel/src/stl_kernel/test_decls.h +++ b/tests/utils/kernel/src/stl_kernel/test_decls.h @@ -4,8 +4,8 @@ #pragma once #include -extern const wchar_t * const STL_KERNEL_NT_DEVICE_NAME; -extern const wchar_t * const STL_KERNEL_DOS_DEVICE_NAME; +extern const wchar_t* const STL_KERNEL_NT_DEVICE_NAME; +extern const wchar_t* const STL_KERNEL_DOS_DEVICE_NAME; extern KGUARDED_MUTEX g_assert_mutex; extern "C" int main(); diff --git a/tests/utils/kernel/src/stl_kernel_loader/install.cpp b/tests/utils/kernel/src/stl_kernel_loader/install.cpp index dcf7b3546f0..2794398d5d7 100644 --- a/tests/utils/kernel/src/stl_kernel_loader/install.cpp +++ b/tests/utils/kernel/src/stl_kernel_loader/install.cpp @@ -2,21 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "install.h" -#include + #include #include -[[noreturn]] void throw_get_last_error(const char *routine) { - auto gle = GetLastError(); - char error_buffer[1024] ={0}; - - FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, //lpSource - gle, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - error_buffer, - static_cast(std::size(error_buffer)), +#include + +[[noreturn]] void throw_get_last_error(const char* routine) { + auto gle = GetLastError(); + char error_buffer[1024] = {0}; + + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, // lpSource + gle, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error_buffer, static_cast(std::size(error_buffer)), nullptr /* va_list arguments */); std::string err_text = "Error: "; @@ -28,41 +26,35 @@ } scm_handle::scm_handle() - : h(OpenSCManager( - nullptr /* lpMachineName */, - nullptr /* lpDatabaseName */, - SC_MANAGER_ALL_ACCESS)) -{ + : h(OpenSCManager(nullptr /* lpMachineName */, nullptr /* lpDatabaseName */, SC_MANAGER_ALL_ACCESS)) { if (!h) { throw_get_last_error(__FUNCTION__); } } -scm_handle::~scm_handle() -{ +scm_handle::~scm_handle() { CloseServiceHandle(h); } struct service_handle { SC_HANDLE h; - service_handle(SC_HANDLE scm, const char *name) noexcept - : h(OpenService(scm, name, SERVICE_ALL_ACCESS)) - {} + service_handle(SC_HANDLE scm, const char* name) noexcept : h(OpenService(scm, name, SERVICE_ALL_ACCESS)) {} service_handle() noexcept : h(nullptr) {} void attach(SC_HANDLE new_h) noexcept { - if(h) CloseServiceHandle(h); + if (h) + CloseServiceHandle(h); h = new_h; } - ~service_handle() - { - if(h) CloseServiceHandle(h); + ~service_handle() { + if (h) + CloseServiceHandle(h); } }; -static void stop_and_remove_driver(SC_HANDLE scm, const char *name) noexcept { +static void stop_and_remove_driver(SC_HANDLE scm, const char* name) noexcept { service_handle driver(scm, name); if (driver.h == nullptr) { @@ -70,28 +62,23 @@ static void stop_and_remove_driver(SC_HANDLE scm, const char *name) noexcept { return; } // ignore the returns, as there isn't anything we can do if the delete fails - SERVICE_STATUS serviceStatus; + SERVICE_STATUS serviceStatus; ControlService(driver.h, SERVICE_CONTROL_STOP, &serviceStatus); DeleteService(driver.h); } -static void install_and_start_driver(SC_HANDLE scm, const char *path, const char *name) { +static void install_and_start_driver(SC_HANDLE scm, const char* path, const char* name) { service_handle driver; - driver.attach( - CreateService(scm, - name, // lpServiceName - name, // lpDisplayName - SERVICE_ALL_ACCESS, - SERVICE_KERNEL_DRIVER, - SERVICE_DEMAND_START, - SERVICE_ERROR_NORMAL, - path, - nullptr, // lpLoadOrderGroup - nullptr, // lpdwTagId - nullptr, // lpDependencies - nullptr, // lpServiceStartName - nullptr // lpServiceStartName - )); + driver.attach(CreateService(scm, + name, // lpServiceName + name, // lpDisplayName + SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path, + nullptr, // lpLoadOrderGroup + nullptr, // lpdwTagId + nullptr, // lpDependencies + nullptr, // lpServiceStartName + nullptr // lpServiceStartName + )); if (driver.h == nullptr) { throw_get_last_error("CreateService"); @@ -103,9 +90,7 @@ static void install_and_start_driver(SC_HANDLE scm, const char *path, const char } } -driver_loader::driver_loader(const char *path, const char *name) - : driver_name(name) -{ +driver_loader::driver_loader(const char* path, const char* name) : driver_name(name) { // clean up any previous runs in case something went horribly wrong stop_and_remove_driver(sc_handle.get(), driver_name.c_str()); install_and_start_driver(sc_handle.get(), path, name); diff --git a/tests/utils/kernel/src/stl_kernel_loader/install.h b/tests/utils/kernel/src/stl_kernel_loader/install.h index fe314475222..f80dd540a2c 100644 --- a/tests/utils/kernel/src/stl_kernel_loader/install.h +++ b/tests/utils/kernel/src/stl_kernel_loader/install.h @@ -4,30 +4,35 @@ #pragma once #include + #include class scm_handle { private: SC_HANDLE h; + public: scm_handle(); ~scm_handle(); - scm_handle(const scm_handle &) = delete; - scm_handle &operator=(const scm_handle &) = delete; + scm_handle(const scm_handle&) = delete; + scm_handle& operator=(const scm_handle&) = delete; - SC_HANDLE get() {return h;} + SC_HANDLE get() { + return h; + } }; class driver_loader { private: scm_handle sc_handle; std::string driver_name; + public: - driver_loader(const char *path, const char *name); + driver_loader(const char* path, const char* name); ~driver_loader(); - driver_loader(const scm_handle &) = delete; - driver_loader &operator=(const scm_handle &) = delete; + driver_loader(const scm_handle&) = delete; + driver_loader& operator=(const scm_handle&) = delete; }; -[[noreturn]] void throw_get_last_error(const char *routine); +[[noreturn]] void throw_get_last_error(const char* routine); diff --git a/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp b/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp index 6a4df40fe70..61c2e1f827e 100644 --- a/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp +++ b/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp @@ -2,46 +2,39 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "install.h" -#include -#include #include #include #include +#include +#include + #include struct DeviceOpener { HANDLE h = INVALID_HANDLE_VALUE; - explicit DeviceOpener(const char *driverName) - { + explicit DeviceOpener(const char* driverName) { std::string dosName = "\\\\.\\"; dosName += driverName; - h = CreateFile( dosName.c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, - nullptr, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - nullptr); + h = CreateFile( + dosName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if ( h == INVALID_HANDLE_VALUE ){ + if (h == INVALID_HANDLE_VALUE) { throw_get_last_error(__FUNCTION__); } } - ~DeviceOpener() {CloseHandle ( h );} + ~DeviceOpener() { + CloseHandle(h); + } }; // returns true if the test passed -bool do_test(const char *path) -{ +bool do_test(const char* path) { // We have a secret handshake with the driver and the build system. // The DOS name of the driver is the same as the absolute path, // except the \ and : are replaced with ".". Shhh. Don't tell anyone. std::string driverName = path; std::replace_if( - driverName.begin(), - driverName.end(), - [](char c) {return c == '\\' || c == ':';}, - '.'); + driverName.begin(), driverName.end(), [](char c) { return c == '\\' || c == ':'; }, '.'); driver_loader sentry(path, driverName.c_str()); DeviceOpener dev(driverName.c_str()); @@ -50,41 +43,30 @@ bool do_test(const char *path) char InputBuffer[1]; TestResults OutputBuffer; - auto success = DeviceIoControl ( dev.h, - (DWORD) IOCTL_SIOCTL_METHOD_RUN_TEST, - &InputBuffer, - sizeof(InputBuffer), - &OutputBuffer, - sizeof( OutputBuffer), - &bytesReturned, - nullptr - ); + auto success = DeviceIoControl(dev.h, (DWORD) IOCTL_SIOCTL_METHOD_RUN_TEST, &InputBuffer, sizeof(InputBuffer), + &OutputBuffer, sizeof(OutputBuffer), &bytesReturned, nullptr); - if ( !success ) { + if (!success) { throw_get_last_error(__FUNCTION__); } - if(OutputBuffer.main_return != 0 || OutputBuffer.tests_failed != 0) { - printf("retval: %d\ntests failed: %d\noutput =\n%s\n", - OutputBuffer.main_return, - OutputBuffer.tests_failed, + if (OutputBuffer.main_return != 0 || OutputBuffer.tests_failed != 0) { + printf("retval: %d\ntests failed: %d\noutput =\n%s\n", OutputBuffer.main_return, OutputBuffer.tests_failed, OutputBuffer.output); return false; } return true; } -int __cdecl main(int argc, char *argv[]) -{ - if(argc < 2) { - printf( "Usage: %s \n", argv[0]); +int __cdecl main(int argc, char* argv[]) { + if (argc < 2) { + printf("Usage: %s \n", argv[0]); return 2; } try { bool result = do_test(argv[1]); return result ? 0 : 1; - } - catch(const std::exception &e) { + } catch (const std::exception& e) { printf("%s\n", e.what()); } return 2; diff --git a/tests/utils/stl/test/features.py b/tests/utils/stl/test/features.py index 3128afd165f..92a932f78ff 100644 --- a/tests/utils/stl/test/features.py +++ b/tests/utils/stl/test/features.py @@ -45,4 +45,7 @@ def getDefaultFeatures(config, litConfig): if litConfig.target_arch.casefold() == 'x86'.casefold(): DEFAULT_FEATURES.append(Feature(name='edg')) + if litConfig.is_kernel: + DEFAULT_FEATURES.append(Feature(name='kernel')) + return DEFAULT_FEATURES diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index cedc4996103..1758e8b5122 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -205,23 +205,18 @@ def getBuildSteps(self, test, litConfig, shared): yield TestStep(cmd, shared.execDir, shared.env, shouldFail) elif TestType.RUN in test.testType: shared.execFile = tmpBase + '.exe' - if not litConfig.is_kernel: - cmd = [test.cxx, test.getSourcePath(), *test.flags, *test.compileFlags, - '/Fe' + shared.execFile, '/link', *test.linkFlags] - yield TestStep(cmd, shared.execDir, shared.env, False) - - if litConfig.is_kernel: + if 'kernel' in test.requires: name = str(shared.execFile).replace('\\','.').replace(':','.') - customKernelCompileFlags = [ + test.compileFlags.append([ '/DKERNEL_TEST_NAME=L"' + name + '"', '/FIstl_kernel/kernel_test_constants.h', '/I' + litConfig.utils_dir + '/kernel/inc', '/I' + litConfig.wdk_include + '/km', #'/I' + litConfig.wdk_include + '/km/crt', #causes vadefs.h conflicts '/I' + litConfig.wdk_include + '/shared', - ] - customKernelLinkFlags = [ + ]) + test.linkFlags.append([ '/LIBPATH:' + litConfig.wdk_lib + '/km/' + litConfig.target_arch, '/IGNORE:4210', '/machine:'+litConfig.target_arch, @@ -236,16 +231,13 @@ def getBuildSteps(self, test, litConfig, shared): 'Ntstrsafe.lib', 'libcpmt.lib', 'libcmt.lib', - ] - cmd = [test.cxx, test.getSourcePath(), - *customKernelCompileFlags, - *test.flags, *test.compileFlags, - '/Fe' + shared.execFile, '/link', *test.linkFlags, - *customKernelLinkFlags, - ] - yield TestStep(cmd, shared.execDir, shared.env, False) + ]) + cmd = [test.cxx, test.getSourcePath(), *test.flags, *test.compileFlags, + '/Fe' + shared.execFile, '/link', *test.linkFlags] + yield TestStep(cmd, shared.execDir, shared.env, False) + if 'kernel' in test.requires: # sign the binary cmd = [litConfig.wdk_bin + '/x86/signtool.exe', 'sign', '/f', litConfig.cert_path, @@ -268,7 +260,7 @@ def getTestSteps(self, test, litConfig, shared): return shouldFail = TestType.FAIL in test.testType - if litConfig.is_kernel: + if 'kernel' in test.requires: cmd = [litConfig.cxx_runtime + "/stl_kernel_loader.exe", shared.execFile] else: cmd = [shared.execFile] diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index fad62453bbd..67b26f6bb86 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -30,6 +30,8 @@ class TestType(Flag): class STLTest(Test): + # TRANSITION: A lot of the members of this class could be computed at execution time to minimize the transmitted + # size of the class. def __init__(self, suite, pathInSuite, litConfig, testConfig, envlstEntry, envNum): self.compileFlags = [] @@ -173,6 +175,8 @@ def _handleEnvlst(self, litConfig, envlstEntry): self.requires.append('clr') # TRANSITION, GH-797 elif flag[1:] == 'BE': self.requires.append('edg') # available for x86, see features.py + elif flag[1:] == 'kernel': + self.requires.append('kernel') if not foundStd: Feature('c++14').enableIn(self.config) From 54fa098a591659698153da953fa50731de0ac090 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Mon, 2 Nov 2020 17:10:01 -0800 Subject: [PATCH 30/56] Update tests/utils/stl/test/format.py Co-authored-by: Stephan T. Lavavej --- tests/utils/stl/test/format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 7cf907b9b15..bcecfb73193 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -252,7 +252,7 @@ def execute(self, test, litConfig): cmd, out, err, rc = self.runStep(step, litConfig) if step.shouldFail and rc == 0: - report += stageName + ' step succeeded unxexpectedly.\n' + report += stageName + ' step succeeded unexpectedly.\n' elif rc != 0: report += stageName + ' step failed unexpectedly.\n' From 0a7194c1466335f1b492a9db2962b0064b90156d Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Mon, 2 Nov 2020 17:11:32 -0800 Subject: [PATCH 31/56] Update tests/utils/stl/test/tests.py Co-authored-by: Stephan T. Lavavej --- tests/utils/stl/test/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index fad62453bbd..acbb021c071 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -119,7 +119,7 @@ def _configureExpectedResult(self, suite, litConfig): elif self.expectedResult.isFailure: self.xfails = ['*'] elif self.config.unsupported: - self.result = Result(lit.Test.UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') + self.result = Result(UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') def _handleEnvlst(self, litConfig, envlstEntry): envCompiler = envlstEntry.getEnvVal('PM_COMPILER', 'cl') From 25d73d5c836ba96f9be1106710f538143df78091 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 2 Nov 2020 20:14:45 -0800 Subject: [PATCH 32/56] Change `/analyze` to `/analyze:autolog-`. --- azure-devops/run-build.yml | 2 +- tests/libcxx/usual_matrix.lst | 2 +- tests/std/tests/fast_matrix.lst | 2 +- tests/std/tests/rtti_matrix.lst | 2 +- tests/tr1/env_single.lst | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index 2d52b453755..bf4c1436163 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -63,7 +63,7 @@ jobs: cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=$(vcpkgLocation)\scripts\buildsystems\vcpkg.cmake ^ -DVCPKG_TARGET_TRIPLET=${{ parameters.targetPlatform }}-windows -DCMAKE_CXX_COMPILER=cl ^ -DCMAKE_BUILD_TYPE=Release -DLIT_FLAGS=$(litFlags) ^ - -DCMAKE_CXX_FLAGS=/analyze ^ + -DCMAKE_CXX_FLAGS=/analyze:autolog- ^ -S $(Build.SourcesDirectory) -B $(buildOutputLocation) cmake --build $(buildOutputLocation) displayName: 'Build the STL' diff --git a/tests/libcxx/usual_matrix.lst b/tests/libcxx/usual_matrix.lst index 5fa9799fff4..a5dd5afec7f 100644 --- a/tests/libcxx/usual_matrix.lst +++ b/tests/libcxx/usual_matrix.lst @@ -5,5 +5,5 @@ RUNALL_INCLUDE ..\universal_prefix.lst RUNALL_CROSSLIST PM_CL="/EHsc /MTd /std:c++latest /permissive- /FImsvc_stdlib_force_include.h /wd4643" RUNALL_CROSSLIST -PM_CL="/analyze /Zc:preprocessor" +PM_CL="/analyze:autolog- /Zc:preprocessor" PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing" diff --git a/tests/std/tests/fast_matrix.lst b/tests/std/tests/fast_matrix.lst index a66449fd05d..ea19bd9ea37 100644 --- a/tests/std/tests/fast_matrix.lst +++ b/tests/std/tests/fast_matrix.lst @@ -4,4 +4,4 @@ # This is for tests that take a long time to execute, so run only one configuration. RUNALL_INCLUDE .\prefix.lst RUNALL_CROSSLIST -PM_CL="/EHsc /MT /O2 /GL /std:c++latest /permissive- /analyze /w14640 /Zc:threadSafeInit-" +PM_CL="/EHsc /MT /O2 /GL /std:c++latest /permissive- /analyze:autolog- /w14640 /Zc:threadSafeInit-" diff --git a/tests/std/tests/rtti_matrix.lst b/tests/std/tests/rtti_matrix.lst index 8ec139c0375..568ccf52ab4 100644 --- a/tests/std/tests/rtti_matrix.lst +++ b/tests/std/tests/rtti_matrix.lst @@ -3,7 +3,7 @@ RUNALL_INCLUDE .\prefix.lst RUNALL_CROSSLIST -PM_CL="/EHsc /MTd /std:c++latest /permissive- /analyze /w14640 /Zc:threadSafeInit-" +PM_CL="/EHsc /MTd /std:c++latest /permissive- /analyze:autolog- /w14640 /Zc:threadSafeInit-" RUNALL_CROSSLIST PM_CL="/GR" PM_CL="/GR-" diff --git a/tests/tr1/env_single.lst b/tests/tr1/env_single.lst index 1710a2a951d..7234b0396b8 100644 --- a/tests/tr1/env_single.lst +++ b/tests/tr1/env_single.lst @@ -3,4 +3,4 @@ RUNALL_INCLUDE .\prefix.lst RUNALL_CROSSLIST -PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze /w14640 /Zc:threadSafeInit-" +PM_CL="/EHsc /MTd /D_ITERATOR_DEBUG_LEVEL=2 /std:c++latest /permissive- /analyze:autolog- /w14640 /Zc:threadSafeInit-" From 2443db66798cb4847950c52d3b29534f29beb41d Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Tue, 3 Nov 2020 13:18:00 -0800 Subject: [PATCH 33/56] Light up kernel tests in CI --- azure-devops/run-build.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index bf4c1436163..63d45812b83 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -62,9 +62,8 @@ jobs: -host_arch=amd64 -arch=${{ parameters.vsDevCmdArch }} -no_logo 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:autolog- ^ - -S $(Build.SourcesDirectory) -B $(buildOutputLocation) + -DCMAKE_BUILD_TYPE=Release -DLIT_FLAGS=$(litFlags) -DCMAKE_CXX_FLAGS=/analyze:autolog- ^ + -DSTL_IS_KERNEL=ON -S $(Build.SourcesDirectory) -B $(buildOutputLocation) cmake --build $(buildOutputLocation) displayName: 'Build the STL' timeoutInMinutes: 10 From 32377abc42bf555c465d2973fa853d2876ffe38b Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Tue, 3 Nov 2020 14:19:30 -0800 Subject: [PATCH 34/56] clang-format --- tests/utils/kernel/inc/cassert | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/utils/kernel/inc/cassert b/tests/utils/kernel/inc/cassert index d37512e2ec6..ad2f81b3c3d 100644 --- a/tests/utils/kernel/inc/cassert +++ b/tests/utils/kernel/inc/cassert @@ -7,14 +7,16 @@ extern "C" { #endif -extern volatile long *g_test_failures; -extern char *g_output_buffer; +extern volatile long* g_test_failures; +extern char* g_output_buffer; extern size_t g_space_available; -void doAssert(const char *file, int line, const char *expr); +void doAssert(const char* file, int line, const char* expr); #undef assert -#define assert(x) \ - if(!(x)) { doAssert(__FILE__, __LINE__, #x); } +#define assert(x) \ + if (!(x)) { \ + doAssert(__FILE__, __LINE__, #x); \ + } #ifdef __cplusplus } From f0c62c323eb1f9a038968e0c146b31a0ba963582 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Tue, 3 Nov 2020 14:22:31 -0800 Subject: [PATCH 35/56] Make validate happy --- tests/utils/kernel/CMakeLists.txt | 1 - tests/utils/kernel/generateMsvcCert.ps1 | 5 ++--- tests/utils/stl/test/format.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/utils/kernel/CMakeLists.txt b/tests/utils/kernel/CMakeLists.txt index fd6288eb5c8..44ca2daec09 100644 --- a/tests/utils/kernel/CMakeLists.txt +++ b/tests/utils/kernel/CMakeLists.txt @@ -42,4 +42,3 @@ target_link_libraries(stl_kernel_loader PRIVATE ucrt.lib AdvApi32.lib ) - diff --git a/tests/utils/kernel/generateMsvcCert.ps1 b/tests/utils/kernel/generateMsvcCert.ps1 index 3af7f504eaa..3ee3b256333 100644 --- a/tests/utils/kernel/generateMsvcCert.ps1 +++ b/tests/utils/kernel/generateMsvcCert.ps1 @@ -15,7 +15,8 @@ Where-Object { $_.Subject -eq 'CN=MsvcStlTestingCert' } | Remove-Item #Make the new cert -$cert = New-SelfSignedCertificate -Type CodeSigningCert -DnsName "MsvcStlTestingCert" -certstorelocation cert:\localmachine\my -NotAfter (Get-Date).AddDays(2) +$cert = New-SelfSignedCertificate -Type CodeSigningCert -DnsName "MsvcStlTestingCert" ` + -certstorelocation cert:\localmachine\my -NotAfter (Get-Date).AddDays(2) $path = 'cert:\localMachine\my\' + $cert.thumbprint $pwd = ConvertTo-SecureString -String $pass -Force -AsPlainText Export-PfxCertificate -cert $path -FilePath $out -Password $pwd @@ -23,5 +24,3 @@ Export-PfxCertificate -cert $path -FilePath $out -Password $pwd # install the cert so that we can load our drivers Import-PfxCertificate -FilePath $out -CertStoreLocation cert:\localmachine\root -Password $pwd Import-PfxCertificate -FilePath $out -CertStoreLocation cert:\localmachine\trustedpublisher -Password $pwd - - diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 6f486bb6b29..dcecfba95a8 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -237,7 +237,7 @@ def getBuildSteps(self, test, litConfig, shared): '/Fe' + shared.execFile, '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - if 'kernel' in test.requires: + if 'kernel' in test.requires: # sign the binary cmd = [litConfig.wdk_bin + '/x86/signtool.exe', 'sign', '/f', litConfig.cert_path, From 6887ca0649ebbc27168787bc62fa8171e21b092a Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Thu, 5 Nov 2020 11:33:07 -0800 Subject: [PATCH 36/56] Get new test format to work with sharding --- tests/utils/stl/test/format.py | 30 +----------- tests/utils/stl/test/tests.py | 87 ++++++++++++++++++++++++---------- 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 7cf907b9b15..f23c6ff6234 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -105,28 +105,6 @@ def getTestsInDirectory(self, testSuite, pathInSuite, litConfig, localConfig, te litConfig, localConfig, envEntry, formatString.format(envNum)) - def _parseScript(self, test): - 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) - ] - - script = \ - lit.TestRunner.parseIntegratedTestScript(test, additional_parsers=parsers, require_script=False) - - if isinstance(script, lit.Test.Result): - test.result = script - return - - test.compileFlags.extend(additionalCompileFlags) - test.fileDependencies.extend(fileDependencies) - 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: @@ -228,12 +206,8 @@ def getTestSteps(self, test, litConfig, shared): def execute(self, test, litConfig): try: - self._parseScript(test) - if test.result is not None: - # TRANSITION: Find a way to do this more cleanly. - # Lit asserts that the result has not already been set. - result = test.result - test.result = None + result = test.configureTest(litConfig) + if result: return result if test.expectedResult and test.expectedResult.isFailure: diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index fad62453bbd..52d07744245 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -30,25 +30,69 @@ class TestType(Flag): class STLTest(Test): - def __init__(self, suite, pathInSuite, litConfig, testConfig, - envlstEntry, envNum): + def __init__(self, suite, pathInSuite, litConfig, testConfig, envlstEntry, envNum): + self.envNum = envNum + self.envlstEntry = envlstEntry + Test.__init__(self, suite, pathInSuite, testConfig, None) + + def configureTest(self, litConfig): self.compileFlags = [] self.cxx = None - self.envNum = envNum self.fileDependencies = [] self.flags = [] self.isenseRspPath = None self.linkFlags = [] self.testType = None - Test.__init__(self, suite, pathInSuite, copy.deepcopy(testConfig), None) - self._configureExpectedResult(suite, litConfig) - if self.result: - return + result = self._configureExpectedResult(litConfig) + if result: + return result + + self._handleEnvlst(litConfig) + self._parseTest() + self._parseFlags() + + 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) + + 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) + + 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) + + 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') + + _, tmpBase = self.getTempPaths() + self.isenseRspPath = tmpBase + '.isense.rsp' + self.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + self.isenseRspPath]) - self._handleEnvlst(litConfig, envlstEntry) self._configureTestType() - _, tmpBase = self.getTempPaths() + 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 @@ -97,7 +141,7 @@ def getTempPaths(self): tmpBase = os.path.join(tmpDir, self.path_in_suite[-2]) return tmpDir, os.path.normpath(tmpBase) - def _configureExpectedResult(self, suite, litConfig): + def _configureExpectedResult(self, litConfig): testName = self.getTestName() self.expectedResult = None @@ -115,14 +159,16 @@ def _configureExpectedResult(self, suite, litConfig): if self.expectedResult is not None: if self.expectedResult == SKIPPED: - self.result = Result(SKIPPED, 'This test was explicitly marked as skipped') + return Result(SKIPPED, 'This test was explicitly marked as skipped') elif self.expectedResult.isFailure: self.xfails = ['*'] elif self.config.unsupported: - self.result = Result(lit.Test.UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') + return Result(UNSUPPORTED, 'This test was marked as unsupported by a lit.cfg') + + return None - def _handleEnvlst(self, litConfig, envlstEntry): - envCompiler = envlstEntry.getEnvVal('PM_COMPILER', 'cl') + def _handleEnvlst(self, litConfig): + envCompiler = self.envlstEntry.getEnvVal('PM_COMPILER', 'cl') cxx = None if not os.path.isfile(envCompiler): @@ -142,8 +188,8 @@ def _handleEnvlst(self, litConfig, envlstEntry): self.compileFlags = copy.deepcopy(litConfig.compile_flags[self.config.name]) self.linkFlags = copy.deepcopy(litConfig.link_flags[self.config.name]) - self.compileFlags.extend(envlstEntry.getEnvVal('PM_CL', '').split()) - self.linkFlags.extend(envlstEntry.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()): targetArch = litConfig.target_arch.casefold() @@ -154,6 +200,7 @@ def _handleEnvlst(self, litConfig, envlstEntry): self.cxx = os.path.normpath(cxx) + def _parseFlags(self): foundStd = False for flag in chain(self.flags, self.compileFlags, self.linkFlags): if flag[1:5] == 'std:': @@ -178,14 +225,6 @@ def _handleEnvlst(self, litConfig, envlstEntry): Feature('c++14').enableIn(self.config) self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17= ') - if 'edg_drop' in self.config.available_features: - if not 'edg' in self.requires: - self.result = Result(UNSUPPORTED, 'We only run /BE tests with the edg drop') - else: - _, tmpBase = self.getTempPaths() - self.isenseRspPath = tmpBase + '.isense.rsp' - self.compileFlags.extend(['/dE--write-isense-rsp', '/dE' + self.isenseRspPath]) - class LibcxxTest(STLTest): def getTestName(self): From 4e5111843bf1d45390ca8dc69b4345a9e19dd05c Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Thu, 5 Nov 2020 11:37:35 -0800 Subject: [PATCH 37/56] Update tests/utils/stl/test/format.py Co-authored-by: Casey Carter --- tests/utils/stl/test/format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 3895cd6476a..2526a4f43aa 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -33,7 +33,7 @@ class TestStep: def _mergeEnvironments(currentEnv, otherEnv): """Merges two execution environments. - If both environments contain the PATH variables, they are also merged + If both environments contain PATH variables, they are also merged using the proper separator. """ resultEnv = dict(currentEnv) From ac12e3c862aaa01fca929d763efcb39a66f6b716 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Thu, 5 Nov 2020 11:38:08 -0800 Subject: [PATCH 38/56] Update tests/utils/stl/test/tests.py Co-authored-by: Casey Carter --- tests/utils/stl/test/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index 52d07744245..5ff57faa2df 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -107,7 +107,7 @@ def _configureTestType(self): 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')): + 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 From 7417354b9e7b8d94f0868c2bb1c89596de190780 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Thu, 5 Nov 2020 11:56:08 -0800 Subject: [PATCH 39/56] We don't need to set this internal variable --- tests/utils/stl/test/tests.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index 5ff57faa2df..c31e460e5a2 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -207,13 +207,10 @@ def _parseFlags(self): foundStd = True if flag[5:] == 'c++latest': Feature('c++2a').enableIn(self.config) - self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17=constexpr') elif flag[5:] == 'c++17': Feature('c++17').enableIn(self.config) - self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17=constexpr') elif flag[5:] == 'c++14': Feature('c++14').enableIn(self.config) - self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17= ') elif flag[1:] == 'clr:pure': self.requires.append('clr_pure') # TRANSITION, GH-798 elif flag[1:] == 'clr': @@ -223,7 +220,6 @@ def _parseFlags(self): if not foundStd: Feature('c++14').enableIn(self.config) - self.compileFlags.append('/D_LIBCPP_CONSTEXPR_AFTER_CXX17= ') class LibcxxTest(STLTest): From 227efe08677e16a956f79695da6517e02bcfa6d7 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Thu, 5 Nov 2020 12:00:18 -0800 Subject: [PATCH 40/56] Update tests/utils/stl/test/tests.py Co-authored-by: Casey Carter --- tests/utils/stl/test/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index c31e460e5a2..a46e1a558d1 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -55,7 +55,7 @@ def configureTest(self, litConfig): 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) + return Result(UNSUPPORTED, "Test requires the following unavailable features: %s" % msg) unsupported_features = self.getUnsupportedFeatures() if unsupported_features: From 3725d6d573acccab1c76dcc00a3d9559ddbb0e93 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Thu, 5 Nov 2020 12:00:31 -0800 Subject: [PATCH 41/56] Update tests/utils/stl/test/tests.py Co-authored-by: Casey Carter --- tests/utils/stl/test/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index a46e1a558d1..ced4ff2b2d6 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -60,7 +60,7 @@ def configureTest(self, litConfig): 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) + return Result(UNSUPPORTED, "Test does not support the following features and/or targets: %s" % msg) if not self.isWithinFeatureLimits(): msg = ', '.join(self.config.limit_to_features) From ad8a0034ca23fcb557c6b96e8c9dbd927132fa30 Mon Sep 17 00:00:00 2001 From: Ben Craig Date: Fri, 13 Nov 2020 16:30:19 -0600 Subject: [PATCH 42/56] first kernel test --- .../env.lst | 1 + .../test.cpp | 13 ++++++++- tests/std/tests/kernel.lst | 4 +++ tests/utils/stl/test/format.py | 29 +++++++------------ 4 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 tests/std/tests/kernel.lst diff --git a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/env.lst b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/env.lst index f141421b292..79324f369a2 100644 --- a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/env.lst +++ b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/env.lst @@ -2,3 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception RUNALL_INCLUDE ..\impure_matrix.lst +RUNALL_INCLUDE ..\kernel.lst diff --git a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp index 6e9a163345d..60270128385 100644 --- a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp +++ b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp @@ -15,7 +15,6 @@ #include #include - using namespace std; #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) @@ -503,12 +502,24 @@ void test_layout_paranoia() { assert(b[2] == 3); } +#ifdef _KERNEL_MODE + +#define assert_bitwise_identical(MSG, LHS, RHS) { \ + double lhs = LHS; \ + double rhs = RHS; \ + if (memcmp(&lhs, &rhs, sizeof(lhs)) != 0) { \ + assert(!MSG); \ + } \ +} + +#else void assert_bitwise_identical(const char* const msg, const double lhs, const double rhs) { if (memcmp(&lhs, &rhs, sizeof(lhs)) != 0) { printf("counterexample found in %s: %a and %a\n", msg, lhs, rhs); abort(); } } +#endif void test_double_identical_results() { #if _HAS_CXX20 diff --git a/tests/std/tests/kernel.lst b/tests/std/tests/kernel.lst new file mode 100644 index 00000000000..9b512903a49 --- /dev/null +++ b/tests/std/tests/kernel.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +PM_CL="/kernel /Zc:preprocessor /std:c++latest /w14640 /Zc:threadSafeInit- /DNO_TEST_ENVIRONMENT_PREPARER" PM_LINK="/IGNORE:4210 /entry:DriverEntry /subsystem:native /nodefaultlib stl_kernel.lib BufferOverflowFastFailK.lib ntoskrnl.lib hal.lib wmilib.lib Ntstrsafe.lib libcpmt.lib libcmt.lib" diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index dcecfba95a8..09e6a4be63e 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -15,6 +15,7 @@ import os import re import shutil +import traceback import lit @@ -205,39 +206,29 @@ def getBuildSteps(self, test, litConfig, shared): yield TestStep(cmd, shared.execDir, shared.env, shouldFail) elif TestType.RUN in test.testType: shared.execFile = tmpBase + '.exe' - if 'kernel' in test.requires: + isKernel = 'kernel' in test.requires + if isKernel: name = str(shared.execFile).replace('\\','.').replace(':','.') - test.compileFlags.append([ + test.compileFlags = [ '/DKERNEL_TEST_NAME=L"' + name + '"', '/FIstl_kernel/kernel_test_constants.h', '/I' + litConfig.utils_dir + '/kernel/inc', '/I' + litConfig.wdk_include + '/km', #'/I' + litConfig.wdk_include + '/km/crt', #causes vadefs.h conflicts '/I' + litConfig.wdk_include + '/shared', - ]) - test.linkFlags.append([ + ] + test.compileFlags + test.linkFlags.extend([ '/LIBPATH:' + litConfig.wdk_lib + '/km/' + litConfig.target_arch, - '/IGNORE:4210', '/machine:'+litConfig.target_arch, - '/entry:DriverEntry', - '/subsystem:native', - '/nodefaultlib', - 'stl_kernel.lib', - 'BufferOverflowFastFailK.lib', - 'ntoskrnl.lib', - 'hal.lib', - 'wmilib.lib', - 'Ntstrsafe.lib', - 'libcpmt.lib', - 'libcmt.lib', ]) + # common path for kernel and non-kernel cmd = [test.cxx, test.getSourcePath(), *test.flags, *test.compileFlags, '/Fe' + shared.execFile, '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - if 'kernel' in test.requires: + if isKernel: # sign the binary cmd = [litConfig.wdk_bin + '/x86/signtool.exe', 'sign', '/f', litConfig.cert_path, @@ -303,7 +294,9 @@ def execute(self, test, litConfig): return (passVar, '') except Exception as e: - litConfig.error(repr(e)) + errorStr = "".join(traceback.format_exception(None, e, e.__traceback__)) + litConfig.error(errorStr) + return (lit.Test.FAIL, errorStr) class LibcxxTestFormat(STLTestFormat): From 721cb3f4d131698e95d127b81a88cb716dc0cd74 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Sat, 5 Dec 2020 07:19:31 -0800 Subject: [PATCH 43/56] Point to the WDK --- azure-devops/run-build.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index 63d45812b83..50c2a7e2caa 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -63,7 +63,11 @@ 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:autolog- ^ - -DSTL_IS_KERNEL=ON -S $(Build.SourcesDirectory) -B $(buildOutputLocation) + -DSTL_IS_KERNEL=ON ^ + -DWDK_INCLUDE_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0" ^ + -DWDK_LIB_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0" ^ + -DWDK_BIN_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0" ^ + -S $(Build.SourcesDirectory) -B $(buildOutputLocation) cmake --build $(buildOutputLocation) displayName: 'Build the STL' timeoutInMinutes: 10 From 51acb6671bb9fbb72fef22aab1ddcf1632d35f29 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Sat, 5 Dec 2020 07:47:04 -0800 Subject: [PATCH 44/56] Fix line endings --- tests/utils/stl/test/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/stl/test/features.py b/tests/utils/stl/test/features.py index a13cf1b6138..2350f3d72b3 100644 --- a/tests/utils/stl/test/features.py +++ b/tests/utils/stl/test/features.py @@ -52,7 +52,7 @@ def getDefaultFeatures(config, litConfig): if litConfig.target_arch.casefold() == 'arm'.casefold(): DEFAULT_FEATURES.append(Feature(name='arch_vfpv4')) - + if litConfig.is_kernel: DEFAULT_FEATURES.append(Feature(name='kernel')) From 4640507f284c6339829cc3cea9104691a76f3eb6 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Sat, 5 Dec 2020 08:06:40 -0800 Subject: [PATCH 45/56] clang-format --- .../test.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp index 60270128385..489924eda89 100644 --- a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp +++ b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp @@ -504,13 +504,14 @@ void test_layout_paranoia() { #ifdef _KERNEL_MODE -#define assert_bitwise_identical(MSG, LHS, RHS) { \ - double lhs = LHS; \ - double rhs = RHS; \ - if (memcmp(&lhs, &rhs, sizeof(lhs)) != 0) { \ - assert(!MSG); \ - } \ -} +#define assert_bitwise_identical(MSG, LHS, RHS) \ + { \ + double lhs = LHS; \ + double rhs = RHS; \ + if (memcmp(&lhs, &rhs, sizeof(lhs)) != 0) { \ + assert(!MSG); \ + } \ + } #else void assert_bitwise_identical(const char* const msg, const double lhs, const double rhs) { From 33319b48a7f7fa82e29ce4c8a05c8470cf9de228 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Sat, 5 Dec 2020 15:50:00 -0800 Subject: [PATCH 46/56] Suppress 5040 in the WDK --- tests/utils/kernel/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/utils/kernel/CMakeLists.txt b/tests/utils/kernel/CMakeLists.txt index 44ca2daec09..96d597063ab 100644 --- a/tests/utils/kernel/CMakeLists.txt +++ b/tests/utils/kernel/CMakeLists.txt @@ -26,7 +26,9 @@ target_include_directories(stl_kernel PRIVATE ${WDK_INCLUDE_DIRECTORY}/km/crt ${WDK_INCLUDE_DIRECTORY}/shared ) -target_compile_options(stl_kernel PRIVATE /kernel) + +# TRANSITION, WDK needs to suppress C5040 +target_compile_options(stl_kernel PRIVATE /kernel /wd5040) add_executable(stl_kernel_loader ${STL_KERNEL_LOADER_SOURCES}) target_include_directories(stl_kernel_loader PRIVATE From dc583343fdba933b3ec6e28076230109cdc8096e Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Sun, 6 Dec 2020 16:45:26 -0800 Subject: [PATCH 47/56] Make everything more verbose (maybe) --- azure-devops/run-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-devops/run-build.yml b/azure-devops/run-build.yml index 4a42ced8020..a517be46d17 100644 --- a/azure-devops/run-build.yml +++ b/azure-devops/run-build.yml @@ -8,7 +8,7 @@ jobs: variables: buildOutputLocation: 'D:\build\${{ parameters.targetPlatform }}' litFlags: '-j$(testParallelism);--timeout=240;--shuffle;--xunit-xml-output=$(buildOutputLocation)/test-results.xml' - shardFlags: '--num-shards=${{ parameters.numShards }};--run-shard=${{ parameters.shardNum }}' + shardFlags: '-vv;--num-shards=${{ parameters.numShards }};--run-shard=${{ parameters.shardNum }}' vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' steps: - script: | @@ -64,7 +64,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);$(shardFlags) ^ - -DCMAKE_CXX_FLAGS=/analyze:autolog- ^ -DSTL_IS_KERNEL=ON ^ + -DCMAKE_CXX_FLAGS="/showIncludes /analyze:autolog-" -DSTL_IS_KERNEL=ON ^ -DWDK_INCLUDE_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0" ^ -DWDK_LIB_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0" ^ -DWDK_BIN_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0" ^ From e910d8108a0a8a1c464e9950a18e41d73a978810 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Sun, 6 Dec 2020 20:31:50 -0800 Subject: [PATCH 48/56] Add a linking pragma --- tests/utils/kernel/src/stl_kernel/stl_kernel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp index 89a1922f7f4..b85637c3997 100644 --- a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp +++ b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp @@ -9,6 +9,8 @@ // at the globals that have the error text and the failure count #include +#pragma comment(lib, "ntoskrnl") + struct device_handle { DEVICE_OBJECT* h = nullptr; From 4f3b0fa5e1caf273c80c46677d1ecc7c3be7e63a Mon Sep 17 00:00:00 2001 From: Ben Craig Date: Fri, 18 Dec 2020 14:55:12 -0600 Subject: [PATCH 49/56] Handle calling convention differences --- tests/std/tests/kernel.lst | 2 +- tests/utils/kernel/CMakeLists.txt | 8 +++++++- .../utils/kernel/src/stl_kernel/stl_kernel.cpp | 1 + tests/utils/kernel/src/stl_kernel/test_decls.h | 2 +- tests/utils/stl/test/tests.py | 17 +++++++++++++++-- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/std/tests/kernel.lst b/tests/std/tests/kernel.lst index 9b512903a49..3c8314e54f2 100644 --- a/tests/std/tests/kernel.lst +++ b/tests/std/tests/kernel.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -PM_CL="/kernel /Zc:preprocessor /std:c++latest /w14640 /Zc:threadSafeInit- /DNO_TEST_ENVIRONMENT_PREPARER" PM_LINK="/IGNORE:4210 /entry:DriverEntry /subsystem:native /nodefaultlib stl_kernel.lib BufferOverflowFastFailK.lib ntoskrnl.lib hal.lib wmilib.lib Ntstrsafe.lib libcpmt.lib libcmt.lib" +PM_CL="/kernel /Zc:preprocessor /std:c++latest /w14640 /Zc:threadSafeInit- /DNO_TEST_ENVIRONMENT_PREPARER" PM_LINK="/IGNORE:4210 /subsystem:native /nodefaultlib stl_kernel.lib BufferOverflowFastFailK.lib ntoskrnl.lib hal.lib wmilib.lib Ntstrsafe.lib libcpmt.lib libcmt.lib" diff --git a/tests/utils/kernel/CMakeLists.txt b/tests/utils/kernel/CMakeLists.txt index 96d597063ab..74e41579c01 100644 --- a/tests/utils/kernel/CMakeLists.txt +++ b/tests/utils/kernel/CMakeLists.txt @@ -28,7 +28,13 @@ target_include_directories(stl_kernel PRIVATE ) # TRANSITION, WDK needs to suppress C5040 -target_compile_options(stl_kernel PRIVATE /kernel /wd5040) +if(VCLIBS_TARGET_ARCHITECTURE STREQUAL "x86") + set(STL_KERNEL_CALLING_CONVENTION "/Gz") +else() + set(STL_KERNEL_CALLING_CONVENTION "") +endif() + +target_compile_options(stl_kernel PRIVATE /kernel /wd5040 ${STL_KERNEL_CALLING_CONVENTION}) add_executable(stl_kernel_loader ${STL_KERNEL_LOADER_SOURCES}) target_include_directories(stl_kernel_loader PRIVATE diff --git a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp index b85637c3997..89722942578 100644 --- a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp +++ b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp @@ -58,6 +58,7 @@ DRIVER_UNLOAD PAGE, StlKernelUnloadDriver; #pragma alloc_text(PAGE, StlKernelDeviceControl) #pragma alloc_text(PAGE, StlKernelUnloadDriver) +_Use_decl_annotations_ NTSTATUS DriverEntry(DRIVER_OBJECT* driver, UNICODE_STRING* /*reg_path*/) { UNICODE_STRING nt_name; RtlInitUnicodeString(&nt_name, STL_KERNEL_NT_DEVICE_NAME); diff --git a/tests/utils/kernel/src/stl_kernel/test_decls.h b/tests/utils/kernel/src/stl_kernel/test_decls.h index 630442afe83..d4642facaa9 100644 --- a/tests/utils/kernel/src/stl_kernel/test_decls.h +++ b/tests/utils/kernel/src/stl_kernel/test_decls.h @@ -8,4 +8,4 @@ extern const wchar_t* const STL_KERNEL_NT_DEVICE_NAME; extern const wchar_t* const STL_KERNEL_DOS_DEVICE_NAME; extern KGUARDED_MUTEX g_assert_mutex; -extern "C" int main(); +extern "C" int __cdecl main(); diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index bd056c0db4a..e8c26a3ffe3 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -50,7 +50,7 @@ def configureTest(self, litConfig): self._handleEnvlst(litConfig) self._parseTest() - self._parseFlags() + self._parseFlags(litConfig) missing_required_features = self.getMissingRequiredFeatures() if missing_required_features: @@ -200,8 +200,9 @@ def _handleEnvlst(self, litConfig): self.cxx = os.path.normpath(cxx) - def _parseFlags(self): + def _parseFlags(self, litConfig): foundStd = False + isKernel = False for flag in chain(self.flags, self.compileFlags, self.linkFlags): if flag[1:5] == 'std:': foundStd = True @@ -225,6 +226,18 @@ def _parseFlags(self): self.requires.append('arch_vfpv4') # available for arm, see features.py elif flag[1:] == 'kernel': self.requires.append('kernel') + isKernel = True + + if isKernel: + targetArch = litConfig.target_arch.casefold() + if (targetArch == 'x86'.casefold()): + # 32-bit kernel uses stdcall by default + self.compileFlags.append('/Gz') + self.compileFlags.append('/wd4007') + self.linkFlags.append('/entry:DriverEntry@8') + else: + self.linkFlags.append('/entry:DriverEntry') + if not foundStd: Feature('c++14').enableIn(self.config) From f041be3c6630a9e283ae90ac567ca22e662869a0 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Mon, 21 Dec 2020 14:38:16 -0800 Subject: [PATCH 50/56] Update tests.py --- tests/utils/stl/test/tests.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index e8c26a3ffe3..690f270418c 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -202,7 +202,6 @@ def _handleEnvlst(self, litConfig): def _parseFlags(self, litConfig): foundStd = False - isKernel = False for flag in chain(self.flags, self.compileFlags, self.linkFlags): if flag[1:5] == 'std:': foundStd = True @@ -226,18 +225,16 @@ def _parseFlags(self, litConfig): self.requires.append('arch_vfpv4') # available for arm, see features.py elif flag[1:] == 'kernel': self.requires.append('kernel') - isKernel = True - - if isKernel: - targetArch = litConfig.target_arch.casefold() - if (targetArch == 'x86'.casefold()): - # 32-bit kernel uses stdcall by default - self.compileFlags.append('/Gz') - self.compileFlags.append('/wd4007') - self.linkFlags.append('/entry:DriverEntry@8') - else: - self.linkFlags.append('/entry:DriverEntry') - + # TRANSITION, We should support kernel mode tests on all platforms + self.requires.append('x64') + targetArch = litConfig.target_arch.casefold() + if (targetArch == 'x86'.casefold()): + # 32-bit kernel uses stdcall by default + self.compileFlags.append('/Gz') + self.compileFlags.append('/wd4007') + self.linkFlags.append('/entry:DriverEntry@8') + else: + self.linkFlags.append('/entry:DriverEntry') if not foundStd: Feature('c++14').enableIn(self.config) From 6f78416abcf3b904a8b564ec7093ad57f2e26717 Mon Sep 17 00:00:00 2001 From: Curtis Jacques Bezault Date: Mon, 21 Dec 2020 14:43:26 -0800 Subject: [PATCH 51/56] clang-format --- tests/utils/kernel/src/stl_kernel/stl_kernel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp index 89722942578..812c40e33d2 100644 --- a/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp +++ b/tests/utils/kernel/src/stl_kernel/stl_kernel.cpp @@ -58,8 +58,7 @@ DRIVER_UNLOAD PAGE, StlKernelUnloadDriver; #pragma alloc_text(PAGE, StlKernelDeviceControl) #pragma alloc_text(PAGE, StlKernelUnloadDriver) -_Use_decl_annotations_ -NTSTATUS DriverEntry(DRIVER_OBJECT* driver, UNICODE_STRING* /*reg_path*/) { +_Use_decl_annotations_ NTSTATUS DriverEntry(DRIVER_OBJECT* driver, UNICODE_STRING* /*reg_path*/) { UNICODE_STRING nt_name; RtlInitUnicodeString(&nt_name, STL_KERNEL_NT_DEVICE_NAME); From db798ef93645d60201b735ad1082eeffb83dc2ec Mon Sep 17 00:00:00 2001 From: Ben Craig Date: Wed, 23 Dec 2020 16:18:42 -0600 Subject: [PATCH 52/56] Always compile kernel tests, but only run on amd64 --- tests/utils/stl/test/format.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 7a2a995e700..88f7618af8e 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -139,7 +139,6 @@ def runStep(self, testStep, litConfig): testStep.workDir = os.getcwd() env = _mergeEnvironments(os.environ, testStep.env) - return testStep.cmd, *stl.util.executeCommand(testStep.cmd, cwd=testStep.workDir, env=env) def getStages(self, test, litConfig): @@ -189,6 +188,7 @@ def getBuildSteps(self, test, litConfig, shared): elif TestType.RUN in test.testType: shared.execFile = tmpBase + '.exe' isKernel = 'kernel' in test.requires + needsSigning = False if isKernel: name = str(shared.execFile).replace('\\','.').replace(':','.') @@ -205,12 +205,15 @@ def getBuildSteps(self, test, litConfig, shared): '/machine:'+litConfig.target_arch, ]) + # only sign (and run) kernel mode tests on x64 + needsSigning = (litConfig.target_arch == 'x64'.casefold()) + # common path for kernel and non-kernel cmd = [test.cxx, test.getSourcePath(), *test.flags, *test.compileFlags, '/Fe' + shared.execFile, '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - if isKernel: + if needsSigning: # sign the binary cmd = [litConfig.wdk_bin + '/x86/signtool.exe', 'sign', '/f', litConfig.cert_path, @@ -234,6 +237,11 @@ def getTestSteps(self, test, litConfig, shared): shouldFail = TestType.FAIL in test.testType if 'kernel' in test.requires: + if litConfig.target_arch != 'x64'.casefold(): + # don't attempt to run kernel tests on any platform except + # x64. We only build on x64 right now. + yield from [] + return cmd = [litConfig.cxx_runtime + "/stl_kernel_loader.exe", shared.execFile] else: cmd = [shared.execFile] From 3886633537a85d8d6ffc44d3104a0c39783a6747 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Mon, 4 Jan 2021 11:31:23 -0800 Subject: [PATCH 53/56] Update format.py --- tests/utils/stl/test/format.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 88f7618af8e..61207a094ed 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -188,7 +188,7 @@ def getBuildSteps(self, test, litConfig, shared): elif TestType.RUN in test.testType: shared.execFile = tmpBase + '.exe' isKernel = 'kernel' in test.requires - needsSigning = False + if isKernel: name = str(shared.execFile).replace('\\','.').replace(':','.') @@ -205,15 +205,13 @@ def getBuildSteps(self, test, litConfig, shared): '/machine:'+litConfig.target_arch, ]) - # only sign (and run) kernel mode tests on x64 - needsSigning = (litConfig.target_arch == 'x64'.casefold()) - # common path for kernel and non-kernel cmd = [test.cxx, test.getSourcePath(), *test.flags, *test.compileFlags, '/Fe' + shared.execFile, '/link', *test.linkFlags] yield TestStep(cmd, shared.execDir, shared.env, False) - if needsSigning: + # only sign (and run) kernel mode tests on x64 + if isKernel and 'x64' in test.requires: # sign the binary cmd = [litConfig.wdk_bin + '/x86/signtool.exe', 'sign', '/f', litConfig.cert_path, From ba553ad7b1ccd2eafc46b19146b2df2e5cc1f4ac Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Mon, 4 Jan 2021 12:22:18 -0800 Subject: [PATCH 54/56] Update format.py --- tests/utils/stl/test/format.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/utils/stl/test/format.py b/tests/utils/stl/test/format.py index 61207a094ed..4f0340e8a44 100644 --- a/tests/utils/stl/test/format.py +++ b/tests/utils/stl/test/format.py @@ -34,11 +34,7 @@ class TestStep: def _mergeEnvironments(currentEnv, otherEnv): """Merges two execution environments. -<<<<<<< HEAD - If both environments contain the PATH variables, they are also merged -======= If both environments contain PATH variables, they are also merged ->>>>>>> e604b6c2ff7e425940264858dba2bc4bfd052b55 using the proper separator. """ resultEnv = dict(currentEnv) From 99e3d46ee59775f338bdcc75c9f7b6abd987cc7d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 13 Feb 2021 16:31:38 -0800 Subject: [PATCH 55/56] Define CMAKE_CXX_FLAGS and STL_IS_KERNEL on separate lines. --- azure-devops/cmake-configure-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-devops/cmake-configure-build.yml b/azure-devops/cmake-configure-build.yml index 46cf78cad74..2525d3e2d01 100644 --- a/azure-devops/cmake-configure-build.yml +++ b/azure-devops/cmake-configure-build.yml @@ -38,7 +38,8 @@ steps: -DCMAKE_CXX_COMPILER=cl ^ -DCMAKE_BUILD_TYPE=Release ^ -DLIT_FLAGS=$(litFlags) ^ - -DCMAKE_CXX_FLAGS="/showIncludes /analyze:autolog-" -DSTL_IS_KERNEL=ON ^ + -DCMAKE_CXX_FLAGS="/showIncludes /analyze:autolog-" ^ + -DSTL_IS_KERNEL=ON ^ -DWDK_INCLUDE_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0" ^ -DWDK_LIB_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0" ^ -DWDK_BIN_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0" ^ From f44db64b72ab6e325aefb194d942a82c5ae51671 Mon Sep 17 00:00:00 2001 From: Ben Craig Date: Sun, 16 May 2021 10:12:55 -0500 Subject: [PATCH 56/56] STL review comments --- azure-devops/cmake-configure-build.yml | 2 +- .../tests/Dev11_0863628_atomic_compare_exchange/test.cpp | 4 ++-- tests/utils/kernel/generateMsvcCert.ps1 | 7 +++++-- tests/utils/kernel/inc/cassert | 2 +- tests/utils/kernel/inc/stl_kernel/stl_kernel.h | 7 ++++--- tests/utils/kernel/src/stl_kernel/doAssert.cpp | 2 +- tests/utils/kernel/src/stl_kernel_loader/testapp.cpp | 8 ++++---- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/azure-devops/cmake-configure-build.yml b/azure-devops/cmake-configure-build.yml index 2525d3e2d01..5d2cb813296 100644 --- a/azure-devops/cmake-configure-build.yml +++ b/azure-devops/cmake-configure-build.yml @@ -38,7 +38,7 @@ steps: -DCMAKE_CXX_COMPILER=cl ^ -DCMAKE_BUILD_TYPE=Release ^ -DLIT_FLAGS=$(litFlags) ^ - -DCMAKE_CXX_FLAGS="/showIncludes /analyze:autolog-" ^ + -DCMAKE_CXX_FLAGS="/analyze:autolog-" ^ -DSTL_IS_KERNEL=ON ^ -DWDK_INCLUDE_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0" ^ -DWDK_LIB_DIRECTORY="C:/Program Files (x86)/Windows Kits/10/Lib/10.0.19041.0" ^ diff --git a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp index 489924eda89..9c3b6e60693 100644 --- a/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp +++ b/tests/std/tests/Dev11_0863628_atomic_compare_exchange/test.cpp @@ -513,14 +513,14 @@ void test_layout_paranoia() { } \ } -#else +#else // _KERNEL_MODE void assert_bitwise_identical(const char* const msg, const double lhs, const double rhs) { if (memcmp(&lhs, &rhs, sizeof(lhs)) != 0) { printf("counterexample found in %s: %a and %a\n", msg, lhs, rhs); abort(); } } -#endif +#endif // _KERNEL_MODE void test_double_identical_results() { #if _HAS_CXX20 diff --git a/tests/utils/kernel/generateMsvcCert.ps1 b/tests/utils/kernel/generateMsvcCert.ps1 index 3ee3b256333..a950ab6ef87 100644 --- a/tests/utils/kernel/generateMsvcCert.ps1 +++ b/tests/utils/kernel/generateMsvcCert.ps1 @@ -1,4 +1,7 @@ -param([string]$out="MsvcStlTestingCert.pfx",[string]$pass="foo") +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +param([string]$out="MsvcStlTestingCert.pfx",[string]$pass="placeholderPassword") $ErrorActionPreference = 'Stop' # Clean up old certificates @@ -14,7 +17,7 @@ Get-ChildItem cert:\localmachine\trustedpublisher | Where-Object { $_.Subject -eq 'CN=MsvcStlTestingCert' } | Remove-Item -#Make the new cert +# Make the new cert $cert = New-SelfSignedCertificate -Type CodeSigningCert -DnsName "MsvcStlTestingCert" ` -certstorelocation cert:\localmachine\my -NotAfter (Get-Date).AddDays(2) $path = 'cert:\localMachine\my\' + $cert.thumbprint diff --git a/tests/utils/kernel/inc/cassert b/tests/utils/kernel/inc/cassert index ad2f81b3c3d..6bc2b2ac56e 100644 --- a/tests/utils/kernel/inc/cassert +++ b/tests/utils/kernel/inc/cassert @@ -7,7 +7,7 @@ extern "C" { #endif -extern volatile long* g_test_failures; +extern int* g_test_failures; extern char* g_output_buffer; extern size_t g_space_available; void doAssert(const char* file, int line, const char* expr); diff --git a/tests/utils/kernel/inc/stl_kernel/stl_kernel.h b/tests/utils/kernel/inc/stl_kernel/stl_kernel.h index 8fba45808f2..43c819cebee 100644 --- a/tests/utils/kernel/inc/stl_kernel/stl_kernel.h +++ b/tests/utils/kernel/inc/stl_kernel/stl_kernel.h @@ -11,8 +11,9 @@ #define IOCTL_SIOCTL_METHOD_RUN_TEST CTL_CODE(40000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) -typedef struct TestResults { +struct TestResults { int main_return; - long tests_failed; + int tests_failed; + // arbitrary buffer size, chosen to make the structure a "round" 4K char output[4088]; -} TestResults; +}; diff --git a/tests/utils/kernel/src/stl_kernel/doAssert.cpp b/tests/utils/kernel/src/stl_kernel/doAssert.cpp index f5f13012715..1e886d84c36 100644 --- a/tests/utils/kernel/src/stl_kernel/doAssert.cpp +++ b/tests/utils/kernel/src/stl_kernel/doAssert.cpp @@ -7,7 +7,7 @@ KGUARDED_MUTEX g_assert_mutex; extern "C" { -long* g_test_failures; +int* g_test_failures; char* g_output_buffer; size_t g_space_available; } diff --git a/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp b/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp index 61c2e1f827e..fd15dc85df2 100644 --- a/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp +++ b/tests/utils/kernel/src/stl_kernel_loader/testapp.cpp @@ -13,7 +13,7 @@ struct DeviceOpener { HANDLE h = INVALID_HANDLE_VALUE; explicit DeviceOpener(const char* driverName) { - std::string dosName = "\\\\.\\"; + std::string dosName = R"(\\.\)"; dosName += driverName; h = CreateFile( dosName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); @@ -43,8 +43,8 @@ bool do_test(const char* path) { char InputBuffer[1]; TestResults OutputBuffer; - auto success = DeviceIoControl(dev.h, (DWORD) IOCTL_SIOCTL_METHOD_RUN_TEST, &InputBuffer, sizeof(InputBuffer), - &OutputBuffer, sizeof(OutputBuffer), &bytesReturned, nullptr); + auto success = DeviceIoControl(dev.h, static_cast(IOCTL_SIOCTL_METHOD_RUN_TEST), &InputBuffer, + sizeof(InputBuffer), &OutputBuffer, sizeof(OutputBuffer), &bytesReturned, nullptr); if (!success) { throw_get_last_error(__FUNCTION__); @@ -60,7 +60,7 @@ bool do_test(const char* path) { int __cdecl main(int argc, char* argv[]) { if (argc < 2) { - printf("Usage: %s \n", argv[0]); + printf("Usage: %s \n", argv[0]); return 2; } try {