@@ -37,9 +37,9 @@ namespace
3737
3838#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000
3939// <source_location> not available in libc++ before LLVM 16
40- TEST_CASE (" custom_error_logger " , " [!shouldfail]" )
40+ TEST_CASE (" custom_error_logger_on_throw " , " [!shouldfail]" )
4141#else
42- TEST_CASE (" custom_error_logger " )
42+ TEST_CASE (" custom_error_logger_on_throw " )
4343#endif
4444{
4545 // Set up global handler
@@ -72,3 +72,62 @@ TEST_CASE("custom_error_logger")
7272 winrt_throw_hresult_handler = nullptr ;
7373 s_loggerCalled = false ;
7474}
75+ template <typename ... Args>
76+ void HresultOnLine80 (Args... args)
77+ {
78+ // Validate that handler translated on creating an HRESULT
79+ #line 80 // Force next line to be reported as line number 80
80+ winrt::hresult_canceled (std::forward<Args>(args)...);
81+ }
82+
83+ #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000
84+ // <source_location> not available in libc++ before LLVM 16
85+ TEST_CASE (" custom_error_logger_on_originate" , " [!shouldfail]" )
86+ #else
87+ TEST_CASE (" custom_error_logger_on_originate" )
88+ #endif
89+ {
90+ // Set up global handler
91+ REQUIRE (!s_loggerCalled);
92+ REQUIRE (!winrt_throw_hresult_handler);
93+ winrt_throw_hresult_handler = logger;
94+
95+ HresultOnLine80 ();
96+ REQUIRE (s_loggerCalled);
97+ // In C++20 these fields should be filled in by std::source_location
98+ REQUIRE (s_loggerArgs.lineNumber == 80 );
99+ const auto fileNameSv = std::string_view (s_loggerArgs.fileName );
100+ REQUIRE (!fileNameSv.empty ());
101+ REQUIRE (fileNameSv.find (" custom_error.cpp" ) != std::string::npos);
102+ #ifdef _DEBUG
103+ const auto functionNameSv = std::string_view (s_loggerArgs.functionName );
104+ REQUIRE (!functionNameSv.empty ());
105+ // Every compiler has a slightly different naming approach for this function, and even the same
106+ // compiler can change its mind over time. Instead of matching the entire function name just
107+ // match against the part we care about.
108+ REQUIRE ((functionNameSv.find (" HresultOnLine80" ) != std::string_view::npos));
109+ #else
110+ REQUIRE (s_loggerArgs.functionName == nullptr );
111+ #endif // _DEBUG
112+
113+ REQUIRE (s_loggerArgs.returnAddress );
114+ REQUIRE (s_loggerArgs.result == HRESULT_FROM_WIN32 (ERROR_CANCELLED)); // E_ILLEGAL_DELEGATE_ASSIGNMENT)
115+
116+ s_loggerCalled = false ;
117+ s_loggerArgs.lineNumber = 0 ;
118+ // verify HRESULT with a custom message
119+ HresultOnLine80 (L" with custom message" );
120+ REQUIRE (s_loggerCalled);
121+ REQUIRE (s_loggerArgs.lineNumber == 80 );
122+
123+ s_loggerCalled = false ;
124+ s_loggerArgs.lineNumber = 0 ;
125+ // verify that no_originate does _not_ call the logger.
126+ HresultOnLine80 (winrt::hresult_error::no_originate);
127+ REQUIRE (!s_loggerCalled);
128+ REQUIRE (s_loggerArgs.lineNumber == 0 );
129+
130+ // Remove global handler
131+ winrt_throw_hresult_handler = nullptr ;
132+ s_loggerCalled = false ;
133+ }
0 commit comments