From 80de0969db963252ae3377e9bdb168623a2ca288 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 16 Jan 2020 14:18:05 -0800 Subject: [PATCH] Provide winrt_activation_handler to hook/mock activation (#477) --- strings/base_activation.h | 5 ++++ strings/base_extern.h | 1 + test/test/custom_activation.cpp | 52 +++++++++++++++++++++++++++++++++ test/test/test.vcxproj | 10 +++++++ 4 files changed, 68 insertions(+) create mode 100644 test/test/custom_activation.cpp diff --git a/strings/base_activation.h b/strings/base_activation.h index c50effe94..37c70aaa9 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -21,6 +21,11 @@ namespace winrt::impl template hresult get_runtime_activation_factory(param::hstring const& name, void** result) noexcept { + if (winrt_activation_handler) + { + return winrt_activation_handler(*(void**)(&name), guid_of(), result); + } + static int32_t(__stdcall * handler)(void* classId, guid const& iid, void** factory) noexcept; impl::load_runtime_function("RoGetActivationFactory", handler, diff --git a/strings/base_extern.h b/strings/base_extern.h index fa9906f09..d78b9c3f1 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -2,6 +2,7 @@ __declspec(selectany) int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; __declspec(selectany) void(__stdcall* winrt_suspend_handler)(void const* token) noexcept {}; __declspec(selectany) void(__stdcall* winrt_resume_handler)(void const* token) noexcept {}; +__declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; extern "C" { diff --git a/test/test/custom_activation.cpp b/test/test/custom_activation.cpp new file mode 100644 index 000000000..d3e309461 --- /dev/null +++ b/test/test/custom_activation.cpp @@ -0,0 +1,52 @@ +#include "winrt/Windows.Foundation.Numerics.h" +#include "catch.hpp" + +using namespace winrt; +using namespace Windows::Foundation; + +namespace +{ + struct custom_factory : implements + { + inline static Uri mock_uri{ nullptr }; + + Uri CreateUri(hstring const& value) const + { + REQUIRE(value == L"http://ignored.com"); + return mock_uri; + } + + Uri CreateWithRelativeUri(hstring const&, hstring const&) const + { + throw hresult_not_implemented(); + } + }; + + int32_t __stdcall handler(void* classId, winrt::guid const& iid, void** factory) noexcept + { + bool expected = reinterpret_cast(classId) == L"Windows.Foundation.Uri"; + REQUIRE(expected); + REQUIRE(iid == guid_of()); + + *factory = detach_abi(make()); + return 0; + } +} + +TEST_CASE("custom_activation") +{ + custom_factory::mock_uri = Uri(L"http://actual.com"); + clear_factory_cache(); + + // Set up global handler + REQUIRE(!winrt_activation_handler); + winrt_activation_handler = handler; + + // Windows.Foundation.Uri activation factory now returns mock object + auto uri = Uri(L"http://ignored.com"); + REQUIRE(uri.Domain() == L"actual.com"); + + // Remove global handler + winrt_activation_handler = nullptr; + clear_factory_cache(); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 604aff066..41419ebae 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -315,6 +315,16 @@ NotUsing NotUsing + + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing +