267 lines
8.9 KiB
C++
267 lines
8.9 KiB
C++
|
|
||
|
#include <wil/winrt.h>
|
||
|
#include <wrl/implements.h>
|
||
|
|
||
|
#include "common.h"
|
||
|
|
||
|
using namespace ABI::Windows::Foundation;
|
||
|
using namespace Microsoft::WRL;
|
||
|
|
||
|
namespace wiltest
|
||
|
{
|
||
|
class AbiTestEventSender WrlFinal : public RuntimeClass<
|
||
|
RuntimeClassFlags<RuntimeClassType::WinRtClassicComMix>,
|
||
|
IClosable,
|
||
|
IMemoryBufferReference,
|
||
|
FtmBase>
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
// IMemoryBufferReference
|
||
|
IFACEMETHODIMP get_Capacity(_Out_ UINT32* value)
|
||
|
{
|
||
|
*value = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
IFACEMETHODIMP add_Closed(
|
||
|
_In_ ITypedEventHandler<IMemoryBufferReference*, IInspectable*>* handler,
|
||
|
_Out_ ::EventRegistrationToken* token)
|
||
|
{
|
||
|
return m_closedEvent.Add(handler, token);
|
||
|
}
|
||
|
|
||
|
IFACEMETHODIMP remove_Closed(::EventRegistrationToken token)
|
||
|
{
|
||
|
return m_closedEvent.Remove(token);
|
||
|
}
|
||
|
|
||
|
// IClosable
|
||
|
IFACEMETHODIMP Close()
|
||
|
{
|
||
|
RETURN_IF_FAILED(m_closedEvent.InvokeAll(this, nullptr));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
Microsoft::WRL::EventSource<ITypedEventHandler<IMemoryBufferReference*, IInspectable*>> m_closedEvent;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
TEST_CASE("UniqueWinRTEventTokenTests::AbiUniqueWinrtEventTokenEventSubscribe", "[winrt][unique_winrt_event_token]")
|
||
|
{
|
||
|
ComPtr<IMemoryBufferReference> testEventSender;
|
||
|
REQUIRE_SUCCEEDED(MakeAndInitialize<wiltest::AbiTestEventSender>(&testEventSender));
|
||
|
ComPtr<IClosable> closable;
|
||
|
testEventSender.As(&closable);
|
||
|
|
||
|
int timesInvoked = 0;
|
||
|
auto handler = Callback<Implements<RuntimeClassFlags<ClassicCom>,
|
||
|
ITypedEventHandler<IMemoryBufferReference*, IInspectable*>, FtmBase>>
|
||
|
([×Invoked](IInspectable*, IInspectable*)
|
||
|
{
|
||
|
timesInvoked++;
|
||
|
return S_OK;
|
||
|
});
|
||
|
REQUIRE(timesInvoked == 0);
|
||
|
|
||
|
{
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> token;
|
||
|
REQUIRE_SUCCEEDED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, testEventSender.Get(), handler.Get(), &token));
|
||
|
REQUIRE(static_cast<bool>(token));
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
}
|
||
|
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("UniqueWinRTEventTokenTests::AbiUniqueWinrtEventTokenEarlyReset", "[winrt][unique_winrt_event_token]")
|
||
|
{
|
||
|
ComPtr<IMemoryBufferReference> testEventSender;
|
||
|
REQUIRE_SUCCEEDED(MakeAndInitialize<wiltest::AbiTestEventSender>(&testEventSender));
|
||
|
ComPtr<IClosable> closable;
|
||
|
testEventSender.As(&closable);
|
||
|
|
||
|
int timesInvoked = 0;
|
||
|
auto handler = Callback<Implements<RuntimeClassFlags<ClassicCom>,
|
||
|
ITypedEventHandler<IMemoryBufferReference*, IInspectable*>, FtmBase>>
|
||
|
([×Invoked](IInspectable*, IInspectable*)
|
||
|
{
|
||
|
timesInvoked++;
|
||
|
return S_OK;
|
||
|
});
|
||
|
REQUIRE(timesInvoked == 0);
|
||
|
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> token;
|
||
|
REQUIRE_SUCCEEDED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, testEventSender.Get(), handler.Get(), &token));
|
||
|
REQUIRE(static_cast<bool>(token));
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
|
||
|
token.reset();
|
||
|
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("UniqueWinRTEventTokenTests::AbiUniqueWinrtEventTokenMoveTokenToDifferentScope", "[winrt][unique_winrt_event_token]")
|
||
|
{
|
||
|
ComPtr<IMemoryBufferReference> testEventSender;
|
||
|
REQUIRE_SUCCEEDED(MakeAndInitialize<wiltest::AbiTestEventSender>(&testEventSender));
|
||
|
ComPtr<IClosable> closable;
|
||
|
testEventSender.As(&closable);
|
||
|
|
||
|
int timesInvoked = 0;
|
||
|
auto handler = Callback<Implements<RuntimeClassFlags<ClassicCom>,
|
||
|
ITypedEventHandler<IMemoryBufferReference*, IInspectable*>, FtmBase>>
|
||
|
([×Invoked](IInspectable*, IInspectable*)
|
||
|
{
|
||
|
timesInvoked++;
|
||
|
return S_OK;
|
||
|
});
|
||
|
REQUIRE(timesInvoked == 0);
|
||
|
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> outerToken;
|
||
|
REQUIRE_FALSE(static_cast<bool>(outerToken));
|
||
|
{
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> token;
|
||
|
REQUIRE_SUCCEEDED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, testEventSender.Get(), handler.Get(), &token));
|
||
|
REQUIRE(static_cast<bool>(token));
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
|
||
|
outerToken = std::move(token);
|
||
|
REQUIRE_FALSE(static_cast<bool>(token));
|
||
|
REQUIRE(static_cast<bool>(outerToken));
|
||
|
}
|
||
|
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 2);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("UniqueWinRTEventTokenTests::AbiUniqueWinrtEventTokenMoveConstructor", "[winrt][unique_winrt_event_token]")
|
||
|
{
|
||
|
ComPtr<IMemoryBufferReference> testEventSender;
|
||
|
REQUIRE_SUCCEEDED(MakeAndInitialize<wiltest::AbiTestEventSender>(&testEventSender));
|
||
|
ComPtr<IClosable> closable;
|
||
|
testEventSender.As(&closable);
|
||
|
|
||
|
int timesInvoked = 0;
|
||
|
auto handler = Callback<Implements<RuntimeClassFlags<ClassicCom>,
|
||
|
ITypedEventHandler<IMemoryBufferReference*, IInspectable*>, FtmBase>>
|
||
|
([×Invoked](IInspectable*, IInspectable*)
|
||
|
{
|
||
|
timesInvoked++;
|
||
|
return S_OK;
|
||
|
});
|
||
|
REQUIRE(timesInvoked == 0);
|
||
|
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> firstToken;
|
||
|
REQUIRE_SUCCEEDED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, testEventSender.Get(), handler.Get(), &firstToken));
|
||
|
REQUIRE(static_cast<bool>(firstToken));
|
||
|
closable->Close();
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> secondToken(std::move(firstToken));
|
||
|
REQUIRE_FALSE(static_cast<bool>(firstToken));
|
||
|
REQUIRE(static_cast<bool>(secondToken));
|
||
|
|
||
|
closable->Close();
|
||
|
REQUIRE(timesInvoked == 2);
|
||
|
|
||
|
firstToken.reset();
|
||
|
closable->Close();
|
||
|
REQUIRE(timesInvoked == 3);
|
||
|
|
||
|
secondToken.reset();
|
||
|
closable->Close();
|
||
|
REQUIRE(timesInvoked == 3);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("UniqueWinRTEventTokenTests::AbiUniqueWinrtEventTokenReleaseAndReattachToNewWrapper", "[winrt][unique_winrt_event_token]")
|
||
|
{
|
||
|
ComPtr<IMemoryBufferReference> testEventSender;
|
||
|
REQUIRE_SUCCEEDED(MakeAndInitialize<wiltest::AbiTestEventSender>(&testEventSender));
|
||
|
ComPtr<IClosable> closable;
|
||
|
testEventSender.As(&closable);
|
||
|
|
||
|
int timesInvoked = 0;
|
||
|
auto handler = Callback<Implements<RuntimeClassFlags<ClassicCom>,
|
||
|
ITypedEventHandler<IMemoryBufferReference*, IInspectable*>, FtmBase>>
|
||
|
([×Invoked](IInspectable*, IInspectable*)
|
||
|
{
|
||
|
timesInvoked++;
|
||
|
return S_OK;
|
||
|
});
|
||
|
REQUIRE(timesInvoked == 0);
|
||
|
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> firstToken;
|
||
|
REQUIRE_SUCCEEDED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, testEventSender.Get(), handler.Get(), &firstToken));
|
||
|
REQUIRE(static_cast<bool>(firstToken));
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
|
||
|
::EventRegistrationToken rawToken = firstToken.release();
|
||
|
REQUIRE_FALSE(static_cast<bool>(firstToken));
|
||
|
REQUIRE(rawToken.value != 0);
|
||
|
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 2);
|
||
|
|
||
|
wil::unique_winrt_event_token<IMemoryBufferReference> secondToken(
|
||
|
rawToken, testEventSender.Get(), &IMemoryBufferReference::remove_Closed);
|
||
|
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 3);
|
||
|
|
||
|
secondToken.reset();
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
REQUIRE(timesInvoked == 3);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("UniqueWinRTEventTokenTests::AbiUniqueWinrtEventTokenPolicyVariants", "[winrt][unique_winrt_event_token]")
|
||
|
{
|
||
|
ComPtr<IMemoryBufferReference> testEventSender;
|
||
|
REQUIRE_SUCCEEDED(MakeAndInitialize<wiltest::AbiTestEventSender>(&testEventSender));
|
||
|
ComPtr<IClosable> closable;
|
||
|
testEventSender.As(&closable);
|
||
|
|
||
|
int timesInvoked = 0;
|
||
|
auto handler = Callback<Implements<RuntimeClassFlags<ClassicCom>,
|
||
|
ITypedEventHandler<IMemoryBufferReference*, IInspectable*>, FtmBase>>
|
||
|
([×Invoked](IInspectable*, IInspectable*)
|
||
|
{
|
||
|
timesInvoked++;
|
||
|
return S_OK;
|
||
|
});
|
||
|
REQUIRE(timesInvoked == 0);
|
||
|
|
||
|
{
|
||
|
#ifdef WIL_ENABLE_EXCEPTIONS
|
||
|
auto exceptionPolicyToken = WI_MakeUniqueWinRtEventToken(Closed, testEventSender.Get(), handler.Get());
|
||
|
REQUIRE(static_cast<bool>(exceptionPolicyToken));
|
||
|
#endif
|
||
|
|
||
|
auto failFastPolicyToken = WI_MakeUniqueWinRtEventTokenFailFast(Closed, testEventSender.Get(), handler.Get());
|
||
|
REQUIRE(static_cast<bool>(failFastPolicyToken));
|
||
|
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
|
||
|
#ifdef WIL_ENABLE_EXCEPTIONS
|
||
|
REQUIRE(timesInvoked == 2);
|
||
|
#else
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
REQUIRE_SUCCEEDED(closable->Close());
|
||
|
|
||
|
#ifdef WIL_ENABLE_EXCEPTIONS
|
||
|
REQUIRE(timesInvoked == 2);
|
||
|
#else
|
||
|
REQUIRE(timesInvoked == 1);
|
||
|
#endif
|
||
|
}
|