-
Notifications
You must be signed in to change notification settings - Fork 241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consume Detours for function mocking #421
Conversation
{ | ||
return *any; | ||
THROW_HR(E_NOT_SET); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that changes like this are a consequence of defining RESULT_NORETURN
to nothing. I debated trying to change it so that only the failfast functions are marked with RESULT_NORETURN
since those are the only ones that we detour, however this is simple enough
Note that an alternative to adding a dependency on vcpkg is to instead check in & build Detours ourselves. Personally, I'm not a huge fan, but... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wow... great work Duncan.
}); | ||
witest::detoured_thread_function<&::LocalFree> detour; | ||
REQUIRE_SUCCEEDED(detour.reset([](HLOCAL p) -> HLOCAL { | ||
HLOCAL h = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wil::unique_hlocal
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that helps much here. h
is the result of the call to LocalFree
and is returned to the caller. We also couldn't use it for wrapping p
since we need the result of the call to LocalFree
to return to the caller.
hooray :) |
[celebrate] Duncan Horn reacted to your message:
…________________________________
From: Alexander Sklar ***@***.***>
Sent: Friday, January 5, 2024 4:56:13 AM
To: microsoft/wil ***@***.***>
Cc: Duncan Horn ***@***.***>; State change ***@***.***>
Subject: Re: [microsoft/wil] Consume Detours for function mocking (PR #421)
hooray :)
—
Reply to this email directly, view it on GitHub<#421 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AJROQIDMQJY5VLSTWSPFEQTYM6BW3AVCNFSM6AAAAABBKUEVG6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZYGEZDIMRRHE>.
You are receiving this because you modified the open/close state.Message ID: ***@***.***>
|
A little background - internal to the Windows repo there's a library for mocking functions for the purpose of writing tests. As of this writing, this library has not yet been made public. The original tests for WIL (before being made open source) relied on this library for a number of things. When porting the tests to this repo, the tests that rely on this library either needed to be modified to use alternative means for testing the same functionality or omitted entirely. This led to a number of hacks to try and achieve the same functionality, some of which have historically caused issues.
This change is an attempt to replace the use of that library with something that uses the Detours library to achieve something similar (it's noteworthy that the internal library also uses Detours). This code isn't intended to be as feature rich as the internal library and is targeted at providing just what's necessary for our tests. In particular, there are two types used for mocking:
detoured_thread_function
- detours a function, however it only invokes the callback if the call came in on the thread that created the object. This is to avoid unintended consequences of some other thread interfering with the test - e.g. because of running tests in parallel, random chance, etc.detoured_global_function
- detours a function that calls the function object regardless of which thread called the detoured function. This is intended as a last resort option when the thread making the call cannot be predicted - e.g. from a thread pool thread, etc.Both of these types are designed to be able to be constructed with a lambda since testing function pointers + globals is often a mess. Additionally, both are designed such that calls are non-reentrant on the thread that called them. This is nice because it allows the detour to just invoke the function it's detouring by name as opposed to needing to do something like reference the object holding it, however this also means that some scenarios may not work 100% as expected (e.g. your detour => detoured function => other function... => detoured function).
I've updated relevant tests to use these types as opposed to the work arounds we've been using & added some tests that were never copied in the first place. Now, this change isn't without some negatives:
vcpkg
. This is an extra setup step - albeit one most people will only need to do once - however it does increase the "barrier to entry" slightly. Aside - I also took the opportunity to switch to consuming Catch2 via vcpkg while I was at it. NOTE: I'm unsure if this may have consequences for code consuming WIL from vcpkg.Ultimately, these tradeoffs seem worth it to me; just calling them out to see what others think.
Fixes #393