зеркало из https://github.com/microsoft/cppwinrt.git
Remove old Windows 7 support code (#1348)
This commit is contained in:
Родитель
9b453cfc51
Коммит
de6ca88bd6
|
@ -97,7 +97,7 @@ jobs:
|
|||
compiler: [MSVC, clang-cl]
|
||||
arch: [x86, x64, arm64]
|
||||
config: [Debug, Release]
|
||||
test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_win7, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none]
|
||||
test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none]
|
||||
exclude:
|
||||
- arch: arm64
|
||||
config: Debug
|
||||
|
@ -250,120 +250,6 @@ jobs:
|
|||
_build/${{ matrix.arch }}/${{ matrix.config }}/*.lib
|
||||
_build/${{ matrix.arch }}/${{ matrix.config }}/*.pdb
|
||||
|
||||
test-llvm-mingw-cppwinrt:
|
||||
name: 'llvm-mingw: Build and test'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [i686, x86_64]
|
||||
config: [Debug, Release]
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
CMAKE_COLOR_DIAGNOSTICS: 1
|
||||
CLICOLOR_FORCE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- id: setup-llvm
|
||||
name: Set up llvm-mingw
|
||||
uses: ./.github/actions/setup-llvm-mingw
|
||||
with:
|
||||
host-arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Build cppwinrt
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
if ("${{ matrix.config }}" -eq "Debug") {
|
||||
$sanitizers = "TRUE"
|
||||
} else {
|
||||
$sanitizers = "FALSE"
|
||||
}
|
||||
cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.config }} `
|
||||
-DDOWNLOAD_WINDOWSNUMERICS=TRUE `
|
||||
-DUSE_ANSI_COLOR=TRUE `
|
||||
-DCMAKE_CXX_FLAGS="-fansi-escape-codes" `
|
||||
-DENABLE_TEST_SANITIZERS=$sanitizers
|
||||
cmake --build . -j2 --target cppwinrt
|
||||
|
||||
- name: Upload cppwinrt.exe
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: llvm-mingw-build-${{ matrix.arch }}-bin
|
||||
path: build/cppwinrt.exe
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd build
|
||||
cmake --build . -j2 --target test-vanilla test_cpp20 test_cpp20_no_sourcelocation test_win7 test_old
|
||||
|
||||
- name: Upload test binaries
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: llvm-mingw-tests-${{ matrix.arch }}-bin
|
||||
path: build/test/*.exe
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build
|
||||
$env:UBSAN_OPTIONS = "print_stacktrace=1"
|
||||
ctest --verbose
|
||||
|
||||
test-msys2-gcc-cppwinrt:
|
||||
name: 'gcc/msys2: Build and test (${{ matrix.sys }}, ${{ matrix.config }})'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# 32-bit builds are running out of memory
|
||||
# - { sys: mingw32, arch: i686, config: Release }
|
||||
- { sys: mingw64, arch: x86_64, config: Debug }
|
||||
- { sys: mingw64, arch: x86_64, config: Release }
|
||||
- { sys: ucrt64, arch: x86_64, config: Release }
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
CMAKE_COLOR_DIAGNOSTICS: 1
|
||||
CLICOLOR_FORCE: 1
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{matrix.sys}}
|
||||
update: true
|
||||
pacboy: >-
|
||||
crt:p
|
||||
gcc:p
|
||||
binutils:p
|
||||
cmake:p
|
||||
ninja:p
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Build cppwinrt
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
if [[ "${{ matrix.arch }}" = "i686" ]]; then
|
||||
skip_large_pch_arg="-DSKIP_LARGE_PCH=TRUE"
|
||||
fi
|
||||
cmake ../ -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.config }} \
|
||||
-DDOWNLOAD_WINDOWSNUMERICS=TRUE \
|
||||
-DUSE_ANSI_COLOR=TRUE \
|
||||
$skip_large_pch_arg
|
||||
cmake --build . --target cppwinrt
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd build
|
||||
cmake --build . -j2 --target test-vanilla test_cpp20 test_cpp20_no_sourcelocation test_win7 test_old
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build
|
||||
ctest --verbose
|
||||
|
||||
build-linux-cross-cppwinrt:
|
||||
name: 'cross: Cross-build from Linux'
|
||||
strategy:
|
||||
|
@ -398,186 +284,6 @@ jobs:
|
|||
name: cross-build-${{ matrix.arch }}-bin
|
||||
path: install/bin/cppwinrt.exe
|
||||
|
||||
test-linux-cross-cppwinrt:
|
||||
name: 'cross: Test run on Windows'
|
||||
needs: build-linux-cross-cppwinrt
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [i686, x86_64]
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Fetch cppwinrt executable
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: cross-build-${{ matrix.arch }}-bin
|
||||
path: ./.test
|
||||
|
||||
- name: Run cppwinrt to build projection
|
||||
run: |
|
||||
.\.test\cppwinrt.exe -in local -out .\.test\out -verbose
|
||||
|
||||
- id: setup-llvm
|
||||
name: Set up llvm-mingw
|
||||
uses: ./.github/actions/setup-llvm-mingw
|
||||
with:
|
||||
host-arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Build cppwinrt tests
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../test -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug `
|
||||
-DCPPWINRT_PROJECTION_INCLUDE_DIR="../.test/out" `
|
||||
-DDOWNLOAD_WINDOWSNUMERICS=TRUE `
|
||||
-DUSE_ANSI_COLOR=TRUE
|
||||
cmake --build . -j2
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build
|
||||
ctest --verbose
|
||||
|
||||
build-linux-native-cppwinrt:
|
||||
name: 'linux: GCC native build + mingw-w64 cross-build tests'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# TODO: Enable gcc build once Arch Linux gets more recent mingw-w64 headers (ver. 11 perhaps?)
|
||||
# cross_toolchain: [gcc, llvm-mingw]
|
||||
cross_toolchain: [llvm-mingw]
|
||||
cross_arch: [i686, x86_64]
|
||||
# include:
|
||||
# - cross_toolchain: gcc
|
||||
# container:
|
||||
# image: archlinux:base-devel
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ matrix.container }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
env:
|
||||
CMAKE_COLOR_DIAGNOSTICS: 1
|
||||
CLICOLOR_FORCE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install build tools
|
||||
if: matrix.cross_toolchain == 'gcc'
|
||||
run: |
|
||||
pacman --noconfirm -Suuy
|
||||
pacman --needed --noconfirm -S cmake ninja git
|
||||
|
||||
- name: Build cppwinrt
|
||||
run: |
|
||||
cmake -S . -B build/native/ \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_INSTALL_PREFIX=$PWD/install/
|
||||
cmake --build build/native/ --target install -j2
|
||||
|
||||
- name: Test run (cppwinrt -?)
|
||||
run: |
|
||||
install/bin/cppwinrt -?
|
||||
|
||||
- name: Test run (build projection using Windows.winmd)
|
||||
run: |
|
||||
curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/bindgen/default/Windows.winmd
|
||||
install/bin/cppwinrt -in Windows.winmd -out /tmp/cppwinrt -verbose
|
||||
|
||||
- id: setup-llvm
|
||||
name: Set up llvm-mingw
|
||||
if: matrix.cross_toolchain == 'llvm-mingw'
|
||||
uses: ./.github/actions/setup-llvm-mingw
|
||||
|
||||
- name: Install GCC cross compiler
|
||||
if: matrix.cross_toolchain == 'gcc'
|
||||
run: |
|
||||
pacman --needed --noconfirm -S mingw-w64-gcc
|
||||
|
||||
- name: Cross-build tests using projection
|
||||
run: |
|
||||
cmake -S test -B build/cross-tests --toolchain "$PWD/cross-mingw-toolchain.cmake" \
|
||||
-DCMAKE_SYSTEM_PROCESSOR=${{ matrix.cross_arch }} \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_CXX_FLAGS="-static" \
|
||||
-DCPPWINRT_PROJECTION_INCLUDE_DIR=/tmp/cppwinrt \
|
||||
-DDOWNLOAD_WINDOWSNUMERICS=TRUE \
|
||||
-DUSE_ANSI_COLOR=TRUE
|
||||
cmake --build build/cross-tests -j2
|
||||
|
||||
- name: Upload built tests
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linux-native-cppwinrt-cross-build-tests-${{ matrix.cross_toolchain }}-${{ matrix.cross_arch }}-bin
|
||||
path: build/cross-tests/*.exe
|
||||
|
||||
test-linux-native-cppwinrt-cross-tests:
|
||||
name: 'linux: Run llvm-mingw cross-build tests'
|
||||
needs: build-linux-native-cppwinrt
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# TODO: Enable gcc build test when it is buildable
|
||||
# cross_toolchain: [gcc, llvm-mingw]
|
||||
cross_toolchain: [llvm-mingw]
|
||||
cross_arch: [i686, x86_64]
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Fetch test executables
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-native-cppwinrt-cross-build-tests-${{ matrix.cross_toolchain }}-${{ matrix.cross_arch }}-bin
|
||||
path: ./
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
$test_exes = ls *.exe -Name
|
||||
$has_failed_tests = 0
|
||||
foreach ($test_exe in $test_exes) {
|
||||
echo "::group::Run '$test_exe'"
|
||||
& .\$test_exe --use-colour yes
|
||||
echo "::endgroup::"
|
||||
if ($LastExitCode -ne 0) {
|
||||
echo "::error::Test '$test_exe' failed!"
|
||||
$has_failed_tests = 1
|
||||
}
|
||||
}
|
||||
if ($has_failed_tests -ne 0) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
build-macos-native-cppwinrt:
|
||||
name: 'macOS: GCC native build'
|
||||
runs-on: macos-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
env:
|
||||
CMAKE_COLOR_DIAGNOSTICS: 1
|
||||
CLICOLOR_FORCE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Build cppwinrt
|
||||
run: |
|
||||
cmake -S . -B build/native/ \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_INSTALL_PREFIX=$PWD/install/
|
||||
cmake --build build/native/ --target install -j2
|
||||
|
||||
- name: Test run (cppwinrt -?)
|
||||
run: |
|
||||
install/bin/cppwinrt -?
|
||||
|
||||
- name: Test run (build projection using Windows.winmd)
|
||||
run: |
|
||||
curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/bindgen/default/Windows.winmd
|
||||
install/bin/cppwinrt -in Windows.winmd -out build/out -verbose
|
||||
|
||||
build-msvc-natvis:
|
||||
name: 'Build natvis'
|
||||
strategy:
|
||||
|
|
|
@ -22,10 +22,6 @@ jobs:
|
|||
TestExe: 'test_cpp20_no_sourcelocation'
|
||||
TestProject: 'test_cpp20_no_sourcelocation'
|
||||
BuildPlatform: 'x86'
|
||||
test_win7.x86:
|
||||
TestExe: 'test_win7'
|
||||
TestProject: 'test_win7'
|
||||
BuildPlatform: 'x86'
|
||||
test_fast.x86:
|
||||
TestExe: 'test_fast'
|
||||
TestProject: 'test_fast'
|
||||
|
|
|
@ -32,7 +32,6 @@ call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,
|
|||
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test
|
||||
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20
|
||||
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20_no_sourcelocation
|
||||
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_win7
|
||||
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast
|
||||
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_slow
|
||||
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_module_lock_custom
|
||||
|
|
24
cppwinrt.sln
24
cppwinrt.sln
|
@ -104,13 +104,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_custom", "
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3C7EA5F8-6E8C-4376-B499-2CAF596384B0}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7\test_win7.vcxproj", "{2EF696B9-7F4A-410F-AE5C-5301565C0F08}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}
|
||||
{D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}
|
||||
{F1C915B3-2C64-4992-AFB7-7F035B1A7607} = {F1C915B3-2C64-4992-AFB7-7F035B1A7607}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp20\test_cpp20.vcxproj", "{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}
|
||||
|
@ -452,22 +445,6 @@ Global
|
|||
{08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.Build.0 = Release|x64
|
||||
{08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.ActiveCfg = Release|Win32
|
||||
{08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.Build.0 = Release|Win32
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x64.Build.0 = Debug|x64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM.Build.0 = Release|ARM
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.ActiveCfg = Release|x64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.Build.0 = Release|x64
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.Build.0 = Release|Win32
|
||||
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
|
@ -521,7 +498,6 @@ Global
|
|||
{303CC0FE-7D66-4F9F-B7A1-0AF7F9359074} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
|
||||
{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
|
||||
{08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
|
||||
{2EF696B9-7F4A-410F-AE5C-5301565C0F08} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
|
||||
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
|
||||
{D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
|
||||
EndGlobalSection
|
||||
|
|
|
@ -11,7 +11,6 @@ if "%target_configuration%"=="" set target_configuration=Debug
|
|||
call :run_test test
|
||||
call :run_test test_cpp20
|
||||
call :run_test test_cpp20_no_sourcelocation
|
||||
call :run_test test_win7
|
||||
call :run_test test_fast
|
||||
call :run_test test_slow
|
||||
call :run_test test_old
|
||||
|
|
|
@ -18,13 +18,6 @@ namespace winrt::impl
|
|||
|
||||
using library_handle = handle_type<library_traits>;
|
||||
|
||||
inline int32_t __stdcall fallback_RoGetActivationFactory(void*, guid const&, void** factory) noexcept
|
||||
{
|
||||
*factory = nullptr;
|
||||
return error_class_not_available;
|
||||
}
|
||||
|
||||
|
||||
template <bool isSameInterfaceAsIActivationFactory>
|
||||
WINRT_IMPL_NOINLINE hresult get_runtime_activation_factory_impl(param::hstring const& name, winrt::guid const& guid, void** result) noexcept
|
||||
{
|
||||
|
@ -33,9 +26,7 @@ namespace winrt::impl
|
|||
return winrt_activation_handler(*(void**)(&name), guid, result);
|
||||
}
|
||||
|
||||
static int32_t(__stdcall * handler)(void* classId, winrt::guid const& iid, void** factory) noexcept;
|
||||
impl::load_runtime_function(L"combase.dll", "RoGetActivationFactory", handler, fallback_RoGetActivationFactory);
|
||||
hresult hr = handler(*(void**)(&name), guid, result);
|
||||
hresult hr = WINRT_IMPL_RoGetActivationFactory(*(void**)(&name), guid, result);
|
||||
|
||||
if (hr == impl::error_not_initialized)
|
||||
{
|
||||
|
@ -48,7 +39,7 @@ namespace winrt::impl
|
|||
|
||||
void* cookie;
|
||||
usage(&cookie);
|
||||
hr = handler(*(void**)(&name), guid, result);
|
||||
hr = WINRT_IMPL_RoGetActivationFactory(*(void**)(&name), guid, result);
|
||||
}
|
||||
|
||||
if (hr == 0)
|
||||
|
|
|
@ -131,54 +131,9 @@ namespace winrt::impl
|
|||
return WINRT_IMPL_LoadLibraryExW(library, nullptr, 0x00001000 /* LOAD_LIBRARY_SEARCH_DEFAULT_DIRS */);
|
||||
}
|
||||
|
||||
template <typename F, typename L>
|
||||
void load_runtime_function(wchar_t const* library, char const* name, F& result, L fallback) noexcept
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result = reinterpret_cast<F>(WINRT_IMPL_GetProcAddress(load_library(library), name));
|
||||
|
||||
if (result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result = fallback;
|
||||
}
|
||||
|
||||
inline int32_t __stdcall fallback_RoGetAgileReference(uint32_t, winrt::guid const& iid, void* object, void** reference) noexcept
|
||||
{
|
||||
*reference = nullptr;
|
||||
static constexpr guid git_clsid{ 0x00000323, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } };
|
||||
|
||||
com_ptr<IGlobalInterfaceTable> git;
|
||||
hresult hr = WINRT_IMPL_CoCreateInstance(git_clsid, nullptr, 1 /*CLSCTX_INPROC_SERVER*/, guid_of<IGlobalInterfaceTable>(), git.put_void());
|
||||
|
||||
if (hr < 0)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
uint32_t cookie{};
|
||||
hr = git->RegisterInterfaceInGlobal(object, iid, &cookie);
|
||||
|
||||
if (hr < 0)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
*reference = new agile_ref_fallback(std::move(git), cookie);
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline hresult get_agile_reference(winrt::guid const& iid, void* object, void** reference) noexcept
|
||||
{
|
||||
static int32_t(__stdcall * handler)(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept;
|
||||
load_runtime_function(L"combase.dll", "RoGetAgileReference", handler, fallback_RoGetAgileReference);
|
||||
return handler(0, iid, object, reference);
|
||||
return WINRT_IMPL_RoGetAgileReference(0, iid, object, reference);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -409,17 +409,9 @@ namespace winrt::impl
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t __stdcall fallback_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept
|
||||
{
|
||||
return 0; // pretend timer has already triggered and a callback is on its way
|
||||
}
|
||||
|
||||
void fire_immediately() noexcept
|
||||
{
|
||||
static int32_t(__stdcall * handler)(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept;
|
||||
impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolTimerEx", handler, fallback_SetThreadpoolTimerEx);
|
||||
|
||||
if (handler(m_timer.get(), nullptr, 0, 0))
|
||||
if (WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), nullptr, 0, 0))
|
||||
{
|
||||
int64_t now = 0;
|
||||
WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0);
|
||||
|
@ -513,10 +505,6 @@ namespace winrt::impl
|
|||
}
|
||||
|
||||
private:
|
||||
static int32_t __stdcall fallback_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept
|
||||
{
|
||||
return 0; // pretend wait has already triggered and a callback is on its way
|
||||
}
|
||||
|
||||
void create_threadpool_wait()
|
||||
{
|
||||
|
@ -534,10 +522,7 @@ namespace winrt::impl
|
|||
|
||||
void fire_immediately() noexcept
|
||||
{
|
||||
static int32_t(__stdcall * handler)(winrt::impl::ptp_wait, void*, void*, void*) noexcept;
|
||||
impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolWaitEx", handler, fallback_SetThreadpoolWaitEx);
|
||||
|
||||
if (handler(m_wait.get(), nullptr, nullptr, nullptr))
|
||||
if (WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), nullptr, nullptr, nullptr))
|
||||
{
|
||||
int64_t now = 0;
|
||||
WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now);
|
||||
|
|
|
@ -175,11 +175,6 @@ namespace winrt::impl
|
|||
hstring const m_message;
|
||||
atomic_ref_count m_references{ 1 };
|
||||
};
|
||||
|
||||
[[noreturn]] inline void __stdcall fallback_RoFailFastWithErrorContext(int32_t) noexcept
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
WINRT_EXPORT namespace winrt
|
||||
|
@ -301,18 +296,9 @@ WINRT_EXPORT namespace winrt
|
|||
|
||||
private:
|
||||
|
||||
static int32_t __stdcall fallback_RoOriginateLanguageException(int32_t error, void* message, void*) noexcept
|
||||
{
|
||||
com_ptr<impl::IErrorInfo> info(new (std::nothrow) impl::error_info_fallback(error, message), take_ownership_from_abi);
|
||||
WINRT_VERIFY_(0, WINRT_IMPL_SetErrorInfo(0, info.get()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void originate(hresult const code, void* message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept
|
||||
{
|
||||
static int32_t(__stdcall* handler)(int32_t error, void* message, void* exception) noexcept;
|
||||
impl::load_runtime_function(L"combase.dll", "RoOriginateLanguageException", handler, fallback_RoOriginateLanguageException);
|
||||
WINRT_VERIFY(handler(code, message, nullptr));
|
||||
WINRT_VERIFY(WINRT_IMPL_RoOriginateLanguageException(code, message, nullptr));
|
||||
|
||||
// This is an extension point that can be filled in by other libraries (such as WIL) to get call outs when errors are
|
||||
// originated. This is intended for logging purposes. When possible include the std::source_information so that accurate
|
||||
|
@ -642,9 +628,7 @@ WINRT_EXPORT namespace winrt
|
|||
|
||||
[[noreturn]] inline void terminate() noexcept
|
||||
{
|
||||
static void(__stdcall * handler)(int32_t) noexcept;
|
||||
impl::load_runtime_function(L"combase.dll", "RoFailFastWithErrorContext", handler, impl::fallback_RoFailFastWithErrorContext);
|
||||
handler(to_hresult());
|
||||
WINRT_IMPL_RoFailFastWithErrorContext(to_hresult());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -337,18 +337,10 @@ namespace winrt::impl
|
|||
return { new(raw) event_array<T>(capacity), take_ownership_from_abi };
|
||||
}
|
||||
|
||||
inline int32_t __stdcall fallback_RoTransformError(int32_t, int32_t, void*) noexcept
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
WINRT_IMPL_NOINLINE inline bool report_failed_invoke()
|
||||
{
|
||||
int32_t const code = to_hresult();
|
||||
|
||||
static int32_t(__stdcall * handler)(int32_t, int32_t, void*) noexcept;
|
||||
impl::load_runtime_function(L"combase.dll", "RoTransformError", handler, fallback_RoTransformError);
|
||||
handler(code, 0, nullptr);
|
||||
WINRT_IMPL_RoTransformError(code, 0, nullptr);
|
||||
|
||||
if (code == static_cast<int32_t>(0x80010108) || // RPC_E_DISCONNECTED
|
||||
code == static_cast<int32_t>(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
|
||||
|
|
|
@ -24,6 +24,14 @@ __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId
|
|||
|
||||
extern "C"
|
||||
{
|
||||
int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12);
|
||||
int32_t __stdcall WINRT_IMPL_RoGetAgileReference(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16);
|
||||
int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16);
|
||||
int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16);
|
||||
int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12);
|
||||
void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4);
|
||||
int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12);
|
||||
|
||||
void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12);
|
||||
int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4);
|
||||
void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8);
|
||||
|
|
|
@ -107,7 +107,6 @@ set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.")
|
|||
add_subdirectory(test)
|
||||
add_subdirectory(test_cpp20)
|
||||
add_subdirectory(test_cpp20_no_sourcelocation)
|
||||
add_subdirectory(test_win7)
|
||||
|
||||
if(HAS_WINDOWSNUMERICS)
|
||||
add_subdirectory(old_tests)
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
file(GLOB TEST_SRCS
|
||||
LIST_DIRECTORIES false
|
||||
CONFIGURE_DEPENDS
|
||||
*.cpp
|
||||
)
|
||||
list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp")
|
||||
|
||||
|
||||
# We can't build test_component[*] for mingw-w64 because it doesn't have an
|
||||
# alternative to midl that can produce winmd files. Also, even if we do manage
|
||||
# to reuse the MSVC-compiled binaries, mingw-w64 is still missing
|
||||
# windowsnumerics.impl.h which is needed to provide the types
|
||||
# winrt::Windows::Foundation::Numerics::float2 and friends that the components
|
||||
# use.
|
||||
list(APPEND BROKEN_TESTS
|
||||
agility
|
||||
delegates
|
||||
enum
|
||||
in_params
|
||||
no_make_detection
|
||||
noexcept
|
||||
out_params
|
||||
parent_includes
|
||||
return_params
|
||||
structs
|
||||
uniform_in_params
|
||||
velocity
|
||||
)
|
||||
|
||||
list(APPEND BROKEN_TESTS
|
||||
# depends on pplawait.h
|
||||
when
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# FIXME: GCC does not compile co_await on thread_pool because it wants
|
||||
# a copy constructor. Disabling this test for now.
|
||||
# This might be related to upstream bug:
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103963
|
||||
list(APPEND BROKEN_TESTS
|
||||
thread_pool
|
||||
)
|
||||
endif()
|
||||
|
||||
# Exclude broken tests
|
||||
foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS)
|
||||
list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp")
|
||||
endforeach()
|
||||
|
||||
add_executable(test_win7 main.cpp ${TEST_SRCS})
|
||||
|
||||
target_precompile_headers(test_win7 PRIVATE pch.h)
|
||||
set_source_files_properties(
|
||||
main.cpp
|
||||
coro_foundation.cpp
|
||||
coro_threadpool.cpp
|
||||
generic_type_names.cpp
|
||||
inspectable_interop.cpp
|
||||
module_lock_dll.cpp
|
||||
PROPERTIES SKIP_PRECOMPILE_HEADERS true
|
||||
)
|
||||
|
||||
add_dependencies(test_win7 build-cppwinrt-projection)
|
||||
|
||||
add_test(
|
||||
NAME test_win7
|
||||
COMMAND "$<TARGET_FILE:test_win7>" ${TEST_COLOR_ARG}
|
||||
)
|
|
@ -1,382 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
|
||||
//
|
||||
// Now that all of the generics are generated (rather than hand-written), it's far less likely
|
||||
// that something like GetMany is incorrect. And the "FillArray" pattern used by GetMany is
|
||||
// tested elsewhere in the out_params and return_params tests. However since C++/WinRT provides
|
||||
// an implementation of GetMany over and above the projection, these tests validate the this
|
||||
// implementation is correct. Other tests exist for collections under 'old_tests' but new
|
||||
// optimizations are coming for GetMany and I want to make sure that GetMany is completely
|
||||
// covered.
|
||||
//
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename T>
|
||||
IIterator<T> single_threaded_generator(std::vector<T>&& values = {})
|
||||
{
|
||||
// This iterator may only be advanced once, ensuring the GetMany complexity optimization
|
||||
// is actually enforced with this test.
|
||||
|
||||
struct generator_container
|
||||
{
|
||||
explicit generator_container(IIterator<T> const& first) : m_current(first)
|
||||
{
|
||||
if (!m_current.HasCurrent())
|
||||
{
|
||||
m_current = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IIterator<T> begin() const { return m_current; }
|
||||
IIterator<T> end() const { return nullptr; }
|
||||
|
||||
private:
|
||||
IIterator<T> m_current;
|
||||
};
|
||||
|
||||
struct generator : implements<generator, IIterable<T>>, iterable_base<generator, T>
|
||||
{
|
||||
explicit generator(IIterator<T> const& first) : m_container(first)
|
||||
{
|
||||
}
|
||||
|
||||
auto& get_container() noexcept
|
||||
{
|
||||
return m_container;
|
||||
}
|
||||
|
||||
auto& get_container() const noexcept
|
||||
{
|
||||
return m_container;
|
||||
}
|
||||
|
||||
private:
|
||||
generator_container m_container;
|
||||
};
|
||||
|
||||
auto v = single_threaded_vector<T>(std::move(values));
|
||||
return make<generator>(v.First()).First();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("GetMany")
|
||||
{
|
||||
// All
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 3> buffer{ 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == v.GetMany(0, buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 3> buffer{ 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == v.First().GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
}
|
||||
|
||||
// None
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 3> buffer{ 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(0 == v.GetMany(3, buffer));
|
||||
REQUIRE(buffer[0] == 0xCC);
|
||||
REQUIRE(buffer[1] == 0xCC);
|
||||
REQUIRE(buffer[2] == 0xCC);
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3,4 });
|
||||
auto pos = v.First();
|
||||
std::array<int, 3> buffer{ 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == pos.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
buffer = { 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(1 == pos.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 4);
|
||||
REQUIRE(buffer[1] == 0xCC);
|
||||
REQUIRE(buffer[2] == 0xCC);
|
||||
buffer = { 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(0 == pos.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 0xCC);
|
||||
REQUIRE(buffer[1] == 0xCC);
|
||||
REQUIRE(buffer[2] == 0xCC);
|
||||
}
|
||||
|
||||
// Less
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 2> buffer{ 0xCC, 0xCC };
|
||||
REQUIRE(2 == v.GetMany(0, buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 2> buffer{ 0xCC, 0xCC };
|
||||
REQUIRE(2 == v.First().GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
}
|
||||
|
||||
// More
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 4> buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == v.GetMany(0, buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
REQUIRE(buffer[3] == 0xCC);
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 4> buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == v.First().GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
REQUIRE(buffer[3] == 0xCC);
|
||||
}
|
||||
|
||||
// Offset
|
||||
{
|
||||
auto v = single_threaded_vector<int>({ 1,2,3 });
|
||||
std::array<int, 4> buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(2 == v.GetMany(1, buffer));
|
||||
REQUIRE(buffer[0] == 2);
|
||||
REQUIRE(buffer[1] == 3);
|
||||
REQUIRE(buffer[2] == 0xCC);
|
||||
REQUIRE(buffer[3] == 0xCC);
|
||||
}
|
||||
|
||||
// The same tests but with a non-trivially destructible type...
|
||||
|
||||
// All
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 3> buffer{ L"old", L"old", L"old" };
|
||||
REQUIRE(3 == v.GetMany(0, buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 3> buffer{ L"old", L"old", L"old" };
|
||||
REQUIRE(3 == v.First().GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
}
|
||||
|
||||
// None
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 3> buffer{ L"old", L"old", L"old" };
|
||||
REQUIRE(0 == v.GetMany(3, buffer));
|
||||
REQUIRE(buffer[0] == L"");
|
||||
REQUIRE(buffer[1] == L"");
|
||||
REQUIRE(buffer[2] == L"");
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3",L"4" });
|
||||
auto pos = v.First();
|
||||
std::array<hstring, 3> buffer{ L"old", L"old", L"old" };
|
||||
REQUIRE(3 == pos.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
buffer = { L"old", L"old", L"old" };
|
||||
REQUIRE(1 == pos.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"4");
|
||||
REQUIRE(buffer[1] == L"");
|
||||
REQUIRE(buffer[2] == L"");
|
||||
buffer = { L"old", L"old", L"old" };
|
||||
REQUIRE(0 == pos.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"");
|
||||
REQUIRE(buffer[1] == L"");
|
||||
REQUIRE(buffer[2] == L"");
|
||||
}
|
||||
|
||||
// Less
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 2> buffer{ L"old", L"old" };
|
||||
REQUIRE(2 == v.GetMany(0, buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 2> buffer{ L"old", L"old" };
|
||||
REQUIRE(2 == v.First().GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
}
|
||||
|
||||
// More
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 4> buffer{ L"old", L"old", L"old", L"old" };
|
||||
REQUIRE(3 == v.GetMany(0, buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
REQUIRE(buffer[3] == L"");
|
||||
}
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 4> buffer{ L"old", L"old", L"old", L"old" };
|
||||
REQUIRE(3 == v.First().GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
REQUIRE(buffer[3] == L"");
|
||||
}
|
||||
|
||||
// Offset
|
||||
{
|
||||
auto v = single_threaded_vector<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 4> buffer{ L"old", L"old", L"old", L"old" };
|
||||
REQUIRE(2 == v.GetMany(1, buffer));
|
||||
REQUIRE(buffer[0] == L"2");
|
||||
REQUIRE(buffer[1] == L"3");
|
||||
REQUIRE(buffer[2] == L"");
|
||||
REQUIRE(buffer[3] == L"");
|
||||
}
|
||||
|
||||
// FIXME: Fail to compile with Clang due to recursive template instantiation using single_threaded_generator.
|
||||
#if !defined(__clang__)
|
||||
|
||||
// Similar tests but with a list to ensure optimal code gen for containers that don't offer random access.
|
||||
|
||||
// All
|
||||
{
|
||||
IIterator<int> v = single_threaded_generator<int>({ 1,2,3 });
|
||||
std::array<int, 3> buffer{ 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
}
|
||||
|
||||
// None
|
||||
{
|
||||
IIterator<int> v = single_threaded_generator<int>({ 1,2,3,4,5 });
|
||||
std::array<int, 3> buffer{ 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
buffer = { 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(2 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 4);
|
||||
REQUIRE(buffer[1] == 5);
|
||||
REQUIRE(buffer[2] == 0xCC);
|
||||
buffer = { 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(0 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 0xCC);
|
||||
REQUIRE(buffer[1] == 0xCC);
|
||||
REQUIRE(buffer[2] == 0xCC);
|
||||
}
|
||||
|
||||
// Less
|
||||
{
|
||||
IIterator<int> v = single_threaded_generator<int>({ 1,2,3 });
|
||||
std::array<int, 2> buffer{ 0xCC, 0xCC };
|
||||
REQUIRE(2 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
}
|
||||
|
||||
// More
|
||||
{
|
||||
IIterator<int> v = single_threaded_generator<int>({ 1,2,3 });
|
||||
std::array<int, 4> buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE(3 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == 1);
|
||||
REQUIRE(buffer[1] == 2);
|
||||
REQUIRE(buffer[2] == 3);
|
||||
REQUIRE(buffer[3] == 0xCC);
|
||||
}
|
||||
|
||||
// The same tests but with a non-trivially destructible type...
|
||||
|
||||
// All
|
||||
{
|
||||
IIterator<hstring> v = single_threaded_generator<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 3> buffer{ L"old", L"old", L"old" };
|
||||
REQUIRE(3 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
}
|
||||
|
||||
// None
|
||||
{
|
||||
IIterator<hstring> v = single_threaded_generator<hstring>({ L"1",L"2",L"3",L"4" });
|
||||
std::array<hstring, 3> buffer{ L"old", L"old", L"old" };
|
||||
REQUIRE(3 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
buffer = { L"old", L"old", L"old" };
|
||||
REQUIRE(1 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"4");
|
||||
REQUIRE(buffer[1] == L"");
|
||||
REQUIRE(buffer[2] == L"");
|
||||
buffer = { L"old", L"old", L"old" };
|
||||
REQUIRE(0 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"");
|
||||
REQUIRE(buffer[1] == L"");
|
||||
REQUIRE(buffer[2] == L"");
|
||||
}
|
||||
|
||||
// Less
|
||||
{
|
||||
IIterator<hstring> v = single_threaded_generator<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 2> buffer{ L"old", L"old" };
|
||||
REQUIRE(2 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
}
|
||||
|
||||
// More
|
||||
{
|
||||
IIterator<hstring> v = single_threaded_generator<hstring>({ L"1",L"2",L"3" });
|
||||
std::array<hstring, 4> buffer{ L"old", L"old", L"old", L"old" };
|
||||
REQUIRE(3 == v.GetMany(buffer));
|
||||
REQUIRE(buffer[0] == L"1");
|
||||
REQUIRE(buffer[1] == L"2");
|
||||
REQUIRE(buffer[2] == L"3");
|
||||
REQUIRE(buffer[3] == L"");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pair
|
||||
{
|
||||
auto m = single_threaded_map<int, hstring>();
|
||||
m.Insert(1, L"1");
|
||||
m.Insert(2, L"2");
|
||||
m.Insert(3, L"3");
|
||||
m.Insert(4, L"4");
|
||||
std::array<IKeyValuePair<int, hstring>, 3> buffer;
|
||||
REQUIRE(3 == m.First().GetMany(buffer));
|
||||
REQUIRE(buffer[0].Key() == 1);
|
||||
REQUIRE(buffer[1].Key() == 2);
|
||||
REQUIRE(buffer[2].Key() == 3);
|
||||
REQUIRE(buffer[0].Value() == L"1");
|
||||
REQUIRE(buffer[1].Value() == L"2");
|
||||
REQUIRE(buffer[2].Value() == L"3");
|
||||
}
|
||||
}
|
|
@ -1,293 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// This implemenetation uses the simplest abi_enter and abi_exit methods
|
||||
//
|
||||
struct Simple : implements<Simple, IClosable, IStringable>
|
||||
{
|
||||
void Close()
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
void abi_enter()
|
||||
{
|
||||
++m_enter;
|
||||
}
|
||||
|
||||
void abi_exit()
|
||||
{
|
||||
++m_exit;
|
||||
}
|
||||
|
||||
int m_enter{};
|
||||
int m_exit{};
|
||||
};
|
||||
|
||||
//
|
||||
// This implemenetation uses the abi_enter but omits the abi_exit method
|
||||
//
|
||||
struct OnlyEnter : implements<OnlyEnter, IClosable, IStringable>
|
||||
{
|
||||
void Close()
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
void abi_enter()
|
||||
{
|
||||
++m_enter;
|
||||
}
|
||||
|
||||
int m_enter{};
|
||||
};
|
||||
|
||||
//
|
||||
// This implemenetation throws from the abi_enter method
|
||||
//
|
||||
struct Throwing : implements<Throwing, IClosable, IStringable>
|
||||
{
|
||||
void Close()
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
void abi_enter()
|
||||
{
|
||||
throw hresult_wrong_thread();
|
||||
}
|
||||
|
||||
void abi_exit()
|
||||
{
|
||||
++m_exit;
|
||||
}
|
||||
|
||||
int m_exit{};
|
||||
};
|
||||
|
||||
//
|
||||
// This implemenetation provides a nested abi_guard
|
||||
//
|
||||
struct NestedGuard : implements<NestedGuard, IClosable, IStringable>
|
||||
{
|
||||
void Close()
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
int m_enter{};
|
||||
int m_exit{};
|
||||
|
||||
struct abi_guard
|
||||
{
|
||||
abi_guard(NestedGuard& that) :
|
||||
m_that(that)
|
||||
{
|
||||
++m_that.m_enter;
|
||||
}
|
||||
|
||||
~abi_guard()
|
||||
{
|
||||
++m_that.m_exit;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
NestedGuard& m_that;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct CountGuard
|
||||
{
|
||||
CountGuard(T& that) :
|
||||
m_that(that)
|
||||
{
|
||||
++m_that.m_enter;
|
||||
}
|
||||
|
||||
~CountGuard()
|
||||
{
|
||||
++m_that.m_exit;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T& m_that;
|
||||
};
|
||||
|
||||
//
|
||||
// This implemenetation use an abi_guard type alias
|
||||
//
|
||||
struct GuardAlias : implements<GuardAlias, IClosable, IStringable>
|
||||
{
|
||||
void Close()
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
int m_enter{};
|
||||
int m_exit{};
|
||||
|
||||
using abi_guard = CountGuard<GuardAlias>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ThrowGuard
|
||||
{
|
||||
ThrowGuard(T&)
|
||||
{
|
||||
throw hresult_wrong_thread();
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// This implemenetation use an abi_guard type alias that thows
|
||||
//
|
||||
struct ThrowAlias : implements<ThrowAlias, IClosable, IStringable>
|
||||
{
|
||||
void Close()
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
using abi_guard = ThrowGuard<ThrowAlias>;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("abi_guard")
|
||||
{
|
||||
{
|
||||
com_ptr<Simple> impl = make_self<Simple>();
|
||||
|
||||
impl->Close();
|
||||
impl->ToString();
|
||||
REQUIRE(impl->m_enter == 0);
|
||||
REQUIRE(impl->m_exit == 0);
|
||||
|
||||
IClosable closable = impl.as<IClosable>();
|
||||
closable.Close();
|
||||
REQUIRE(impl->m_enter == 1);
|
||||
REQUIRE(impl->m_exit == 1);
|
||||
|
||||
IStringable stringable = impl.as<IStringable>();
|
||||
stringable.ToString();
|
||||
REQUIRE(impl->m_enter == 2);
|
||||
REQUIRE(impl->m_exit == 2);
|
||||
}
|
||||
{
|
||||
com_ptr<OnlyEnter> impl = make_self<OnlyEnter>();
|
||||
|
||||
impl->Close();
|
||||
impl->ToString();
|
||||
|
||||
REQUIRE(impl->m_enter == 0);
|
||||
|
||||
IClosable closable = impl.as<IClosable>();
|
||||
closable.Close();
|
||||
|
||||
REQUIRE(impl->m_enter == 1);
|
||||
|
||||
IStringable stringable = impl.as<IStringable>();
|
||||
stringable.ToString();
|
||||
|
||||
REQUIRE(impl->m_enter == 2);
|
||||
}
|
||||
{
|
||||
com_ptr<Throwing> impl = make_self<Throwing>();
|
||||
|
||||
impl->Close();
|
||||
impl->ToString();
|
||||
|
||||
IClosable closable = impl.as<IClosable>();
|
||||
REQUIRE_THROWS_AS(closable.Close(), hresult_wrong_thread);
|
||||
|
||||
IStringable stringable = impl.as<IStringable>();
|
||||
REQUIRE_THROWS_AS(stringable.ToString(), hresult_wrong_thread);
|
||||
|
||||
REQUIRE(impl->m_exit == 0);
|
||||
}
|
||||
{
|
||||
com_ptr<NestedGuard> impl = make_self<NestedGuard>();
|
||||
|
||||
impl->Close();
|
||||
impl->ToString();
|
||||
|
||||
REQUIRE(impl->m_enter == 0);
|
||||
REQUIRE(impl->m_exit == 0);
|
||||
|
||||
IClosable closable = impl.as<IClosable>();
|
||||
closable.Close();
|
||||
|
||||
REQUIRE(impl->m_enter == 1);
|
||||
REQUIRE(impl->m_exit == 1);
|
||||
|
||||
IStringable stringable = impl.as<IStringable>();
|
||||
stringable.ToString();
|
||||
|
||||
REQUIRE(impl->m_enter == 2);
|
||||
REQUIRE(impl->m_exit == 2);
|
||||
}
|
||||
{
|
||||
com_ptr<GuardAlias> impl = make_self<GuardAlias>();
|
||||
|
||||
impl->Close();
|
||||
impl->ToString();
|
||||
|
||||
REQUIRE(impl->m_enter == 0);
|
||||
REQUIRE(impl->m_exit == 0);
|
||||
|
||||
IClosable closable = impl.as<IClosable>();
|
||||
closable.Close();
|
||||
|
||||
REQUIRE(impl->m_enter == 1);
|
||||
REQUIRE(impl->m_exit == 1);
|
||||
|
||||
IStringable stringable = impl.as<IStringable>();
|
||||
stringable.ToString();
|
||||
|
||||
REQUIRE(impl->m_enter == 2);
|
||||
REQUIRE(impl->m_exit == 2);
|
||||
}
|
||||
{
|
||||
com_ptr<ThrowAlias> impl = make_self<ThrowAlias>();
|
||||
|
||||
impl->Close();
|
||||
impl->ToString();
|
||||
|
||||
IClosable closable = impl.as<IClosable>();
|
||||
REQUIRE_THROWS_AS(closable.Close(), hresult_wrong_thread);
|
||||
|
||||
IStringable stringable = impl.as<IStringable>();
|
||||
REQUIRE_THROWS_AS(stringable.ToString(), hresult_wrong_thread);
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Object : implements<Object, IStringable>
|
||||
{
|
||||
hstring ToString()
|
||||
{
|
||||
return L"Object";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("agile_ref")
|
||||
{
|
||||
agile_ref<IStringable> ref = make<Object>();
|
||||
|
||||
//
|
||||
// Here we're creating an agile_ref explicitly and using a traditional lambda variable capture
|
||||
// to pass it to the delegate.
|
||||
//
|
||||
|
||||
delegate<> a = [ref]
|
||||
{
|
||||
IStringable object = ref.get();
|
||||
REQUIRE(object.ToString() == L"Object");
|
||||
};
|
||||
|
||||
a();
|
||||
|
||||
//
|
||||
// Here's we're using the make_agile helper with generalized lambda capture to produce a
|
||||
// variable local to the lambda.
|
||||
//
|
||||
|
||||
delegate<> b = [ref = make_agile(make<Object>())]
|
||||
{
|
||||
IStringable object = ref.get();
|
||||
REQUIRE(object.ToString() == L"Object");
|
||||
};
|
||||
|
||||
b();
|
||||
|
||||
//
|
||||
// And it's ok to resolve a nullptr agile_ref.
|
||||
//
|
||||
|
||||
agile_ref<IStringable> empty;
|
||||
IStringable object = empty.get();
|
||||
REQUIRE(object == nullptr);
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.Delegates.h"
|
||||
|
||||
//
|
||||
// These tests confirm the COM identity and other behaviours for agile implementations.
|
||||
//
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct TestAgile : implements<TestAgile, IClosable>
|
||||
{
|
||||
bool& m_destroyed;
|
||||
TestAgile(bool& destroyed) : m_destroyed(destroyed) { m_destroyed = false; }
|
||||
~TestAgile() { m_destroyed = true; }
|
||||
|
||||
void Close() {}
|
||||
};
|
||||
|
||||
struct TestNonAgile : implements<TestNonAgile, non_agile, IClosable>
|
||||
{
|
||||
void Close() {}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("agility")
|
||||
{
|
||||
using Windows::Foundation::IUnknown;
|
||||
using Windows::Foundation::IInspectable;
|
||||
|
||||
// Test agility
|
||||
{
|
||||
bool destroyed = false;
|
||||
|
||||
{
|
||||
IInspectable object = make<TestAgile>(destroyed);
|
||||
|
||||
// Confirm agility
|
||||
object.as<IAgileObject>();
|
||||
|
||||
// Confirm legacy agility
|
||||
com_ptr<IMarshal> marshal = object.as<IMarshal>();
|
||||
|
||||
// Confirm tear-off identity
|
||||
IUnknown object_identity = object.as<IUnknown>();
|
||||
IUnknown marshal_identity = marshal.as<IUnknown>();
|
||||
|
||||
REQUIRE(object_identity == marshal_identity);
|
||||
REQUIRE(!destroyed);
|
||||
}
|
||||
|
||||
// Confirm tear-off does not leak reference
|
||||
REQUIRE(destroyed);
|
||||
}
|
||||
|
||||
// Test non-agility
|
||||
{
|
||||
IInspectable object = make<TestNonAgile>();
|
||||
|
||||
// Does not implement IAgileObject
|
||||
REQUIRE_THROWS_AS(object.as<IAgileObject>(), hresult_no_interface);
|
||||
|
||||
// Does not implement IMarshal
|
||||
REQUIRE_THROWS_AS(object.as<IMarshal>(), hresult_no_interface);
|
||||
}
|
||||
|
||||
// Test IMarshal tearoff lifetime
|
||||
{
|
||||
bool destroyed = false;
|
||||
|
||||
IInspectable object = make<TestAgile>(destroyed);
|
||||
com_ptr<IMarshal> marshal = object.as<IMarshal>();
|
||||
object = nullptr;
|
||||
REQUIRE(!destroyed);
|
||||
|
||||
// Confirm agility (back to object)
|
||||
marshal.as<IAgileObject>();
|
||||
|
||||
// QI on tearoff itself
|
||||
com_ptr<IMarshal> marshal2 = marshal.as<IMarshal>();
|
||||
REQUIRE(marshal == marshal2);
|
||||
marshal2 = nullptr;
|
||||
|
||||
// Confirm tear-off does not leak reference
|
||||
REQUIRE(!destroyed);
|
||||
marshal = nullptr;
|
||||
REQUIRE(destroyed);
|
||||
}
|
||||
|
||||
// Test agile delegate
|
||||
{
|
||||
IUnknown object = test_component::Delegates::AgileDelegate([] {});
|
||||
com_ptr<IMarshal> marshal = object.as<IMarshal>();
|
||||
object = nullptr;
|
||||
|
||||
// Confirm agility (back to object)
|
||||
marshal.as<IAgileObject>();
|
||||
|
||||
// QI on tearoff itself
|
||||
com_ptr<IMarshal> marshal2 = marshal.as<IMarshal>();
|
||||
REQUIRE(marshal == marshal2);
|
||||
}
|
||||
|
||||
// Test agile weak reference
|
||||
{
|
||||
bool destroyed = false;
|
||||
IClosable object = make<TestAgile>(destroyed);
|
||||
com_ptr<winrt::impl::IWeakReferenceSource> source = object.as<winrt::impl::IWeakReferenceSource>();
|
||||
|
||||
// Clear object but source keeps object alive
|
||||
object = nullptr;
|
||||
source.as<IMarshal>();
|
||||
|
||||
com_ptr<winrt::impl::IWeakReference> ref;
|
||||
check_hresult(source->GetWeakReference(ref.put()));
|
||||
|
||||
// Drop the source object
|
||||
REQUIRE(S_OK == ref->Resolve(guid_of<IClosable>(), put_abi(object)));
|
||||
REQUIRE(object != nullptr);
|
||||
source = nullptr;
|
||||
REQUIRE(!destroyed);
|
||||
object = nullptr;
|
||||
REQUIRE(destroyed);
|
||||
REQUIRE(S_OK == ref->Resolve(guid_of<IClosable>(), put_abi(object)));
|
||||
REQUIRE(object == nullptr);
|
||||
|
||||
// Marshaling support on weak ref
|
||||
com_ptr<IMarshal> marshal = ref.as<IMarshal>();
|
||||
ref = nullptr;
|
||||
|
||||
// Confirm agility (back to object):
|
||||
marshal.as<IAgileObject>();
|
||||
|
||||
// QI on tearoff itself
|
||||
com_ptr<IMarshal> marshal2 = marshal.as<IMarshal>();
|
||||
REQUIRE(marshal == marshal2);
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef __cpp_lib_coroutine
|
||||
using std::suspend_never;
|
||||
#else
|
||||
using std::experimental::suspend_never;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Checks that the coroutine is automatically canceled when reaching a suspension point.
|
||||
//
|
||||
|
||||
IAsyncAction Action(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
handle start{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
handle completed{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
auto async = make(start.get());
|
||||
REQUIRE(async.Status() == AsyncStatus::Started);
|
||||
|
||||
async.Completed([&](auto&& sender, AsyncStatus status)
|
||||
{
|
||||
REQUIRE(async == sender);
|
||||
REQUIRE(status == AsyncStatus::Canceled);
|
||||
SetEvent(completed.get());
|
||||
});
|
||||
|
||||
async.Cancel();
|
||||
SetEvent(start.get());
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0);
|
||||
|
||||
REQUIRE(async.Status() == AsyncStatus::Canceled);
|
||||
REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED));
|
||||
REQUIRE_THROWS_AS(async.GetResults(), hresult_canceled);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__) && defined(_MSC_VER)
|
||||
// FIXME: Test is known to segfault when built with Clang.
|
||||
TEST_CASE("async_auto_cancel", "[.clang-crash]")
|
||||
#else
|
||||
TEST_CASE("async_auto_cancel")
|
||||
#endif
|
||||
{
|
||||
Check(Action);
|
||||
Check(ActionWithProgress);
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef __cpp_lib_coroutine
|
||||
using std::suspend_never;
|
||||
#else
|
||||
using std::experimental::suspend_never;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Checks that the cancellation callback is invoked.
|
||||
//
|
||||
|
||||
IAsyncAction Action(HANDLE event, bool& canceled)
|
||||
{
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
cancel.callback([&]
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
});
|
||||
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress(HANDLE event, bool& canceled)
|
||||
{
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
cancel.callback([&]
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
});
|
||||
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation(HANDLE event, bool& canceled)
|
||||
{
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
cancel.callback([&]
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
});
|
||||
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress(HANDLE event, bool& canceled)
|
||||
{
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
cancel.callback([&]
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
});
|
||||
|
||||
co_await resume_on_signal(event);
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
handle event{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
bool canceled = false;
|
||||
auto async = make(event.get(), canceled);
|
||||
async.Cancel();
|
||||
REQUIRE(canceled);
|
||||
SetEvent(event.get());
|
||||
REQUIRE_THROWS_AS(async.GetResults(), hresult_canceled);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__) && defined(_MSC_VER)
|
||||
// FIXME: Test is known to segfault when built with Clang.
|
||||
TEST_CASE("async_cancel_callback", "[.clang-crash]")
|
||||
#else
|
||||
TEST_CASE("async_cancel_callback")
|
||||
#endif
|
||||
{
|
||||
Check(Action);
|
||||
Check(ActionWithProgress);
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef __cpp_lib_coroutine
|
||||
using std::suspend_never;
|
||||
#else
|
||||
using std::experimental::suspend_never;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Checks that manual cancellation checks work.
|
||||
//
|
||||
|
||||
IAsyncAction Action(HANDLE event, bool& canceled)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
if (cancel())
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
}
|
||||
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress(HANDLE event, bool& canceled)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
if (cancel())
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
}
|
||||
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation(HANDLE event, bool& canceled)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
if (cancel())
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
}
|
||||
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress(HANDLE event, bool& canceled)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
auto cancel = co_await get_cancellation_token();
|
||||
|
||||
if (cancel())
|
||||
{
|
||||
REQUIRE(!canceled);
|
||||
canceled = true;
|
||||
}
|
||||
|
||||
co_await suspend_never();
|
||||
REQUIRE(false);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
handle start{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
handle completed{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
bool canceled = false;
|
||||
auto async = make(start.get(), canceled);
|
||||
REQUIRE(async.Status() == AsyncStatus::Started);
|
||||
|
||||
async.Completed([&](auto&& sender, AsyncStatus status)
|
||||
{
|
||||
REQUIRE(async == sender);
|
||||
REQUIRE(status == AsyncStatus::Canceled);
|
||||
REQUIRE(canceled);
|
||||
SetEvent(completed.get());
|
||||
});
|
||||
|
||||
async.Cancel();
|
||||
SetEvent(start.get());
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0);
|
||||
|
||||
REQUIRE(async.Status() == AsyncStatus::Canceled);
|
||||
REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED));
|
||||
REQUIRE_THROWS_AS(async.GetResults(), hresult_canceled);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__) && defined(_MSC_VER)
|
||||
// FIXME: Test is known to segfault when built with Clang.
|
||||
TEST_CASE("async_check_cancel", "[.clang-crash]")
|
||||
#else
|
||||
TEST_CASE("async_check_cancel")
|
||||
#endif
|
||||
{
|
||||
Check(Action);
|
||||
Check(ActionWithProgress);
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// Checks that coroutine locals are destroyed prior to notifying waiters.
|
||||
//
|
||||
|
||||
struct Local
|
||||
{
|
||||
bool& destroyed;
|
||||
|
||||
~Local()
|
||||
{
|
||||
REQUIRE(!destroyed);
|
||||
destroyed = true;
|
||||
}
|
||||
};
|
||||
|
||||
IAsyncAction Action(HANDLE event, bool& destroyed)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
Local local{ destroyed };
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress(HANDLE event, bool& destroyed)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
Local local{ destroyed };
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation(HANDLE event, bool& destroyed)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
Local local{ destroyed };
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress(HANDLE event, bool& destroyed)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
Local local{ destroyed };
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
handle start{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
handle completed{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
bool destroyed = false;
|
||||
auto async = make(start.get(), destroyed);
|
||||
|
||||
async.Completed([&](auto&&...)
|
||||
{
|
||||
REQUIRE(destroyed);
|
||||
SetEvent(completed.get());
|
||||
});
|
||||
|
||||
SetEvent(start.get());
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("async_local")
|
||||
{
|
||||
Check(Action);
|
||||
Check(ActionWithProgress);
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// Checks that coroutines lacking suspension points work.
|
||||
//
|
||||
|
||||
IAsyncAction Action()
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress()
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation()
|
||||
{
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress()
|
||||
{
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncAction Await()
|
||||
{
|
||||
co_await Action();
|
||||
co_await ActionWithProgress();
|
||||
co_await Operation();
|
||||
co_await OperationWithProgress();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Check(T const& async)
|
||||
{
|
||||
REQUIRE(async.Status() == AsyncStatus::Completed);
|
||||
REQUIRE(async.ErrorCode() == 0);
|
||||
REQUIRE(async.Id() == 1);
|
||||
|
||||
// Should not throw in the Completed state.
|
||||
async.GetResults();
|
||||
|
||||
bool completed = false;
|
||||
|
||||
async.Completed([&](auto&& sender, AsyncStatus status)
|
||||
{
|
||||
completed = true;
|
||||
REQUIRE(async == sender);
|
||||
REQUIRE(status == AsyncStatus::Completed);
|
||||
});
|
||||
|
||||
REQUIRE(completed);
|
||||
|
||||
// May only assign Completed handler once.
|
||||
REQUIRE_THROWS_AS(async.Completed([&](auto && ...) {}), hresult_illegal_delegate_assignment);
|
||||
|
||||
// Close does nothing.
|
||||
async.Close();
|
||||
|
||||
// Harmless but too late to cancel.
|
||||
async.Cancel();
|
||||
REQUIRE(async.Status() == AsyncStatus::Completed);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("async_no_suspend")
|
||||
{
|
||||
Action().get();
|
||||
ActionWithProgress().get();
|
||||
Operation().get();
|
||||
OperationWithProgress().get();
|
||||
Await().get();
|
||||
|
||||
Check(Action());
|
||||
Check(ActionWithProgress());
|
||||
Check(Operation());
|
||||
Check(OperationWithProgress());
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// Checks that progress reporting works.
|
||||
//
|
||||
|
||||
IAsyncActionWithProgress<int> Action(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
auto progress = co_await get_progress_token();
|
||||
progress(123);
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> Operation(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
auto progress = co_await get_progress_token();
|
||||
progress(123);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
IAsyncAction Check(F make)
|
||||
{
|
||||
// Event not set to allow Progress handler to be wired up.
|
||||
handle start{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
|
||||
auto async = make(start.get());
|
||||
bool progress = false;
|
||||
|
||||
async.Progress([&](auto&& sender, int value)
|
||||
{
|
||||
progress = true;
|
||||
REQUIRE(async == sender);
|
||||
REQUIRE(value == 123);
|
||||
});
|
||||
|
||||
SetEvent(start.get());
|
||||
co_await async;
|
||||
|
||||
REQUIRE(progress);
|
||||
REQUIRE(async.Status() == AsyncStatus::Completed);
|
||||
REQUIRE(async.ErrorCode() == S_OK);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
IAsyncAction TooLate(F make)
|
||||
{
|
||||
// Event initially set so that coroutine does not suspend.
|
||||
handle start{ CreateEvent(nullptr, true, true, nullptr) };
|
||||
|
||||
auto async = make(start.get());
|
||||
REQUIRE(async.Status() == AsyncStatus::Completed);
|
||||
|
||||
bool progress = false;
|
||||
|
||||
async.Progress([&](auto&&...)
|
||||
{
|
||||
REQUIRE(false);
|
||||
});
|
||||
|
||||
co_await async;
|
||||
|
||||
REQUIRE(!progress);
|
||||
REQUIRE(async.Status() == AsyncStatus::Completed);
|
||||
REQUIRE(async.ErrorCode() == S_OK);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("async_progress")
|
||||
{
|
||||
Check(Action);
|
||||
Check(Operation);
|
||||
|
||||
TooLate(Action);
|
||||
TooLate(Operation);
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// Checks that result values are propagated properly.
|
||||
//
|
||||
|
||||
IAsyncOperation<int> Operation(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_return 123;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_return 123;
|
||||
}
|
||||
|
||||
IAsyncAction Await()
|
||||
{
|
||||
// Manual reset so that all waiters will resume and initially set so they won't block.
|
||||
handle event{ CreateEvent(nullptr, true, true, nullptr) };
|
||||
|
||||
int a = co_await Operation(event.get());
|
||||
int b = co_await OperationWithProgress(event.get());
|
||||
|
||||
REQUIRE(a == 123);
|
||||
REQUIRE(b == 123);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
handle start{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
handle completed{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
auto async = make(start.get());
|
||||
REQUIRE(async.Status() == AsyncStatus::Started);
|
||||
if constexpr (has_async_progress<decltype(async)>)
|
||||
{
|
||||
// You're allowed to peek at partial results of IAsyncXxxWithProgress.
|
||||
REQUIRE_NOTHROW(async.GetResults());
|
||||
}
|
||||
else
|
||||
{
|
||||
REQUIRE_THROWS_AS(async.GetResults(), hresult_illegal_method_call);
|
||||
}
|
||||
|
||||
async.Completed([&](auto&& sender, AsyncStatus status)
|
||||
{
|
||||
REQUIRE(async == sender);
|
||||
REQUIRE(status == AsyncStatus::Completed);
|
||||
SetEvent(completed.get());
|
||||
});
|
||||
|
||||
// Still in Started state waiting for signal.
|
||||
Sleep(100);
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 0) == WAIT_TIMEOUT);
|
||||
REQUIRE(async.Status() == AsyncStatus::Started);
|
||||
|
||||
// Signal async to run.
|
||||
SetEvent(start.get());
|
||||
|
||||
// Wait for async to complete.
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0);
|
||||
|
||||
REQUIRE(async.Status() == AsyncStatus::Completed);
|
||||
REQUIRE(async.ErrorCode() == S_OK);
|
||||
REQUIRE(async.GetResults() == 123);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("async_result")
|
||||
{
|
||||
handle start{ CreateEvent(nullptr, true, true, nullptr) };
|
||||
REQUIRE(123 == Operation(start.get()).get());
|
||||
REQUIRE(123 == OperationWithProgress(start.get()).get());
|
||||
Await().get();
|
||||
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// Checks that return values support both rvalue and lvalue.
|
||||
//
|
||||
|
||||
IAsyncOperation<hstring> Operation(bool rvalue)
|
||||
{
|
||||
if (rvalue)
|
||||
{
|
||||
hstring value = L"rvalue";
|
||||
co_return std::move(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
hstring value = L"lvalue";
|
||||
co_return value;
|
||||
}
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<hstring, int> OperationWithProgress(bool rvalue)
|
||||
{
|
||||
if (rvalue)
|
||||
{
|
||||
hstring value = L"rvalue";
|
||||
co_return std::move(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
hstring value = L"lvalue";
|
||||
co_return value;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
REQUIRE(make(true).get() == L"rvalue");
|
||||
REQUIRE(make(false).get() == L"lvalue");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("async_return")
|
||||
{
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// Checks basic suspension behavior.
|
||||
//
|
||||
|
||||
IAsyncAction Action(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress(HANDLE event)
|
||||
{
|
||||
co_await resume_on_signal(event);
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncAction Await()
|
||||
{
|
||||
// Manual reset so that all waiters will resume and initially set so they won't block.
|
||||
handle event{ CreateEvent(nullptr, true, true, nullptr) };
|
||||
|
||||
co_await Action(event.get());
|
||||
co_await ActionWithProgress(event.get());
|
||||
co_await Operation(event.get());
|
||||
co_await OperationWithProgress(event.get());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
handle start{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
handle completed{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
auto async = make(start.get());
|
||||
REQUIRE(async.Status() == AsyncStatus::Started);
|
||||
if constexpr (has_async_progress<decltype(async)>)
|
||||
{
|
||||
// You're allowed to peek at partial results of IAsyncXxxWithProgress.
|
||||
REQUIRE_NOTHROW(async.GetResults());
|
||||
}
|
||||
else
|
||||
{
|
||||
REQUIRE_THROWS_AS(async.GetResults(), hresult_illegal_method_call);
|
||||
}
|
||||
|
||||
async.Completed([&](auto&& sender, AsyncStatus status)
|
||||
{
|
||||
REQUIRE(async == sender);
|
||||
REQUIRE(status == AsyncStatus::Completed);
|
||||
SetEvent(completed.get());
|
||||
});
|
||||
|
||||
// Still in Started state waiting for signal.
|
||||
Sleep(100);
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 0) == WAIT_TIMEOUT);
|
||||
REQUIRE(async.Status() == AsyncStatus::Started);
|
||||
|
||||
// Signal async to run.
|
||||
SetEvent(start.get());
|
||||
|
||||
// Wait for async to complete.
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0);
|
||||
|
||||
REQUIRE(async.Status() == AsyncStatus::Completed);
|
||||
REQUIRE(async.ErrorCode() == S_OK);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("async_suspend")
|
||||
{
|
||||
handle start{ CreateEvent(nullptr, true, true, nullptr) };
|
||||
Action(start.get()).get();
|
||||
ActionWithProgress(start.get()).get();
|
||||
Operation(start.get()).get();
|
||||
OperationWithProgress(start.get()).get();
|
||||
Await().get();
|
||||
|
||||
Check(Action);
|
||||
Check(ActionWithProgress);
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// Checks that exceptions are correctly captured and propagated.
|
||||
//
|
||||
|
||||
IAsyncAction Action()
|
||||
{
|
||||
co_await 10ms;
|
||||
throw hresult_invalid_argument(L"Async");
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress()
|
||||
{
|
||||
co_await 10ms;
|
||||
throw hresult_invalid_argument(L"Async");
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation()
|
||||
{
|
||||
co_await 10ms;
|
||||
throw hresult_invalid_argument(L"Async");
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress()
|
||||
{
|
||||
co_await 10ms;
|
||||
throw hresult_invalid_argument(L"Async");
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void Check(F make)
|
||||
{
|
||||
try
|
||||
{
|
||||
make().get();
|
||||
REQUIRE(false);
|
||||
}
|
||||
catch (hresult_invalid_argument const& e)
|
||||
{
|
||||
REQUIRE(e.message() == L"Async");
|
||||
}
|
||||
|
||||
handle completed{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
auto async = make();
|
||||
|
||||
async.Completed([&](auto&& sender, AsyncStatus status)
|
||||
{
|
||||
REQUIRE(async == sender);
|
||||
REQUIRE(status == AsyncStatus::Error);
|
||||
SetEvent(completed.get());
|
||||
});
|
||||
|
||||
REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0);
|
||||
REQUIRE(async.Status() == AsyncStatus::Error);
|
||||
|
||||
hresult_error e(async.ErrorCode(), take_ownership_from_abi);
|
||||
REQUIRE(e.message() == L"Async");
|
||||
|
||||
try
|
||||
{
|
||||
async.GetResults();
|
||||
REQUIRE(false);
|
||||
}
|
||||
catch (hresult_invalid_argument const& e)
|
||||
{
|
||||
REQUIRE(e.message() == L"Async");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__) && defined(_MSC_VER)
|
||||
// FIXME: Test is known to segfault when built with Clang.
|
||||
TEST_CASE("async_throw", "[.clang-crash]")
|
||||
#else
|
||||
TEST_CASE("async_throw")
|
||||
#endif
|
||||
{
|
||||
Check(Action);
|
||||
Check(ActionWithProgress);
|
||||
Check(Operation);
|
||||
Check(OperationWithProgress);
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace std::literals;
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
IAsyncAction Action(TimeSpan delay, AsyncStatus result)
|
||||
{
|
||||
co_await resume_after(delay);
|
||||
|
||||
if (result == AsyncStatus::Error)
|
||||
{
|
||||
throw hresult_invalid_argument();
|
||||
}
|
||||
|
||||
if (result == AsyncStatus::Canceled)
|
||||
{
|
||||
throw hresult_canceled();
|
||||
}
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionWithProgress(TimeSpan delay, AsyncStatus result)
|
||||
{
|
||||
co_await resume_after(delay);
|
||||
|
||||
if (result == AsyncStatus::Error)
|
||||
{
|
||||
throw hresult_invalid_argument();
|
||||
}
|
||||
|
||||
if (result == AsyncStatus::Canceled)
|
||||
{
|
||||
throw hresult_canceled();
|
||||
}
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation(TimeSpan delay, AsyncStatus result)
|
||||
{
|
||||
co_await resume_after(delay);
|
||||
|
||||
if (result == AsyncStatus::Error)
|
||||
{
|
||||
throw hresult_invalid_argument();
|
||||
}
|
||||
|
||||
if (result == AsyncStatus::Canceled)
|
||||
{
|
||||
throw hresult_canceled();
|
||||
}
|
||||
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationWithProgress(TimeSpan delay, AsyncStatus result)
|
||||
{
|
||||
co_await resume_after(delay);
|
||||
|
||||
if (result == AsyncStatus::Error)
|
||||
{
|
||||
throw hresult_invalid_argument();
|
||||
}
|
||||
|
||||
if (result == AsyncStatus::Canceled)
|
||||
{
|
||||
throw hresult_canceled();
|
||||
}
|
||||
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void check(T const& no_suspend_ok, T const& no_suspend_fail, T const& delay_ok, T const& delay_fail, T const& no_suspend_cancel, T const& delay_cancel, T const& long_delay)
|
||||
{
|
||||
REQUIRE(no_suspend_ok.wait_for(0s) == AsyncStatus::Completed);
|
||||
no_suspend_ok.get();
|
||||
REQUIRE_THROWS_AS(no_suspend_ok.wait_for(0s), hresult_illegal_delegate_assignment);
|
||||
|
||||
REQUIRE(no_suspend_fail.wait_for(0s) == AsyncStatus::Error);
|
||||
REQUIRE_THROWS_AS(no_suspend_fail.get(), hresult_invalid_argument);
|
||||
|
||||
REQUIRE(delay_ok.wait_for(1s) == AsyncStatus::Completed);
|
||||
delay_ok.get();
|
||||
|
||||
REQUIRE(delay_fail.wait_for(1s) == AsyncStatus::Error);
|
||||
REQUIRE_THROWS_AS(delay_fail.get(), hresult_invalid_argument);
|
||||
|
||||
REQUIRE(no_suspend_cancel.wait_for(0s) == AsyncStatus::Canceled);
|
||||
REQUIRE_THROWS_AS(no_suspend_cancel.get(), hresult_canceled);
|
||||
|
||||
REQUIRE(delay_cancel.wait_for(1s) == AsyncStatus::Canceled);
|
||||
REQUIRE_THROWS_AS(delay_cancel.get(), hresult_canceled);
|
||||
|
||||
REQUIRE(long_delay.wait_for(100ms) == AsyncStatus::Started);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__) && defined(_MSC_VER)
|
||||
// FIXME: Test is known to segfault when built with Clang.
|
||||
TEST_CASE("async_wait_for", "[.clang-crash]")
|
||||
#else
|
||||
TEST_CASE("async_wait_for")
|
||||
#endif
|
||||
{
|
||||
check(
|
||||
Action(0s, AsyncStatus::Completed),
|
||||
Action(0s, AsyncStatus::Error),
|
||||
Action(100ms, AsyncStatus::Completed),
|
||||
Action(100ms, AsyncStatus::Error),
|
||||
Action(0s, AsyncStatus::Canceled),
|
||||
Action(100ms, AsyncStatus::Canceled),
|
||||
Action(1h, AsyncStatus::Completed));
|
||||
|
||||
check(
|
||||
ActionWithProgress(0s, AsyncStatus::Completed),
|
||||
ActionWithProgress(0s, AsyncStatus::Error),
|
||||
ActionWithProgress(100ms, AsyncStatus::Completed),
|
||||
ActionWithProgress(100ms, AsyncStatus::Error),
|
||||
ActionWithProgress(0s, AsyncStatus::Canceled),
|
||||
ActionWithProgress(100ms, AsyncStatus::Canceled),
|
||||
ActionWithProgress(1h, AsyncStatus::Completed));
|
||||
|
||||
check(
|
||||
Operation(0s, AsyncStatus::Completed),
|
||||
Operation(0s, AsyncStatus::Error),
|
||||
Operation(100ms, AsyncStatus::Completed),
|
||||
Operation(100ms, AsyncStatus::Error),
|
||||
Operation(0s, AsyncStatus::Canceled),
|
||||
Operation(100ms, AsyncStatus::Canceled),
|
||||
Operation(1h, AsyncStatus::Completed));
|
||||
|
||||
check(
|
||||
OperationWithProgress(0s, AsyncStatus::Completed),
|
||||
OperationWithProgress(0s, AsyncStatus::Error),
|
||||
OperationWithProgress(100ms, AsyncStatus::Completed),
|
||||
OperationWithProgress(100ms, AsyncStatus::Error),
|
||||
OperationWithProgress(0s, AsyncStatus::Canceled),
|
||||
OperationWithProgress(100ms, AsyncStatus::Canceled),
|
||||
OperationWithProgress(1h, AsyncStatus::Completed));
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
struct DECLSPEC_UUID("5fb96f8d-409c-42a9-99a7-8a95c1459dbd") ICapture : ::IUnknown
|
||||
{
|
||||
virtual int32_t __stdcall GetValue() noexcept = 0;
|
||||
virtual int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept = 0;
|
||||
};
|
||||
|
||||
#ifdef __CRT_UUID_DECL
|
||||
__CRT_UUID_DECL(ICapture, 0x5fb96f8d, 0x409c, 0x42a9, 0x99, 0xa7, 0x8a, 0x95, 0xc1, 0x45, 0x9d, 0xbd)
|
||||
#endif
|
||||
|
||||
struct Capture : implements<Capture, ICapture, IStringable>
|
||||
{
|
||||
int32_t const m_value{};
|
||||
|
||||
Capture(int32_t value) :
|
||||
m_value{ value }
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return hstring{ std::to_wstring(m_value) };
|
||||
}
|
||||
|
||||
int32_t __stdcall GetValue() noexcept override
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept override
|
||||
{
|
||||
auto capture = make<Capture>(value);
|
||||
return capture->QueryInterface(iid, object);
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT __stdcall CreateNonMemberCapture(int value, GUID const& iid, void** object) noexcept
|
||||
{
|
||||
auto capture = make<Capture>(value);
|
||||
return capture->QueryInterface(iid, object);
|
||||
}
|
||||
|
||||
TEST_CASE("capture")
|
||||
{
|
||||
com_ptr<ICapture> a = capture<ICapture>(CreateNonMemberCapture, 10);
|
||||
REQUIRE(a->GetValue() == 10);
|
||||
a = nullptr;
|
||||
a.capture(CreateNonMemberCapture, 20);
|
||||
REQUIRE(a->GetValue() == 20);
|
||||
|
||||
com_ptr<ICapture> b = capture<ICapture>(a, &ICapture::CreateMemberCapture, 30);
|
||||
REQUIRE(b->GetValue() == 30);
|
||||
b = nullptr;
|
||||
b.capture(a, &ICapture::CreateMemberCapture, 40);
|
||||
REQUIRE(b->GetValue() == 40);
|
||||
|
||||
IStringable c = capture<IStringable>(CreateNonMemberCapture, 50);
|
||||
REQUIRE(c.ToString() == L"50");
|
||||
c = capture<IStringable>(a, &ICapture::CreateMemberCapture, 60);
|
||||
REQUIRE(c.ToString() == L"60");
|
||||
|
||||
com_ptr<IDispatch> d;
|
||||
|
||||
REQUIRE_THROWS_AS(capture<IDispatch>(CreateNonMemberCapture, 0), hresult_no_interface);
|
||||
REQUIRE_THROWS_AS(capture<IClosable>(CreateNonMemberCapture, 0), hresult_no_interface);
|
||||
REQUIRE_THROWS_AS(d.capture(CreateNonMemberCapture, 0), hresult_no_interface);
|
||||
REQUIRE_THROWS_AS(capture<IDispatch>(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface);
|
||||
REQUIRE_THROWS_AS(capture<IClosable>(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface);
|
||||
REQUIRE_THROWS_AS(d.capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface);
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "cmd_reader.h"
|
||||
#include <fstream>
|
||||
|
||||
using namespace cppwinrt;
|
||||
|
||||
class response_file
|
||||
{
|
||||
const char* resp_file_name = "respfile.txt";
|
||||
void write_response_file(const char* input)
|
||||
{
|
||||
std::ofstream resp_file(resp_file_name);
|
||||
if (!resp_file.is_open())
|
||||
FAIL("Response file could not be created");
|
||||
resp_file << input;
|
||||
resp_file.close();
|
||||
}
|
||||
|
||||
void remove_response_file()
|
||||
{
|
||||
std::remove(resp_file_name);
|
||||
}
|
||||
|
||||
public:
|
||||
response_file(const char* input)
|
||||
{
|
||||
write_response_file(input);
|
||||
}
|
||||
|
||||
template<size_t numOptions>
|
||||
reader create_reader(size_t const argc, const char* argv[], const option(&options)[numOptions])
|
||||
{
|
||||
return reader{ argc, argv, options };
|
||||
}
|
||||
|
||||
~response_file()
|
||||
{
|
||||
remove_response_file();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("cmd_reader")
|
||||
{
|
||||
static constexpr option options[]
|
||||
{
|
||||
{ "input", 1 },
|
||||
{ "reference", 0 },
|
||||
{ "output", 0, 1 },
|
||||
{ "component", 0, 1 },
|
||||
{ "filter", 0 },
|
||||
{ "name", 0, 1 },
|
||||
{ "verbose", 0, 0 },
|
||||
};
|
||||
|
||||
// input and output
|
||||
{
|
||||
const char* argv[] = { "progname", "-in", "example_file.in", "-out", "example_file.out" };
|
||||
const size_t argc = 5;
|
||||
reader args{ argc, argv, options };
|
||||
|
||||
REQUIRE(args.exists("input"));
|
||||
REQUIRE(args.value("input") == "example_file.in");
|
||||
REQUIRE_FALSE(args.exists("reference"));
|
||||
REQUIRE(args.exists("output"));
|
||||
REQUIRE(args.value("output") == "example_file.out");
|
||||
REQUIRE_FALSE(args.exists("filter"));
|
||||
REQUIRE_FALSE(args.exists("name"));
|
||||
REQUIRE_FALSE(args.exists("verbose"));
|
||||
}
|
||||
|
||||
// response file #1: filename no quotes
|
||||
{
|
||||
const char* argv[] = { "progname", "@respfile.txt" };
|
||||
const size_t argc = _countof(argv);
|
||||
|
||||
response_file rf{ R"(-in example_file.in -out example_file.out)" };
|
||||
reader args = rf.create_reader(argc, argv, options);
|
||||
|
||||
REQUIRE(args.exists("input"));
|
||||
REQUIRE(args.value("input") == "example_file.in");
|
||||
REQUIRE_FALSE(args.exists("reference"));
|
||||
REQUIRE(args.exists("output"));
|
||||
REQUIRE(args.value("output") == "example_file.out");
|
||||
REQUIRE_FALSE(args.exists("filter"));
|
||||
REQUIRE_FALSE(args.exists("name"));
|
||||
REQUIRE_FALSE(args.exists("verbose"));
|
||||
}
|
||||
|
||||
// response file #2: filename with quotes
|
||||
{
|
||||
const char* argv[] = { "progname", "@respfile.txt" };
|
||||
const size_t argc = _countof(argv);
|
||||
|
||||
response_file rf{ R"(-in "example file.in" -out "example file.out")" };
|
||||
reader args = rf.create_reader(argc, argv, options);
|
||||
|
||||
REQUIRE(args.exists("input"));
|
||||
REQUIRE(args.value("input") == "example file.in");
|
||||
REQUIRE_FALSE(args.exists("reference"));
|
||||
REQUIRE(args.exists("output"));
|
||||
REQUIRE(args.value("output") == "example file.out");
|
||||
REQUIRE_FALSE(args.exists("filter"));
|
||||
REQUIRE_FALSE(args.exists("name"));
|
||||
REQUIRE_FALSE(args.exists("verbose"));
|
||||
}
|
||||
|
||||
// response file #3: filename with quote within name
|
||||
{
|
||||
const char* argv[] = { "progname", "@respfile.txt" };
|
||||
const size_t argc = _countof(argv);
|
||||
|
||||
response_file rf{ R"(-in example\"file.in -out example\"file.out)" };
|
||||
reader args = rf.create_reader(argc, argv, options);
|
||||
|
||||
REQUIRE(args.exists("input"));
|
||||
REQUIRE(args.value("input") == R"(example"file.in)");
|
||||
REQUIRE_FALSE(args.exists("reference"));
|
||||
REQUIRE(args.exists("output"));
|
||||
REQUIRE(args.value("output") == R"(example"file.out)");
|
||||
REQUIRE_FALSE(args.exists("filter"));
|
||||
REQUIRE_FALSE(args.exists("name"));
|
||||
REQUIRE_FALSE(args.exists("verbose"));
|
||||
}
|
||||
|
||||
// response file #4: really really long path
|
||||
{
|
||||
const char* argv[] = { "progname", "@respfile.txt" };
|
||||
const size_t argc = _countof(argv);
|
||||
std::string file_name_in(R"(C:\)");
|
||||
std::string file_name_out(R"(C:\)");
|
||||
std::string input_str("-in ");
|
||||
|
||||
for (int i = 0; i < 500; i++) {
|
||||
file_name_in.append(R"(dirname\)");
|
||||
file_name_out.append(R"(dirname\)");
|
||||
}
|
||||
|
||||
file_name_in.append("example_file.in");
|
||||
file_name_out.append("example_file.out");
|
||||
input_str.append(file_name_in).append(" -out ").append(file_name_out);
|
||||
|
||||
response_file rf{ input_str.data() };
|
||||
reader args = rf.create_reader(argc, argv, options);
|
||||
|
||||
REQUIRE(args.exists("input"));
|
||||
REQUIRE(args.value("input") == file_name_in);
|
||||
REQUIRE_FALSE(args.exists("reference"));
|
||||
REQUIRE(args.exists("output"));
|
||||
REQUIRE(args.value("output") == file_name_out);
|
||||
REQUIRE_FALSE(args.exists("filter"));
|
||||
REQUIRE_FALSE(args.exists("name"));
|
||||
REQUIRE_FALSE(args.exists("verbose"));
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
// Intentionally not using pch...
|
||||
#include "catch.hpp"
|
||||
|
||||
// Only need winrt/Windows.Foundation.h for IAsyncXxx coroutine support
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
IAsyncOperation<hstring> Async()
|
||||
{
|
||||
co_return L"hello";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("coro_foundation")
|
||||
{
|
||||
REQUIRE(Async().get() == L"hello");
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// Intentionally not using pch...
|
||||
#include "catch.hpp"
|
||||
|
||||
// Only need winrt/base.h for coroutine thread pool support.
|
||||
#include "winrt/base.h"
|
||||
|
||||
using namespace winrt;
|
||||
|
||||
namespace
|
||||
{
|
||||
fire_and_forget Async()
|
||||
{
|
||||
co_await resume_background();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("coro_base")
|
||||
{
|
||||
Async();
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
// Some custom exception type unknown to C++/WinRT
|
||||
struct CustomError
|
||||
{
|
||||
};
|
||||
|
||||
struct Sample : implements<Sample, IStringable>
|
||||
{
|
||||
hstring ToString()
|
||||
{
|
||||
// Throw custom exception inside C++/WinRT projection
|
||||
throw CustomError();
|
||||
}
|
||||
};
|
||||
|
||||
// Global handler to translate custom exception
|
||||
int32_t __stdcall handler(void* address) noexcept
|
||||
{
|
||||
REQUIRE(address);
|
||||
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (CustomError)
|
||||
{
|
||||
return 0x80000018; // E_ILLEGAL_DELEGATE_ASSIGNMENT
|
||||
}
|
||||
|
||||
REQUIRE(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("custom_error")
|
||||
{
|
||||
// Set up global handler
|
||||
REQUIRE(!winrt_to_hresult_handler);
|
||||
winrt_to_hresult_handler = handler;
|
||||
|
||||
// Validate that handler translated exception
|
||||
REQUIRE_THROWS_AS(make<Sample>().ToString(), hresult_illegal_delegate_assignment);
|
||||
|
||||
// Remove global handler
|
||||
winrt_to_hresult_handler = nullptr;
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
|
||||
TEST_CASE("delegate")
|
||||
{
|
||||
// <>
|
||||
{
|
||||
bool invoked = false;
|
||||
delegate<> d = [&] {invoked = true; };
|
||||
d();
|
||||
REQUIRE(invoked);
|
||||
}
|
||||
|
||||
// <int>
|
||||
{
|
||||
int result = 0;
|
||||
delegate<int> d = [&](int a) {result = a; };
|
||||
d(123);
|
||||
REQUIRE(result == 123);
|
||||
}
|
||||
|
||||
// <int,int>
|
||||
{
|
||||
int result = 0;
|
||||
delegate<int, int> d = [&](int a, int b) {result = a + b; };
|
||||
d(4,5);
|
||||
REQUIRE(result == 9);
|
||||
}
|
||||
|
||||
// void()
|
||||
{
|
||||
bool invoked = false;
|
||||
delegate<void()> d = [&] {invoked = true; };
|
||||
d();
|
||||
REQUIRE(invoked);
|
||||
}
|
||||
|
||||
// void(int)
|
||||
{
|
||||
int result = 0;
|
||||
delegate<void(int)> d = [&](int a) {result = a; };
|
||||
d(123);
|
||||
REQUIRE(result == 123);
|
||||
}
|
||||
|
||||
// void(int,int)
|
||||
{
|
||||
int result = 0;
|
||||
delegate<void(int,int)> d = [&](int a, int b) {result = a + b; };
|
||||
d(4, 5);
|
||||
REQUIRE(result == 9);
|
||||
}
|
||||
|
||||
// int()
|
||||
{
|
||||
delegate<int()> d = [] { return 123; };
|
||||
REQUIRE(d() == 123);
|
||||
}
|
||||
|
||||
// int(int)
|
||||
{
|
||||
delegate<int(int)> d = [](int a) {return a; };
|
||||
REQUIRE(d(123) == 123);
|
||||
}
|
||||
|
||||
// int(int,int)
|
||||
{
|
||||
delegate<int(int, int)> d = [](int a, int b) {return a + b; };
|
||||
REQUIRE(d(4, 5) == 9);
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.Delegates.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace test_component::Delegates;
|
||||
|
||||
TEST_CASE("delegates")
|
||||
{
|
||||
{
|
||||
bool run{};
|
||||
AgileDelegate d = [&] {run = true; };
|
||||
REQUIRE(!run);
|
||||
d();
|
||||
REQUIRE(run);
|
||||
}
|
||||
{
|
||||
hstring value;
|
||||
InDelegate d = [&](hstring const& in)
|
||||
{
|
||||
value = in;
|
||||
};
|
||||
REQUIRE(value.empty());
|
||||
d(L"Test");
|
||||
REQUIRE(value == L"Test");
|
||||
}
|
||||
{
|
||||
ReturnStringDelegate d = [] {return L"Test"; };
|
||||
REQUIRE(d() == L"Test");
|
||||
}
|
||||
{
|
||||
ReturnInt32Delegate d = [] {return 123; };
|
||||
REQUIRE(d() == 123);
|
||||
}
|
||||
{
|
||||
OutStringDelegate d = [](hstring& value)
|
||||
{
|
||||
value = L"Test";
|
||||
};
|
||||
hstring value;
|
||||
d(value);
|
||||
REQUIRE(value == L"Test");
|
||||
}
|
||||
{
|
||||
OutStringDelegate d = [](hstring&)
|
||||
{
|
||||
};
|
||||
hstring value = L"old";
|
||||
d(value);
|
||||
REQUIRE(value == L"");
|
||||
}
|
||||
{
|
||||
OutInt32Delegate d = [](int32_t & value)
|
||||
{
|
||||
value = 123;
|
||||
};
|
||||
int32_t value{ 0xCC };
|
||||
d(value);
|
||||
REQUIRE(value == 123);
|
||||
}
|
||||
{
|
||||
OutInt32Delegate d = [](int32_t&)
|
||||
{
|
||||
};
|
||||
int32_t value{ 123 };
|
||||
d(value);
|
||||
REQUIRE(value == 123);
|
||||
}
|
||||
{
|
||||
ReturnStringArrayDelegate d = [] { return com_array<hstring>{ L"One", L"Two", L"Three" }; };
|
||||
com_array<hstring> value = d();
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0] == L"One");
|
||||
REQUIRE(value[1] == L"Two");
|
||||
REQUIRE(value[2] == L"Three");
|
||||
}
|
||||
{
|
||||
OutStringArrayDelegate d = [](com_array<hstring>& value) { value = { L"One", L"Two", L"Three" }; };
|
||||
|
||||
com_array<hstring> value;
|
||||
d(value);
|
||||
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0] == L"One");
|
||||
REQUIRE(value[1] == L"Two");
|
||||
REQUIRE(value[2] == L"Three");
|
||||
}
|
||||
{
|
||||
RefStringArrayDelegate d = [](array_view<hstring> value) { value[0] = L"One"; value[1] = L"Two"; value[2] = L"Three"; };
|
||||
|
||||
std::array<hstring, 4> value{ L"r1", L"r2", L"r3", L"r4" };
|
||||
d(value);
|
||||
|
||||
REQUIRE(value[0] == L"One");
|
||||
REQUIRE(value[1] == L"Two");
|
||||
REQUIRE(value[2] == L"Three");
|
||||
REQUIRE(value[3] == L"");
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace std::literals;
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
IAsyncAction Action()
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
IAsyncActionWithProgress<int> ActionProgress()
|
||||
{
|
||||
co_await 500ms;
|
||||
auto progress = co_await get_progress_token();
|
||||
progress(123);
|
||||
co_return;
|
||||
}
|
||||
|
||||
IAsyncOperation<int> Operation()
|
||||
{
|
||||
co_return 123;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<int, int> OperationProgress()
|
||||
{
|
||||
co_await 500ms;
|
||||
auto progress = co_await get_progress_token();
|
||||
progress(123);
|
||||
co_return 123;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("disconnected,1")
|
||||
{
|
||||
event<EventHandler<int>> source;
|
||||
|
||||
source.add([](auto...)
|
||||
{
|
||||
throw hresult_error(RPC_E_DISCONNECTED);
|
||||
});
|
||||
|
||||
auto token = source.add([](auto...)
|
||||
{
|
||||
throw hresult_error(E_INVALIDARG);
|
||||
});
|
||||
|
||||
// Should have two delegates
|
||||
REQUIRE(source);
|
||||
|
||||
// Should lose the disconnected delegate
|
||||
source(nullptr, 123);
|
||||
REQUIRE(source);
|
||||
|
||||
// Fire the remaining delegate
|
||||
source(nullptr, 123);
|
||||
REQUIRE(source);
|
||||
|
||||
// Remove the final delegate
|
||||
source.remove(token);
|
||||
|
||||
// No more delegates
|
||||
REQUIRE(!source);
|
||||
|
||||
source(nullptr, 123);
|
||||
}
|
||||
|
||||
TEST_CASE("disconnected,2")
|
||||
{
|
||||
auto async = Action();
|
||||
|
||||
async.Completed([](auto&&...)
|
||||
{
|
||||
throw hresult_error(RPC_E_DISCONNECTED);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("disconnected,3")
|
||||
{
|
||||
auto async = ActionProgress();
|
||||
handle signal{ CreateEventW(nullptr, true, false, nullptr) };
|
||||
|
||||
async.Progress([](auto&&...)
|
||||
{
|
||||
throw hresult_error(RPC_E_DISCONNECTED);
|
||||
});
|
||||
|
||||
async.Completed([&](auto&&...)
|
||||
{
|
||||
SetEvent(signal.get());
|
||||
throw hresult_error(RPC_E_DISCONNECTED);
|
||||
});
|
||||
|
||||
WaitForSingleObject(signal.get(), INFINITE);
|
||||
// Give some time for to_hresult() to complete.
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
TEST_CASE("disconnected,4")
|
||||
{
|
||||
auto async = Operation();
|
||||
|
||||
async.Completed([](auto&&...)
|
||||
{
|
||||
throw hresult_error(RPC_E_DISCONNECTED);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("disconnected,5")
|
||||
{
|
||||
auto async = OperationProgress();
|
||||
handle signal{ CreateEventW(nullptr, true, false, nullptr) };
|
||||
|
||||
async.Progress([](auto&&...)
|
||||
{
|
||||
throw hresult_error(RPC_E_DISCONNECTED);
|
||||
});
|
||||
|
||||
async.Completed([&](auto&&...)
|
||||
{
|
||||
SetEvent(signal.get());
|
||||
throw hresult_error(RPC_E_DISCONNECTED);
|
||||
});
|
||||
|
||||
WaitForSingleObject(signal.get(), INFINITE);
|
||||
// Give some time for to_hresult() to complete.
|
||||
Sleep(500);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace test_component;
|
||||
|
||||
TEST_CASE("enum")
|
||||
{
|
||||
STATIC_REQUIRE(std::is_same_v<std::underlying_type_t<Signed>, int32_t>);
|
||||
STATIC_REQUIRE(std::is_same_v<std::underlying_type_t<Unsigned>, uint32_t>);
|
||||
|
||||
STATIC_REQUIRE(name_of<Signed>() == L"test_component.Signed"sv);
|
||||
STATIC_REQUIRE(name_of<Unsigned>() == L"test_component.Unsigned"sv);
|
||||
|
||||
REQUIRE(((Unsigned::First | Unsigned::Second | Unsigned::Third) & Unsigned::Second) == Unsigned::Second);
|
||||
|
||||
REQUIRE(static_cast<int32_t>(Signed::First) == -1);
|
||||
REQUIRE(static_cast<int32_t>(Signed::Second) == 0);
|
||||
REQUIRE(static_cast<int32_t>(Signed::Third) == 1);
|
||||
|
||||
REQUIRE(static_cast<uint32_t>(Unsigned::First) == 0);
|
||||
REQUIRE(static_cast<uint32_t>(Unsigned::Second) == 1);
|
||||
REQUIRE(static_cast<uint32_t>(Unsigned::Third) == 2);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
TEST_CASE("fast_iterator")
|
||||
{
|
||||
{
|
||||
auto v = winrt::single_threaded_vector<int>({ 1, 2, 3 });
|
||||
|
||||
std::vector<int> result;
|
||||
|
||||
std::copy(begin(v), end(v), std::back_inserter(result));
|
||||
|
||||
REQUIRE((result == std::vector{ 1, 2, 3 }));
|
||||
}
|
||||
{
|
||||
auto v = winrt::single_threaded_vector<int>({ 1, 2, 3 });
|
||||
|
||||
std::vector<int> result;
|
||||
|
||||
std::copy(rbegin(v), rend(v), std::back_inserter(result));
|
||||
|
||||
REQUIRE((result == std::vector{ 3, 2, 1 }));
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Sample : implements<Sample, IStringable>
|
||||
{
|
||||
hstring ToString()
|
||||
{
|
||||
return L"Sample";
|
||||
}
|
||||
|
||||
~Sample()
|
||||
{
|
||||
// It's safe to QI/AddRef/Release inside destructor.
|
||||
IStringable s;
|
||||
check_hresult(QueryInterface(guid_of<IStringable>(), put_abi(s)));
|
||||
REQUIRE(s.ToString() == L"Sample");
|
||||
|
||||
// Weak references are also supported during destruction.
|
||||
REQUIRE(weak_ref<IStringable>{ s }.get());
|
||||
|
||||
REQUIRE(released);
|
||||
REQUIRE(!destroyed);
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
static void final_release(std::unique_ptr<Sample> ptr) noexcept
|
||||
{
|
||||
// It's safe to QI/AddRef/Release inside final_release.
|
||||
IStringable s;
|
||||
check_hresult(ptr->QueryInterface(guid_of<IStringable>(), put_abi(s)));
|
||||
REQUIRE(s.ToString() == L"Sample");
|
||||
|
||||
// References must be released prior to destroying the unique_ptr.
|
||||
s = nullptr;
|
||||
|
||||
REQUIRE(!released);
|
||||
REQUIRE(!destroyed);
|
||||
released = true;
|
||||
ptr = nullptr;
|
||||
REQUIRE(destroyed);
|
||||
}
|
||||
|
||||
static inline bool released;
|
||||
static inline bool destroyed;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("final_release")
|
||||
{
|
||||
{
|
||||
auto s = make<Sample>();
|
||||
|
||||
// Weak references are supported prior to destruction.
|
||||
REQUIRE(weak_ref<IStringable>{ s }.get());
|
||||
|
||||
REQUIRE(!Sample::released);
|
||||
REQUIRE(!Sample::destroyed);
|
||||
s = nullptr;
|
||||
REQUIRE(Sample::released);
|
||||
REQUIRE(Sample::destroyed);
|
||||
}
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
// Windows.Foundation is intentionally *not* included here to ensure that stable names/guids
|
||||
// are generated with only the xxx.0.h header. This ensures that indirect declarations produce
|
||||
// stable identity values.
|
||||
#define WINRT_LEAN_AND_MEAN
|
||||
#include "winrt/Windows.Storage.h"
|
||||
|
||||
#include "catch.hpp"
|
||||
#include "generic_types.h"
|
||||
|
||||
TEST_CASE("generic_type_names")
|
||||
{
|
||||
using A = IIterable<IStringable>;
|
||||
using B = IKeyValuePair<hstring, IAsyncOperationWithProgress<A, float>>;
|
||||
|
||||
test_guids();
|
||||
|
||||
//
|
||||
// Generated Windows.Foundation names
|
||||
//
|
||||
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IStringable",
|
||||
IStringable);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IAsyncActionWithProgress`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IAsyncActionWithProgress<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
IAsyncOperationWithProgress<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IAsyncOperation`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IAsyncOperation<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReferenceArray`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IReferenceArray<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IReference<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncActionProgressHandler`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
AsyncActionProgressHandler<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncActionWithProgressCompletedHandler`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
AsyncActionWithProgressCompletedHandler<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncOperationCompletedHandler`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
AsyncOperationCompletedHandler<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncOperationProgressHandler`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
AsyncOperationProgressHandler<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncOperationWithProgressCompletedHandler`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
AsyncOperationWithProgressCompletedHandler<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.EventHandler`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
EventHandler<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.TypedEventHandler`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
TypedEventHandler<A, B>);
|
||||
|
||||
//
|
||||
// Generated Windows.Foundation.Collections names
|
||||
//
|
||||
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IIterable`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IIterable<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IIterator`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IIterator<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IKeyValuePair`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
IKeyValuePair<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IMapChangedEventArgs`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IMapChangedEventArgs<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IMapView`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
IMapView<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IMap`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
IMap<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IObservableMap`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
IObservableMap<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IObservableVector`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IObservableVector<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVectorView`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IVectorView<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
IVector<A>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.MapChangedEventHandler`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Windows.Foundation.Collections.IKeyValuePair`2<String, Windows.Foundation.IAsyncOperationWithProgress`2<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>, Single>>>",
|
||||
MapChangedEventHandler<A, B>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.VectorChangedEventHandler`1<Windows.Foundation.Collections.IIterable`1<Windows.Foundation.IStringable>>",
|
||||
VectorChangedEventHandler<A>);
|
||||
|
||||
//
|
||||
// Generated primitive names
|
||||
//
|
||||
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Boolean>",
|
||||
IReference<bool>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Int8>",
|
||||
IReference<int8_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Int16>",
|
||||
IReference<int16_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Int32>",
|
||||
IReference<int32_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Int64>",
|
||||
IReference<int64_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<UInt8>",
|
||||
IReference<uint8_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<UInt16>",
|
||||
IReference<uint16_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<UInt32>",
|
||||
IReference<uint32_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<UInt64>",
|
||||
IReference<uint64_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Single>",
|
||||
IReference<float>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Double>",
|
||||
IReference<double>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Char16>",
|
||||
IReference<char16_t>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Guid>",
|
||||
IReference<guid>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.HResult>",
|
||||
IReference<hresult>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<String>",
|
||||
IReference<hstring>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.EventRegistrationToken>",
|
||||
IReference<event_token>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.TimeSpan>",
|
||||
IReference<TimeSpan>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.DateTime>",
|
||||
IReference<DateTime>);
|
||||
#if __has_include(<windowsnumerics.impl.h>)
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Point>",
|
||||
IReference<Point>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Rect>",
|
||||
IReference<Rect>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Size>",
|
||||
IReference<Size>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Numerics.Vector2>",
|
||||
IReference<float2>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Numerics.Vector3>",
|
||||
IReference<float3>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Numerics.Vector4>",
|
||||
IReference<float4>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Numerics.Matrix3x2>",
|
||||
IReference<float3x2>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Numerics.Matrix4x4>",
|
||||
IReference<float4x4>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Numerics.Quaternion>",
|
||||
IReference<quaternion>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Numerics.Plane>",
|
||||
IReference<plane>);
|
||||
#endif
|
||||
|
||||
// Enums, structs, IInspectable, classes, and delegates
|
||||
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.PropertyType>",
|
||||
IReference<PropertyType>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1<Windows.Foundation.Point>",
|
||||
IReference<Point>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1<Object>",
|
||||
IVector<IInspectable>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1<Windows.Foundation.Uri>",
|
||||
IVector<Uri>);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1<Windows.Foundation.AsyncActionCompletedHandler>",
|
||||
IVector<AsyncActionCompletedHandler>);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "generic_types.h"
|
||||
|
||||
TEST_CASE("generic_types")
|
||||
{
|
||||
test_guids();
|
||||
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Uri", Uri);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.PropertyType", PropertyType);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.Point", Point);
|
||||
REQUIRE_EQUAL_NAME(L"Windows.Foundation.IStringable", IStringable);
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
#if __has_include(<windowsnumerics.impl.h>)
|
||||
using namespace Windows::Foundation::Numerics;
|
||||
#endif
|
||||
using namespace std::literals;
|
||||
|
||||
#define REQUIRE_EQUAL_GUID(left, ...) STATIC_REQUIRE(equal(guid(left), guid_of<__VA_ARGS__>()));
|
||||
#define REQUIRE_EQUAL_NAME(left, ...) STATIC_REQUIRE(left == name_of<__VA_ARGS__>());
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr bool equal(guid const& left, guid const& right) noexcept
|
||||
{
|
||||
return left.Data1 == right.Data1 &&
|
||||
left.Data2 == right.Data2 &&
|
||||
left.Data3 == right.Data3 &&
|
||||
left.Data4[0] == right.Data4[0] &&
|
||||
left.Data4[1] == right.Data4[1] &&
|
||||
left.Data4[2] == right.Data4[2] &&
|
||||
left.Data4[3] == right.Data4[3] &&
|
||||
left.Data4[4] == right.Data4[4] &&
|
||||
left.Data4[5] == right.Data4[5] &&
|
||||
left.Data4[6] == right.Data4[6] &&
|
||||
left.Data4[7] == right.Data4[7];
|
||||
}
|
||||
|
||||
void test_guids()
|
||||
{
|
||||
using A = IIterable<IStringable>;
|
||||
using B = IKeyValuePair<hstring, IAsyncOperationWithProgress<A, float>>;
|
||||
|
||||
REQUIRE_EQUAL_GUID("96369F54-8EB6-48F0-ABCE-C1B211E627C3"sv, IStringable);
|
||||
|
||||
//
|
||||
// Generated Windows.Foundation GUIDs
|
||||
//
|
||||
|
||||
REQUIRE_EQUAL_GUID("DD725452-2DA3-5103-9C7D-22EE9BB14AD3", IAsyncActionWithProgress<A>);
|
||||
REQUIRE_EQUAL_GUID("94645425-B9E5-5B91-B509-8DA4DF6A8916", IAsyncOperationWithProgress<A, B>);
|
||||
REQUIRE_EQUAL_GUID("2BD35EE6-72D9-5C5D-9827-05EBB81487AB", IAsyncOperation<A>);
|
||||
REQUIRE_EQUAL_GUID("4A33FE03-E8B9-5346-A124-5449913ECA57", IReferenceArray<A>);
|
||||
REQUIRE_EQUAL_GUID("F9E4006C-6E8C-56DF-811C-61F9990EBFB0", IReference<A>);
|
||||
REQUIRE_EQUAL_GUID("C261D8D0-71BA-5F38-A239-872342253A18", AsyncActionProgressHandler<A>);
|
||||
REQUIRE_EQUAL_GUID("9A0D211C-0374-5D23-9E15-EAA3570FAE63", AsyncActionWithProgressCompletedHandler<A>);
|
||||
REQUIRE_EQUAL_GUID("9D534225-231F-55E7-A6D0-6C938E2D9160", AsyncOperationCompletedHandler<A>);
|
||||
REQUIRE_EQUAL_GUID("264F1E0C-ABE4-590B-9D37-E1CC118ECC75", AsyncOperationProgressHandler<A, B>);
|
||||
REQUIRE_EQUAL_GUID("C2D078D8-AC47-55AB-83E8-123B2BE5BC5A", AsyncOperationWithProgressCompletedHandler<A, B>);
|
||||
REQUIRE_EQUAL_GUID("FA0B7D80-7EFA-52DF-9B69-0574CE57ADA4", EventHandler<A>);
|
||||
REQUIRE_EQUAL_GUID("EDB31843-B4CF-56EB-925A-D4D0CE97A08D", TypedEventHandler<A, B>);
|
||||
|
||||
//
|
||||
// Generated Windows.Foundation.Collections GUIDs
|
||||
//
|
||||
|
||||
REQUIRE_EQUAL_GUID("96565EB9-A692-59C8-BCB5-647CDE4E6C4D", IIterable<A>);
|
||||
REQUIRE_EQUAL_GUID("3C9B1E27-8357-590B-8828-6E917F172390", IIterator<A>);
|
||||
REQUIRE_EQUAL_GUID("89336CD9-8B66-50A7-9759-EB88CCB2E1FE", IKeyValuePair<A, B>);
|
||||
REQUIRE_EQUAL_GUID("E1AA5138-12BD-51A1-8558-698DFD070ABE", IMapChangedEventArgs<A>);
|
||||
REQUIRE_EQUAL_GUID("B78F0653-FA89-59CF-BA95-726938AAE666", IMapView<A, B>);
|
||||
REQUIRE_EQUAL_GUID("9962CD50-09D5-5C46-B1E1-3C679C1C8FAE", IMap<A, B>);
|
||||
REQUIRE_EQUAL_GUID("75F99E2A-137E-537E-A5B1-0B5A6245FC02", IObservableMap<A, B>);
|
||||
REQUIRE_EQUAL_GUID("D24C289F-2341-5128-AAA1-292DD0DC1950", IObservableVector<A>);
|
||||
REQUIRE_EQUAL_GUID("5F07498B-8E14-556E-9D2E-2E98D5615DA9", IVectorView<A>);
|
||||
REQUIRE_EQUAL_GUID("0E3F106F-A266-50A1-8043-C90FCF3844F6", IVector<A>);
|
||||
REQUIRE_EQUAL_GUID("19046F0B-CF81-5DEC-BBB2-7CC250DA8B8B", MapChangedEventHandler<A, B>);
|
||||
REQUIRE_EQUAL_GUID("A1E9ACD7-E4DF-5A79-AEFA-DE07934AB0FB", VectorChangedEventHandler<A>);
|
||||
|
||||
//
|
||||
// Generated primitive GUIDs
|
||||
//
|
||||
|
||||
REQUIRE_EQUAL_GUID("3C00FD60-2950-5939-A21A-2D12C5A01B8A", IReference<bool>);
|
||||
REQUIRE_EQUAL_GUID("95500129-FBF6-5AFC-89DF-70642D741990", IReference<int8_t>);
|
||||
REQUIRE_EQUAL_GUID("6EC9E41B-6709-5647-9918-A1270110FC4E", IReference<int16_t>);
|
||||
REQUIRE_EQUAL_GUID("548CEFBD-BC8A-5FA0-8DF2-957440FC8BF4", IReference<int32_t>);
|
||||
REQUIRE_EQUAL_GUID("4DDA9E24-E69F-5C6A-A0A6-93427365AF2A", IReference<int64_t>);
|
||||
REQUIRE_EQUAL_GUID("e5198cc8-2873-55f5-b0a1-84ff9e4aad62", IReference<uint8_t>);
|
||||
REQUIRE_EQUAL_GUID("5AB7D2C3-6B62-5E71-A4B6-2D49C4F238FD", IReference<uint16_t>);
|
||||
REQUIRE_EQUAL_GUID("513ef3af-e784-5325-a91e-97c2b8111cf3", IReference<uint32_t>);
|
||||
REQUIRE_EQUAL_GUID("6755e376-53bb-568b-a11d-17239868309e", IReference<uint64_t>);
|
||||
REQUIRE_EQUAL_GUID("719CC2BA-3E76-5DEF-9F1A-38D85A145EA8", IReference<float>);
|
||||
REQUIRE_EQUAL_GUID("2F2D6C29-5473-5F3E-92E7-96572BB990E2", IReference<double>);
|
||||
REQUIRE_EQUAL_GUID("FB393EF3-BBAC-5BD5-9144-84F23576F415", IReference<char16_t>);
|
||||
REQUIRE_EQUAL_GUID("7D50F649-632C-51F9-849A-EE49428933EA", IReference<guid>);
|
||||
REQUIRE_EQUAL_GUID("6FF27A1E-4B6A-59B7-B2C3-D1F2EE474593", IReference<hresult>);
|
||||
REQUIRE_EQUAL_GUID("FD416DFB-2A07-52EB-AAE3-DFCE14116C05", IReference<hstring>);
|
||||
REQUIRE_EQUAL_GUID("A9B18291-CE2A-5DAE-8A23-B7F7388416DB", IReference<event_token>);
|
||||
REQUIRE_EQUAL_GUID("604D0C4C-91DE-5C2A-935F-362F13EAF800", IReference<TimeSpan>);
|
||||
REQUIRE_EQUAL_GUID("5541D8A7-497C-5AA4-86FC-7713ADBF2A2C", IReference<DateTime>);
|
||||
REQUIRE_EQUAL_GUID("84F14C22-A00A-5272-8D3D-82112E66DF00", IReference<Point>);
|
||||
REQUIRE_EQUAL_GUID("80423F11-054F-5EAC-AFD3-63B6CE15E77B", IReference<Rect>);
|
||||
REQUIRE_EQUAL_GUID("61723086-8e53-5276-9f36-2a4bb93e2b75", IReference<Size>);
|
||||
#if __has_include(<windowsnumerics.impl.h>)
|
||||
REQUIRE_EQUAL_GUID("48F6A69E-8465-57AE-9400-9764087F65AD", IReference<float2>);
|
||||
REQUIRE_EQUAL_GUID("1EE770FF-C954-59CA-A754-6199A9BE282C", IReference<float3>);
|
||||
REQUIRE_EQUAL_GUID("A5E843C9-ED20-5339-8F8D-9FE404CF3654", IReference<float4>);
|
||||
REQUIRE_EQUAL_GUID("76358CFD-2CBD-525B-A49E-90EE18247B71", IReference<float3x2>);
|
||||
REQUIRE_EQUAL_GUID("DACBFFDC-68EF-5FD0-B657-782D0AC9807E", IReference<float4x4>);
|
||||
REQUIRE_EQUAL_GUID("B27004BB-C014-5DCE-9A21-799C5A3C1461", IReference<quaternion>);
|
||||
REQUIRE_EQUAL_GUID("46D542A1-52F7-58E7-ACFC-9A6D364DA022", IReference<plane>);
|
||||
#endif
|
||||
|
||||
// Enums, structs, IInspectable, classes, and delegates
|
||||
|
||||
REQUIRE_EQUAL_GUID("ECEBDE54-FAC0-5AEB-9BA9-9E1FE17E31D5", IReference<PropertyType>);
|
||||
REQUIRE_EQUAL_GUID("84F14C22-A00A-5272-8D3D-82112E66DF00", IReference<Point>);
|
||||
REQUIRE_EQUAL_GUID("B32BDCA4-5E52-5B27-BC5D-D66A1A268C2A", IVector<IInspectable>);
|
||||
REQUIRE_EQUAL_GUID("0D82BD8D-FE62-5D67-A7B9-7886DD75BC4E", IVector<Uri>);
|
||||
REQUIRE_EQUAL_GUID("5DAFE591-86DC-59AA-BFDA-07F5D59FC708", IVector<AsyncActionCompletedHandler>);
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
TEST_CASE("guid_key")
|
||||
{
|
||||
auto uri = guid_of<Uri>();
|
||||
auto deferral = guid_of<Deferral>();
|
||||
|
||||
std::map<guid, std::string> ordered;
|
||||
ordered[uri] = "Uri";
|
||||
ordered[deferral] = "Deferral";
|
||||
REQUIRE(ordered[uri] == "Uri");
|
||||
REQUIRE(ordered[deferral] == "Deferral");
|
||||
|
||||
std::unordered_map<guid, std::string> unordered;
|
||||
unordered[uri] = "Uri";
|
||||
unordered[deferral] = "Deferral";
|
||||
REQUIRE(unordered[uri] == "Uri");
|
||||
REQUIRE(unordered[deferral] == "Deferral");
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include <windows.foundation.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Stringable : winrt::implements<Stringable, winrt::Windows::Foundation::IStringable>
|
||||
{
|
||||
winrt::hstring ToString()
|
||||
{
|
||||
return L"hello";
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT GetStringable(GUID const& id, void** object) noexcept
|
||||
{
|
||||
*object = nullptr;
|
||||
|
||||
if (id != __uuidof(ABI::Windows::Foundation::IStringable))
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
*object = winrt::detach_abi(winrt::make<Stringable>());
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("iid_ppv_args")
|
||||
{
|
||||
{
|
||||
winrt::com_ptr<ABI::Windows::Foundation::IStringable> ptr;
|
||||
REQUIRE(S_OK == GetStringable(IID_PPV_ARGS(&ptr)));
|
||||
REQUIRE(ptr.as<winrt::Windows::Foundation::IStringable>().ToString() == L"hello");
|
||||
}
|
||||
{
|
||||
winrt::com_ptr<ABI::Windows::Foundation::IClosable> ptr;
|
||||
REQUIRE(E_NOINTERFACE == GetStringable(IID_PPV_ARGS(&ptr)));
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace test_component;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Value : implements<Value, IStringable>
|
||||
{
|
||||
Value(int32_t value) :
|
||||
m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return hstring{ std::to_wstring(m_value) };
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int32_t m_value{};
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("in_params")
|
||||
{
|
||||
Class object;
|
||||
|
||||
REQUIRE(object.InInt32(123) == L"123");
|
||||
REQUIRE(object.InString(L"123") == L"123");
|
||||
REQUIRE(object.InObject(make<Value>(123)) == L"123");
|
||||
REQUIRE(object.InStringable(make<Value>(123)) == L"123");
|
||||
REQUIRE(object.InStruct({ L"1", L"2" }) == L"12");
|
||||
REQUIRE(object.InStructRef({ L"1", L"2" }) == L"12ref");
|
||||
REQUIRE(object.InEnum(Signed::First) == L"First");
|
||||
|
||||
REQUIRE(object.InInt32Array({ 1,2 }) == L"12");
|
||||
REQUIRE(object.InStringArray({ L"1", L"2" }) == L"12");
|
||||
REQUIRE(object.InObjectArray({ make<Value>(1), make<Value>(2) }) == L"12");
|
||||
REQUIRE(object.InStringableArray({ make<Value>(1), make<Value>(2) }) == L"12");
|
||||
REQUIRE(object.InStructArray({ {L"1",L"2"}, {L"3",L"4"} }) == L"1234");
|
||||
REQUIRE(object.InEnumArray({ Signed::First, Signed::Second }) == L"FirstSecond");
|
||||
|
||||
// Ensure 0-length arrays are passed as non-null pointers to the ABI,
|
||||
// in order to keep RPC happy.
|
||||
REQUIRE(object.InInt32Array({ }) == L"");
|
||||
REQUIRE(object.InStringArray({ }) == L"");
|
||||
REQUIRE(object.InObjectArray({ }) == L"");
|
||||
REQUIRE(object.InStringableArray({ }) == L"");
|
||||
REQUIRE(object.InStructArray({ }) == L"");
|
||||
REQUIRE(object.InEnumArray({ }) == L"");
|
||||
|
||||
// params::hstring optimizations
|
||||
REQUIRE(object.InString(L"") == L"");
|
||||
REQUIRE(object.InString({}) == L"");
|
||||
wchar_t non_const_string[1] = { L'\0' };
|
||||
REQUIRE(object.InString(non_const_string) == L"");
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
#include <inspectable.h>
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
using namespace winrt;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct DECLSPEC_UUID("ed0dd761-c31e-4803-8cf9-22a2cb20ec47") IBadInterop : ::IInspectable
|
||||
{
|
||||
virtual int32_t __stdcall JustSayNo() noexcept = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef __CRT_UUID_DECL
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
__CRT_UUID_DECL(IBadInterop, 0xed0dd761, 0xc31e, 0x4803, 0x8c, 0xf9, 0x22, 0xa2, 0xcb, 0x20, 0xec, 0x47)
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Sample : implements<Sample, Windows::Foundation::IActivationFactory, IBadInterop>
|
||||
{
|
||||
Windows::Foundation::IInspectable ActivateInstance()
|
||||
{
|
||||
throw hresult_not_implemented();
|
||||
}
|
||||
|
||||
hstring GetRuntimeClassName() const
|
||||
{
|
||||
return L"Sample";
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
|
||||
#endif
|
||||
Windows::Foundation::TrustLevel GetTrustLevel() const noexcept
|
||||
{
|
||||
return Windows::Foundation::TrustLevel::PartialTrust;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
int32_t __stdcall JustSayNo() noexcept final
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("inspectable_interop")
|
||||
{
|
||||
Windows::Foundation::IActivationFactory a = make<Sample>();
|
||||
REQUIRE(a != nullptr);
|
||||
|
||||
Windows::Foundation::IActivationFactory b = a.as<Windows::Foundation::IActivationFactory>();
|
||||
REQUIRE(b != nullptr);
|
||||
|
||||
com_ptr<IBadInterop> c = a.as<IBadInterop>();
|
||||
REQUIRE(c != nullptr);
|
||||
REQUIRE(c->JustSayNo() == 123);
|
||||
|
||||
Windows::Foundation::IActivationFactory d = c.as<Windows::Foundation::IActivationFactory>();
|
||||
REQUIRE(a == d);
|
||||
|
||||
Windows::Foundation::IInspectable f = c.as<Windows::Foundation::IInspectable>();
|
||||
REQUIRE(f != nullptr);
|
||||
|
||||
Windows::Foundation::IInspectable e(c.detach(), take_ownership_from_abi);
|
||||
|
||||
REQUIRE(winrt::get_class_name(e) == L"Sample");
|
||||
REQUIRE(winrt::get_trust_level(e) == Windows::Foundation::TrustLevel::PartialTrust);
|
||||
|
||||
auto interfaces = winrt::get_interfaces(e);
|
||||
REQUIRE(interfaces.size() == 1);
|
||||
REQUIRE(interfaces[0] == guid_of<Windows::Foundation::IActivationFactory>());
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include <inspectable.h>
|
||||
|
||||
struct DECLSPEC_UUID("5040a5f4-796a-42ff-9f06-be89137a518f") IBase : IUnknown
|
||||
{
|
||||
};
|
||||
|
||||
struct DECLSPEC_UUID("529fed32-514f-4150-b1ba-15b47df700b7") IDerived : IBase
|
||||
{
|
||||
};
|
||||
|
||||
struct DECLSPEC_UUID("b81fb2a2-eab4-488a-96a7-434873c2c20b") IMoreDerived : IDerived
|
||||
{
|
||||
};
|
||||
|
||||
#ifdef __CRT_UUID_DECL
|
||||
__CRT_UUID_DECL(IBase, 0x5040a5f4, 0x796a, 0x42ff, 0x9f, 0x06, 0xbe, 0x89, 0x13, 0x7a, 0x51, 0x8f)
|
||||
__CRT_UUID_DECL(IDerived, 0x529fed32, 0x514f, 0x4150, 0xb1, 0xba, 0x15, 0xb4, 0x7d, 0xf7, 0x00, 0xb7)
|
||||
__CRT_UUID_DECL(IMoreDerived, 0xb81fb2a2, 0xeab4, 0x488a, 0x96, 0xa7, 0x43, 0x48, 0x73, 0xc2, 0xc2, 0x0b)
|
||||
#endif
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
template<> bool is_guid_of<IDerived>(guid const& id) noexcept
|
||||
{
|
||||
return is_guid_of<IDerived, IBase>(id);
|
||||
}
|
||||
|
||||
template<> bool is_guid_of<IMoreDerived>(guid const& id) noexcept
|
||||
{
|
||||
return is_guid_of<IMoreDerived, IDerived, IBase>(id);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace winrt;
|
||||
|
||||
struct MyBase : implements<MyBase, IBase>
|
||||
{
|
||||
};
|
||||
|
||||
struct MyDerived : implements<MyDerived, IDerived>
|
||||
{
|
||||
};
|
||||
|
||||
struct MyMoreDerived : implements<MyMoreDerived, IMoreDerived, Windows::Foundation::IInspectable>
|
||||
{
|
||||
};
|
||||
|
||||
Windows::Foundation::IAsyncAction Async()
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
TEST_CASE("interop")
|
||||
{
|
||||
{
|
||||
Windows::Foundation::IAsyncAction a = Async();
|
||||
com_ptr<::IInspectable> b = a.as<::IInspectable>();
|
||||
Windows::Foundation::IAsyncAction c = b.as<Windows::Foundation::IAsyncAction>();
|
||||
REQUIRE(a == c);
|
||||
}
|
||||
{
|
||||
com_ptr<IBase> a = make<MyBase>();
|
||||
REQUIRE(a);
|
||||
REQUIRE(a.try_as<IBase>() != nullptr);
|
||||
REQUIRE(a.try_as<IDerived>() == nullptr);
|
||||
REQUIRE(a.try_as<IMoreDerived>() == nullptr);
|
||||
REQUIRE(a.try_as<::IInspectable>() == nullptr);
|
||||
}
|
||||
{
|
||||
com_ptr<IDerived> a = make<MyDerived>();
|
||||
REQUIRE(a);
|
||||
REQUIRE(a.try_as<IBase>() != nullptr);
|
||||
REQUIRE(a.try_as<IDerived>() != nullptr);
|
||||
REQUIRE(a.try_as<IMoreDerived>() == nullptr);
|
||||
REQUIRE(a.try_as<::IInspectable>() == nullptr);
|
||||
}
|
||||
{
|
||||
com_ptr<IMoreDerived> a = make<MyMoreDerived>();
|
||||
REQUIRE(a);
|
||||
REQUIRE(a.try_as<IBase>() != nullptr);
|
||||
REQUIRE(a.try_as<IDerived>() != nullptr);
|
||||
REQUIRE(a.try_as<IMoreDerived>() != nullptr);
|
||||
REQUIRE(a.try_as<::IInspectable>() != nullptr);
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
//
|
||||
// Checks that invalid tokens may be removed harmlessly.
|
||||
//
|
||||
|
||||
TEST_CASE("invalid_events")
|
||||
{
|
||||
event<TypedEventHandler<int, int>> event;
|
||||
int counter{};
|
||||
|
||||
auto a = event.add([&](auto && ...)
|
||||
{
|
||||
counter += 1;
|
||||
});
|
||||
|
||||
auto b = event.add([&](auto && ...)
|
||||
{
|
||||
counter += 10;
|
||||
});
|
||||
|
||||
REQUIRE(counter == 0);
|
||||
event(0, 0);
|
||||
REQUIRE(counter == 11);
|
||||
|
||||
// Remove invalid token (with two valids)
|
||||
event.remove(event_token {1});
|
||||
|
||||
counter = 0;
|
||||
event(0, 0);
|
||||
REQUIRE(counter == 11);
|
||||
|
||||
// Remove valid token
|
||||
event.remove(b);
|
||||
|
||||
counter = 0;
|
||||
event(0, 0);
|
||||
REQUIRE(counter == 1);
|
||||
|
||||
// Remove invalid token (with one valid)
|
||||
event.remove(event_token {1});
|
||||
|
||||
counter = 0;
|
||||
event(0, 0);
|
||||
REQUIRE(counter == 1);
|
||||
|
||||
// Remove remaining valid token
|
||||
event.remove(a);
|
||||
|
||||
counter = 0;
|
||||
event(0, 0);
|
||||
REQUIRE(counter == 0);
|
||||
|
||||
// Remove invalid token (with no valids)
|
||||
event.remove(event_token {1});
|
||||
|
||||
counter = 0;
|
||||
event(0, 0);
|
||||
REQUIRE(counter == 0);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#include <crtdbg.h>
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
|
||||
// Force reportFatal to be available on mingw-w64
|
||||
#define CATCH_CONFIG_WINDOWS_SEH
|
||||
|
||||
#include "catch.hpp"
|
||||
#include "winrt/base.h"
|
||||
|
||||
using namespace winrt;
|
||||
|
||||
int main(int const argc, char** argv)
|
||||
{
|
||||
init_apartment();
|
||||
std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); });
|
||||
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
|
||||
(void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
|
||||
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
|
||||
(void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
||||
return Catch::Session().run(argc, argv);
|
||||
}
|
||||
|
||||
CATCH_TRANSLATE_EXCEPTION(hresult_error const& e)
|
||||
{
|
||||
return to_string(e.message());
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
|
||||
// The default behavior (no macro) provides the static winrt::get_module_lock implementation for components/DLLs.
|
||||
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Stringable : winrt::implements<Stringable, winrt::Windows::Foundation::IStringable>
|
||||
{
|
||||
winrt::hstring ToString()
|
||||
{
|
||||
return L"Stringable";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("module_lock_dll")
|
||||
{
|
||||
uint32_t const count = winrt::get_module_lock();
|
||||
|
||||
++winrt::get_module_lock();
|
||||
|
||||
REQUIRE(winrt::get_module_lock() == count + 1);
|
||||
|
||||
--winrt::get_module_lock();
|
||||
|
||||
REQUIRE(winrt::get_module_lock() == count);
|
||||
|
||||
{
|
||||
auto stringable = winrt::make<Stringable>();
|
||||
REQUIRE(winrt::get_module_lock() == count + 1);
|
||||
}
|
||||
|
||||
REQUIRE(winrt::get_module_lock() == count);
|
||||
|
||||
{
|
||||
winrt::Windows::Foundation::EventHandler<int> delegate = [](auto&&...) {};
|
||||
REQUIRE(winrt::get_module_lock() == count + 1);
|
||||
}
|
||||
|
||||
REQUIRE(winrt::get_module_lock() == count);
|
||||
|
||||
{
|
||||
winrt::delegate<void()> delegate = [] {};
|
||||
REQUIRE(winrt::get_module_lock() == count + 1);
|
||||
}
|
||||
|
||||
REQUIRE(winrt::get_module_lock() == count);
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
void check_terminated(winrt::param::hstring const&)
|
||||
{
|
||||
}
|
||||
|
||||
TEST_CASE("names")
|
||||
{
|
||||
REQUIRE(name_of<Windows::Foundation::IUnknown>() == L"{00000000-0000-0000-c000-000000000046}"sv);
|
||||
STATIC_REQUIRE(name_of<IInspectable>() == L"Object"sv);
|
||||
|
||||
check_terminated(name_of<Windows::Foundation::IUnknown>());
|
||||
check_terminated(name_of<IInspectable>());
|
||||
check_terminated(name_of<EventHandler<guid>>());
|
||||
check_terminated(name_of<TypedEventHandler<guid, Point>>());
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace test_component;
|
||||
|
||||
TEST_CASE("no_make_detection")
|
||||
{
|
||||
REQUIRE(test_component::Class::TestNoMakeDetection());
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace test_component;
|
||||
|
||||
TEST_CASE("noexcept")
|
||||
{
|
||||
Class c;
|
||||
|
||||
c.NoexceptVoid();
|
||||
int32_t a = c.NoexceptInt32();
|
||||
hstring b = c.NoexceptString();
|
||||
|
||||
REQUIRE(a == 123);
|
||||
REQUIRE(b == L"123");
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation::Numerics;
|
||||
|
||||
TEST_CASE("numerics")
|
||||
{
|
||||
#if __has_include(<windowsnumerics.impl.h>)
|
||||
// Basic smoke test exercising SIMD intrinsics used by numerics.
|
||||
|
||||
auto one = float4::one();
|
||||
|
||||
REQUIRE(one * one == one);
|
||||
#endif
|
||||
}
|
|
@ -1,278 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace test_component;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Stringable : implements<Stringable, IStringable>
|
||||
{
|
||||
hstring ToString()
|
||||
{
|
||||
return L"Stringable";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("out_params")
|
||||
{
|
||||
Class object;
|
||||
|
||||
{
|
||||
int value;
|
||||
object.OutInt32(value);
|
||||
REQUIRE(value == 123);
|
||||
}
|
||||
{
|
||||
hstring value = L"replace";
|
||||
object.OutString(value);
|
||||
REQUIRE(value == L"123");
|
||||
}
|
||||
{
|
||||
IInspectable value = make<Stringable>();
|
||||
object.OutObject(value);
|
||||
REQUIRE(value.as<IStringable>().ToString() == L"123");
|
||||
}
|
||||
{
|
||||
IStringable value = make<Stringable>();
|
||||
object.OutStringable(value);
|
||||
REQUIRE(value.ToString() == L"123");
|
||||
}
|
||||
{
|
||||
Struct value{ L"First", L"Second" };
|
||||
object.OutStruct(value);
|
||||
REQUIRE(value.First == L"1");
|
||||
REQUIRE(value.Second == L"2");
|
||||
}
|
||||
{
|
||||
Signed value;
|
||||
object.OutEnum(value);
|
||||
REQUIRE(value == Signed::First);
|
||||
}
|
||||
|
||||
{
|
||||
com_array<int32_t> value(10);
|
||||
object.OutInt32Array(value);
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0] == 1);
|
||||
REQUIRE(value[1] == 2);
|
||||
REQUIRE(value[2] == 3);
|
||||
}
|
||||
{
|
||||
com_array<hstring> value(10);
|
||||
object.OutStringArray(value);
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0] == L"1");
|
||||
REQUIRE(value[1] == L"2");
|
||||
REQUIRE(value[2] == L"3");
|
||||
}
|
||||
{
|
||||
com_array<IInspectable> value(10);
|
||||
object.OutObjectArray(value);
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0].as<IStringable>().ToString() == L"1");
|
||||
REQUIRE(value[1].as<IStringable>().ToString() == L"2");
|
||||
REQUIRE(value[2].as<IStringable>().ToString() == L"3");
|
||||
}
|
||||
{
|
||||
com_array<IStringable> value(10);
|
||||
object.OutStringableArray(value);
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0].ToString() == L"1");
|
||||
REQUIRE(value[1].ToString() == L"2");
|
||||
REQUIRE(value[2].ToString() == L"3");
|
||||
}
|
||||
{
|
||||
com_array<Struct> value(10);
|
||||
object.OutStructArray(value);
|
||||
REQUIRE(value.size() == 2);
|
||||
REQUIRE(value[0].First == L"1");
|
||||
REQUIRE(value[0].Second == L"2");
|
||||
REQUIRE(value[1].First == L"10");
|
||||
REQUIRE(value[1].Second == L"20");
|
||||
}
|
||||
{
|
||||
com_array<Signed> value(10);
|
||||
object.OutEnumArray(value);
|
||||
REQUIRE(value.size() == 2);
|
||||
REQUIRE(value[0] == Signed::First);
|
||||
REQUIRE(value[1] == Signed::Second);
|
||||
}
|
||||
|
||||
{
|
||||
std::array<int32_t, 4> value{ 0xCC, 0xCC, 0xCC, 0xCC };
|
||||
object.RefInt32Array(value);
|
||||
REQUIRE(value[0] == 1);
|
||||
REQUIRE(value[1] == 2);
|
||||
REQUIRE(value[2] == 3);
|
||||
REQUIRE(value[3] == 0xCC);
|
||||
}
|
||||
{
|
||||
std::array<hstring, 4> value{ L"r1", L"r2", L"r3", L"r4" };
|
||||
object.RefStringArray(value);
|
||||
REQUIRE(value[0] == L"1");
|
||||
REQUIRE(value[1] == L"2");
|
||||
REQUIRE(value[2] == L"3");
|
||||
REQUIRE(value[3] == L"");
|
||||
}
|
||||
{
|
||||
std::array<IInspectable, 4> value{ make<Stringable>(), make<Stringable>(), make<Stringable>(), make<Stringable>() };
|
||||
object.RefObjectArray(value);
|
||||
REQUIRE(value[0].as<IStringable>().ToString() == L"1");
|
||||
REQUIRE(value[1].as<IStringable>().ToString() == L"2");
|
||||
REQUIRE(value[2].as<IStringable>().ToString() == L"3");
|
||||
REQUIRE(value[3] == nullptr);
|
||||
}
|
||||
{
|
||||
std::array<IStringable, 4> value{ make<Stringable>(), make<Stringable>(), make<Stringable>(), make<Stringable>() };
|
||||
object.RefStringableArray(value);
|
||||
REQUIRE(value[0].ToString() == L"1");
|
||||
REQUIRE(value[1].ToString() == L"2");
|
||||
REQUIRE(value[2].ToString() == L"3");
|
||||
REQUIRE(value[3] == nullptr);
|
||||
}
|
||||
{
|
||||
std::array<Struct, 3> value{ {L"First", L"Second"} };
|
||||
object.RefStructArray(value);
|
||||
REQUIRE(value[0].First == L"1");
|
||||
REQUIRE(value[0].Second == L"2");
|
||||
REQUIRE(value[1].First == L"3");
|
||||
REQUIRE(value[1].Second == L"4");
|
||||
REQUIRE(value[2].First == L"");
|
||||
REQUIRE(value[2].Second == L"");
|
||||
}
|
||||
{
|
||||
std::array<Signed, 3> value{};
|
||||
object.RefEnumArray(value);
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0] == Signed::First);
|
||||
REQUIRE(value[1] == Signed::Second);
|
||||
REQUIRE(value[2] == static_cast<Signed>(0));
|
||||
}
|
||||
// Ensure 0-length arrays are passed as non-null pointers to the ABI,
|
||||
// in order to keep RPC happy.
|
||||
{
|
||||
REQUIRE_NOTHROW(object.RefInt32Array({}));
|
||||
REQUIRE_NOTHROW(object.RefStringArray({}));
|
||||
REQUIRE_NOTHROW(object.RefObjectArray({}));
|
||||
REQUIRE_NOTHROW(object.RefStringableArray({}));
|
||||
REQUIRE_NOTHROW(object.RefStructArray({}));
|
||||
REQUIRE_NOTHROW(object.RefEnumArray({}));
|
||||
}
|
||||
|
||||
object.Fail(true);
|
||||
|
||||
{
|
||||
int value = 0xCC;
|
||||
REQUIRE_THROWS_AS(object.OutInt32(value), hresult_invalid_argument);
|
||||
REQUIRE(value == 0xCC);
|
||||
}
|
||||
{
|
||||
hstring value = L"replace";
|
||||
REQUIRE_THROWS_AS(object.OutString(value), hresult_invalid_argument);
|
||||
REQUIRE(value == L"");
|
||||
}
|
||||
{
|
||||
IInspectable value = make<Stringable>();
|
||||
REQUIRE_THROWS_AS(object.OutObject(value), hresult_invalid_argument);
|
||||
REQUIRE(value == nullptr);
|
||||
}
|
||||
{
|
||||
IStringable value = make<Stringable>();
|
||||
REQUIRE_THROWS_AS(object.OutStringable(value), hresult_invalid_argument);
|
||||
REQUIRE(value == nullptr);
|
||||
}
|
||||
{
|
||||
Struct value{ L"First", L"Second" };
|
||||
REQUIRE_THROWS_AS(object.OutStruct(value), hresult_invalid_argument);
|
||||
REQUIRE(value.First == L"");
|
||||
REQUIRE(value.Second == L"");
|
||||
}
|
||||
{
|
||||
Signed value = static_cast<Signed>(0xCC);
|
||||
REQUIRE_THROWS_AS(object.OutEnum(value), hresult_invalid_argument);
|
||||
REQUIRE(static_cast<int32_t>(value) == 0xCC);
|
||||
}
|
||||
|
||||
{
|
||||
com_array<int32_t> value(10);
|
||||
REQUIRE_THROWS_AS(object.OutInt32Array(value), hresult_invalid_argument);
|
||||
REQUIRE(value.size() == 0);
|
||||
}
|
||||
{
|
||||
com_array<hstring> value(10);
|
||||
REQUIRE_THROWS_AS(object.OutStringArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value.size() == 0);
|
||||
}
|
||||
{
|
||||
com_array<IInspectable> value(10);
|
||||
REQUIRE_THROWS_AS(object.OutObjectArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value.size() == 0);
|
||||
}
|
||||
{
|
||||
com_array<IStringable> value(10);
|
||||
REQUIRE_THROWS_AS(object.OutStringableArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value.size() == 0);
|
||||
}
|
||||
{
|
||||
com_array<Struct> value(10);
|
||||
REQUIRE_THROWS_AS(object.OutStructArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value.size() == 0);
|
||||
}
|
||||
{
|
||||
com_array<Signed> value(10);
|
||||
REQUIRE_THROWS_AS(object.OutEnumArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value.size() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
std::array<int32_t, 4> value{ 0xCC, 0xCC, 0xCC, 0xCC };
|
||||
REQUIRE_THROWS_AS(object.RefInt32Array(value), hresult_invalid_argument);
|
||||
REQUIRE(value[0] == 0xCC);
|
||||
REQUIRE(value[1] == 0xCC);
|
||||
REQUIRE(value[2] == 0xCC);
|
||||
REQUIRE(value[3] == 0xCC);
|
||||
}
|
||||
{
|
||||
std::array<hstring, 4> value{ L"r1", L"r2", L"r3", L"r4" };
|
||||
REQUIRE_THROWS_AS(object.RefStringArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value[0] == L"");
|
||||
REQUIRE(value[1] == L"");
|
||||
REQUIRE(value[2] == L"");
|
||||
REQUIRE(value[3] == L"");
|
||||
}
|
||||
{
|
||||
std::array<IInspectable, 4> value{ make<Stringable>(), make<Stringable>(), make<Stringable>(), make<Stringable>() };
|
||||
REQUIRE_THROWS_AS(object.RefObjectArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value[0] == nullptr);
|
||||
REQUIRE(value[1] == nullptr);
|
||||
REQUIRE(value[2] == nullptr);
|
||||
REQUIRE(value[3] == nullptr);
|
||||
}
|
||||
{
|
||||
std::array<IStringable, 4> value{ make<Stringable>(), make<Stringable>(), make<Stringable>(), make<Stringable>() };
|
||||
REQUIRE_THROWS_AS(object.RefStringableArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value[0] == nullptr);
|
||||
REQUIRE(value[1] == nullptr);
|
||||
REQUIRE(value[2] == nullptr);
|
||||
REQUIRE(value[3] == nullptr);
|
||||
}
|
||||
{
|
||||
std::array<Struct, 3> value{ {L"First", L"Second"} };
|
||||
REQUIRE_THROWS_AS(object.RefStructArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value[0].First == L"");
|
||||
REQUIRE(value[0].Second == L"");
|
||||
REQUIRE(value[1].First == L"");
|
||||
REQUIRE(value[1].Second == L"");
|
||||
REQUIRE(value[2].First == L"");
|
||||
REQUIRE(value[2].Second == L"");
|
||||
}
|
||||
{
|
||||
std::array<Signed, 2> value{ static_cast<Signed>(0xCC), static_cast<Signed>(0xCC) };
|
||||
REQUIRE_THROWS_AS(object.RefEnumArray(value), hresult_invalid_argument);
|
||||
REQUIRE(value[0] == static_cast<Signed>(0xCC));
|
||||
REQUIRE(value[1] == static_cast<Signed>(0xCC));
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.Parent.One.Two.Three.h"
|
||||
|
||||
using namespace winrt::test_component;
|
||||
|
||||
TEST_CASE("parent_includes")
|
||||
{
|
||||
// Including "...Three.h" should include all (available) ancestors, skipping
|
||||
// any that are empty. In this case, "Three" and "Parent" are not empty while
|
||||
// the intermediate namespaces are empty.
|
||||
|
||||
Parent::One::Two::Three::ThreeStruct three;
|
||||
three.Value = 0;
|
||||
|
||||
Parent::ParentStruct parent;
|
||||
parent.Value = 0;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
#include "pch.h"
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "mingw_com_support.h"
|
||||
|
||||
#define WINRT_LEAN_AND_MEAN
|
||||
#include <unknwn.h>
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "winrt/Windows.Foundation.Numerics.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
// Extracts return and progress types from IAsyncXxx.
|
||||
|
||||
template<typename T>
|
||||
struct async_traits;
|
||||
|
||||
template<>
|
||||
struct async_traits<winrt::Windows::Foundation::IAsyncAction>
|
||||
{
|
||||
using progress_type = void;
|
||||
};
|
||||
|
||||
template<typename P>
|
||||
struct async_traits<winrt::Windows::Foundation::IAsyncActionWithProgress<P>>
|
||||
{
|
||||
using progress_type = P;
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
struct async_traits<winrt::Windows::Foundation::IAsyncOperation<R>>
|
||||
{
|
||||
using progress_type = void;
|
||||
};
|
||||
|
||||
template<typename R, typename P>
|
||||
struct async_traits<winrt::Windows::Foundation::IAsyncOperationWithProgress<R, P>>
|
||||
{
|
||||
using progress_type = P;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using async_return_type = decltype(std::declval<T>().GetResults());
|
||||
template<typename T>
|
||||
using async_progress_type = typename async_traits<std::decay_t<T>>::progress_type;
|
||||
template<typename T>
|
||||
inline constexpr bool has_async_progress = !std::is_same_v<void, typename async_traits<std::decay_t<T>>::progress_type>;
|
|
@ -1,80 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace test_component;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Stringable : implements<Stringable, IStringable>
|
||||
{
|
||||
hstring ToString()
|
||||
{
|
||||
return L"Stringable";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("return_params")
|
||||
{
|
||||
Class object;
|
||||
|
||||
{
|
||||
int value = object.ReturnInt32();
|
||||
REQUIRE(value == 123);
|
||||
}
|
||||
{
|
||||
hstring value = object.ReturnString();
|
||||
REQUIRE(value == L"123");
|
||||
}
|
||||
{
|
||||
IInspectable value = object.ReturnObject();
|
||||
REQUIRE(value.as<IStringable>().ToString() == L"123");
|
||||
}
|
||||
{
|
||||
IStringable value = object.ReturnStringable();
|
||||
REQUIRE(value.ToString() == L"123");
|
||||
}
|
||||
{
|
||||
Struct value = object.ReturnStruct();
|
||||
REQUIRE(value.First == L"1");
|
||||
REQUIRE(value.Second == L"2");
|
||||
}
|
||||
{
|
||||
com_array<int32_t> value = object.ReturnInt32Array();
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0] == 1);
|
||||
REQUIRE(value[1] == 2);
|
||||
REQUIRE(value[2] == 3);
|
||||
}
|
||||
{
|
||||
com_array<hstring> value = object.ReturnStringArray();
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0] == L"1");
|
||||
REQUIRE(value[1] == L"2");
|
||||
REQUIRE(value[2] == L"3");
|
||||
}
|
||||
{
|
||||
com_array<IInspectable> value = object.ReturnObjectArray();
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0].as<IStringable>().ToString() == L"1");
|
||||
REQUIRE(value[1].as<IStringable>().ToString() == L"2");
|
||||
REQUIRE(value[2].as<IStringable>().ToString() == L"3");
|
||||
}
|
||||
{
|
||||
com_array<IStringable> value = object.ReturnStringableArray();
|
||||
REQUIRE(value.size() == 3);
|
||||
REQUIRE(value[0].ToString() == L"1");
|
||||
REQUIRE(value[1].ToString() == L"2");
|
||||
REQUIRE(value[2].ToString() == L"3");
|
||||
}
|
||||
{
|
||||
com_array<Struct> value = object.ReturnStructArray();
|
||||
REQUIRE(value.size() == 2);
|
||||
REQUIRE(value[0].First == L"1");
|
||||
REQUIRE(value[0].Second == L"2");
|
||||
REQUIRE(value[1].First == L"10");
|
||||
REQUIRE(value[1].Second == L"20");
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.Structs.Nested.h"
|
||||
#include "winrt/test_component_no_pch.Peer2.h"
|
||||
|
||||
using namespace winrt;
|
||||
|
||||
TEST_CASE("structs")
|
||||
{
|
||||
test_component::Structs::Nested::Outer outer{};
|
||||
outer.Depends.InnerValue = 1;
|
||||
outer.OuterValue = 2;
|
||||
|
||||
test_component_no_pch::Peer2::B depends{};
|
||||
depends.First.Value = 1;
|
||||
|
||||
test_component::Structs::All all{};
|
||||
all.H = {};
|
||||
}
|
|
@ -1,363 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{2EF696B9-7F4A-410F-AE5C-5301565C0F08}</ProjectGuid>
|
||||
<RootNamespace>unittests</RootNamespace>
|
||||
<ProjectName>test_win7</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(OutputPath);Generated Files;..;..\..\cppwinrt</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="generic_types.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="abi_guard.cpp" />
|
||||
<ClCompile Include="agile_ref.cpp" />
|
||||
<ClCompile Include="agility.cpp" />
|
||||
<ClCompile Include="async_auto_cancel.cpp" />
|
||||
<ClCompile Include="async_cancel_callback.cpp" />
|
||||
<ClCompile Include="async_check_cancel.cpp" />
|
||||
<ClCompile Include="async_local.cpp" />
|
||||
<ClCompile Include="async_no_suspend.cpp" />
|
||||
<ClCompile Include="async_progress.cpp" />
|
||||
<ClCompile Include="async_result.cpp" />
|
||||
<ClCompile Include="async_return.cpp" />
|
||||
<ClCompile Include="async_suspend.cpp" />
|
||||
<ClCompile Include="async_throw.cpp" />
|
||||
<ClCompile Include="async_wait_for.cpp" />
|
||||
<ClCompile Include="capture.cpp" />
|
||||
<ClCompile Include="cmd_reader.cpp" />
|
||||
<ClCompile Include="coro_foundation.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coro_threadpool.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="custom_error.cpp" />
|
||||
<ClCompile Include="delegate.cpp" />
|
||||
<ClCompile Include="delegates.cpp" />
|
||||
<ClCompile Include="disconnected.cpp" />
|
||||
<ClCompile Include="enum.cpp" />
|
||||
<ClCompile Include="fast_iterator.cpp" />
|
||||
<ClCompile Include="final_release.cpp" />
|
||||
<ClCompile Include="generic_types.cpp" />
|
||||
<ClCompile Include="generic_type_names.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GetMany.cpp" />
|
||||
<ClCompile Include="guid_key.cpp" />
|
||||
<ClCompile Include="iid_ppv_args.cpp" />
|
||||
<ClCompile Include="inspectable_interop.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="interop.cpp" />
|
||||
<ClCompile Include="invalid_events.cpp" />
|
||||
<ClCompile Include="in_params.cpp" />
|
||||
<ClCompile Include="main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="module_lock_dll.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="names.cpp" />
|
||||
<ClCompile Include="noexcept.cpp" />
|
||||
<ClCompile Include="no_make_detection.cpp" />
|
||||
<ClCompile Include="numerics.cpp" />
|
||||
<ClCompile Include="out_params.cpp" />
|
||||
<ClCompile Include="parent_includes.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="return_params.cpp" />
|
||||
<ClCompile Include="structs.cpp" />
|
||||
<ClCompile Include="thread_pool.cpp" />
|
||||
<ClCompile Include="uniform_in_params.cpp" />
|
||||
<ClCompile Include="velocity.cpp" />
|
||||
<ClCompile Include="when.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,61 +0,0 @@
|
|||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct AsyncQueue
|
||||
{
|
||||
thread_pool m_pool;
|
||||
|
||||
AsyncQueue(uint32_t const high, uint32_t const low)
|
||||
{
|
||||
m_pool.thread_limits(high, low);
|
||||
}
|
||||
|
||||
IAsyncAction Async(delegate<> callback)
|
||||
{
|
||||
co_await m_pool;
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t test(uint32_t const iterations, uint32_t const high, uint32_t const low)
|
||||
{
|
||||
AsyncQueue queue(high, low);
|
||||
std::vector<IAsyncAction> results;
|
||||
uint32_t counter{};
|
||||
|
||||
for (uint32_t i = 0; i < iterations; ++i)
|
||||
{
|
||||
results.push_back(queue.Async([&]
|
||||
{
|
||||
auto value = counter + 1;
|
||||
Sleep(10); // Induce thread pool to use more threads if available, also force race condition
|
||||
counter = value;
|
||||
}));
|
||||
}
|
||||
|
||||
for (auto&& async : results)
|
||||
{
|
||||
async.get();
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("thread_pool")
|
||||
{
|
||||
uint32_t const test_iterations = 100;
|
||||
|
||||
uint32_t const stable_counter = test(test_iterations, 1, 1);
|
||||
uint32_t const unstable_counter = test(test_iterations, 10, 10);
|
||||
|
||||
// This is determinstic since the queue is single-threaded.
|
||||
REQUIRE(stable_counter == test_iterations);
|
||||
|
||||
// This is unlikely to fail since the pool is multi-threaded.
|
||||
REQUIRE(unstable_counter < test_iterations);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace test_component;
|
||||
|
||||
TEST_CASE("uniform_in_params")
|
||||
{
|
||||
Class{ single_threaded_vector<hstring>({ L"test" }).as<IIterable<hstring>>(), 0 };
|
||||
Class{ single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } }).as<IIterable<IKeyValuePair<hstring, hstring>>>(), 0, 0 };
|
||||
Class{ single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } }), 0, 0, 0 };
|
||||
Class{ single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } }).GetView(), 0, 0, 0, 0 };
|
||||
Class{ single_threaded_vector<hstring>({ L"test" }), 0, 0, 0, 0, 0 };
|
||||
Class{ single_threaded_vector<hstring>({ L"test" }).GetView(), 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
Class c;
|
||||
REQUIRE(L"test" == c.InIterable({L"test"}));
|
||||
REQUIRE(L"test" == c.InIterablePair(single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } })));
|
||||
REQUIRE(L"test" == c.InAsyncIterable({ L"test" }).get());
|
||||
REQUIRE(L"test" == c.InAsyncIterablePair(single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } })).get());
|
||||
REQUIRE(L"test" == c.InMap(single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } })));
|
||||
REQUIRE(L"test" == c.InMapView(single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } }).GetView()));
|
||||
REQUIRE(L"test" == c.InAsyncMapView(single_threaded_map<hstring, hstring>(std::map<hstring, hstring>{ {L"test", L"test" } }).GetView()).get());
|
||||
REQUIRE(L"test" == c.InVector({ L"test" }));
|
||||
REQUIRE(L"test" == c.InVectorView({ L"test" }));
|
||||
REQUIRE(L"test" == c.InAsyncVectorView({ L"test" }).get());
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include "winrt/test_component.Velocity.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace test_component::Velocity;
|
||||
|
||||
TEST_CASE("velocity")
|
||||
{
|
||||
// This interface is always disabled but shows up in the type system
|
||||
// if it is present in the winmd.
|
||||
IInterface1 a;
|
||||
REQUIRE(a == nullptr);
|
||||
|
||||
// This interface is always enabled and is naturally available in
|
||||
// the projection.
|
||||
IInterface2 b;
|
||||
REQUIRE(b == nullptr);
|
||||
|
||||
// Class1 is always disabled and thus will not activate.
|
||||
REQUIRE_THROWS_AS(Class1(), hresult_class_not_registered);
|
||||
|
||||
// Class2 is always enabled so should activate just fine.
|
||||
Class2 c;
|
||||
c.Class2_Method();
|
||||
|
||||
// Class3 is always disabled and thus will not activate.
|
||||
REQUIRE_THROWS_AS(Class3(), hresult_class_not_registered);
|
||||
|
||||
// Class4 is not feature-controlled but uses feature interfaces.
|
||||
Class4 d;
|
||||
d.Class4_Method();
|
||||
|
||||
// The single argument constructor is always disabled.
|
||||
REQUIRE_THROWS_AS(Class4(1), hresult_class_not_registered);
|
||||
|
||||
// The Class4_Static1 static is always disabled.
|
||||
REQUIRE_THROWS_AS(Class4::Class4_Static1(), hresult_class_not_registered);
|
||||
|
||||
// The two argument constructor is always enabled.
|
||||
Class4 e(1, 2);
|
||||
|
||||
// The Class4_Static2 static is always enabled.
|
||||
Class4::Class4_Static2();
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#include "pch.h"
|
||||
#include <pplawait.h>
|
||||
|
||||
using namespace concurrency;
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
task<void> ppl(bool& done)
|
||||
{
|
||||
co_await resume_background();
|
||||
done = true;
|
||||
}
|
||||
|
||||
IAsyncAction async(bool& done)
|
||||
{
|
||||
co_await resume_background();
|
||||
done = true;
|
||||
}
|
||||
|
||||
IAsyncOperation<int> when_signaled(int value, handle const& event)
|
||||
{
|
||||
co_await resume_on_signal(event.get());
|
||||
co_return value;
|
||||
}
|
||||
|
||||
IAsyncAction done()
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
TEST_CASE("when")
|
||||
{
|
||||
{
|
||||
bool ppl_done = false;
|
||||
bool async_done = false;
|
||||
|
||||
// Ensures that different async types can be aggregated.
|
||||
when_all(ppl(ppl_done), async(async_done)).get();
|
||||
|
||||
REQUIRE(ppl_done);
|
||||
REQUIRE(async_done);
|
||||
}
|
||||
{
|
||||
// Works with IAsyncAction (with no return value).
|
||||
IAsyncAction result = when_any(done(), done());
|
||||
result.get();
|
||||
}
|
||||
{
|
||||
handle first_event{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) };
|
||||
handle second_event{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) };
|
||||
|
||||
IAsyncOperation<int> first = when_signaled(1, first_event);
|
||||
IAsyncOperation<int> second = when_signaled(2, second_event);
|
||||
|
||||
IAsyncOperation<int> result = when_any(first, second);
|
||||
|
||||
// Make sure we're still waiting.
|
||||
Sleep(100);
|
||||
REQUIRE(result.Status() == AsyncStatus::Started);
|
||||
REQUIRE(first.Status() == AsyncStatus::Started);
|
||||
REQUIRE(second.Status() == AsyncStatus::Started);
|
||||
|
||||
// Allow only one of the async objects to complete.
|
||||
SetEvent(second_event.get());
|
||||
|
||||
// This should now complete.
|
||||
REQUIRE(2 == result.get());
|
||||
|
||||
REQUIRE(first.Status() == AsyncStatus::Started);
|
||||
REQUIRE(second.Status() == AsyncStatus::Completed);
|
||||
|
||||
SetEvent(first_event.get());
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче