1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685 |
- #include <wil/result.h>
- #include <wil/resource.h>
- #include <wil/win32_helpers.h>
- #include <wil/filesystem.h>
- #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- #include <wil/wrl.h>
- #endif
- #include <wil/com.h>
- #ifdef WIL_ENABLE_EXCEPTIONS
- #include <memory>
- #include <set>
- #include <thread>
- #include <unordered_set>
- #endif
- // Do not include most headers until after the WIL headers to ensure that we're not inadvertently adding any unnecessary
- // dependencies to STL, WRL, or indirectly retrieved headers
- #ifndef __cplusplus_winrt
- #include <windows.foundation.collections.h>
- #include <windows.foundation.h>
- #endif
- // Include Resource.h a second time after including other headers
- #include <wil/resource.h>
- #include "common.h"
- #include "MallocSpy.h"
- #include "test_objects.h"
- #pragma warning(push)
- #pragma warning(disable: 4702) // Unreachable code
- TEST_CASE("WindowsInternalTests::CommonHelpers", "[resource]")
- {
- {
- wil::unique_handle spHandle;
- REQUIRE(spHandle == nullptr);
- REQUIRE(nullptr == spHandle);
- REQUIRE_FALSE(spHandle != nullptr);
- REQUIRE_FALSE(nullptr != spHandle);
- //equivalence check will static_assert because spMutex does not allow pointer access
- wil::mutex_release_scope_exit spMutex;
- //REQUIRE(spMutex == nullptr);
- //REQUIRE(nullptr == spMutex);
- //equivalence check will static_assert because spFile does not use nullptr_t as a invalid value
- wil::unique_hfile spFile;
- //REQUIRE(spFile == nullptr);
- }
- #ifdef __WIL_WINBASE_STL
- {
- wil::shared_handle spHandle;
- REQUIRE(spHandle == nullptr);
- REQUIRE(nullptr == spHandle);
- REQUIRE_FALSE(spHandle != nullptr);
- REQUIRE_FALSE(nullptr != spHandle);
- }
- #endif
- }
- TEST_CASE("WindowsInternalTests::AssertMacros", "[result_macros]")
- {
- //WI_ASSERT macros are all no-ops if in retail
- #ifndef RESULT_DEBUG
- WI_ASSERT(false);
- WI_ASSERT_MSG(false, "WI_ASSERT_MSG");
- WI_ASSERT_NOASSUME(false);
- WI_ASSERT_MSG_NOASSUME(false, "WI_ASSERT_MSG_NOASSUME");
- WI_VERIFY(false);
- WI_VERIFY_MSG(false, "WI_VERIFY_MSG");
- #endif
- WI_ASSERT(true);
- WI_ASSERT_MSG(true, "WI_ASSERT_MSG");
- WI_ASSERT_NOASSUME(true);
- WI_ASSERT_MSG_NOASSUME(true, "WI_ASSERT_MSG_NOASSUME");
- WI_VERIFY(true);
- WI_VERIFY_MSG(true, "WI_VERIFY_MSG");
- }
- void __stdcall EmptyResultMacrosLoggingCallback(wil::FailureInfo*, PWSTR, size_t) WI_NOEXCEPT
- {
- }
- #ifdef WIL_ENABLE_EXCEPTIONS
- // Test Result Macros
- void TestErrorCallbacks()
- {
- {
- size_t callbackCount = 0;
- auto monitor = wil::ThreadFailureCallback([&](wil::FailureInfo const &failure) -> bool
- {
- REQUIRE(failure.hr == E_ACCESSDENIED);
- callbackCount++;
- return false;
- });
- constexpr size_t depthCount = 10;
- for (size_t index = 0; index < depthCount; index++)
- {
- LOG_HR(E_ACCESSDENIED);
- }
- REQUIRE(callbackCount == depthCount);
- }
- {
- wil::ThreadFailureCache cache;
- LOG_HR(E_ACCESSDENIED);
- REQUIRE(cache.GetFailure() != nullptr);
- REQUIRE(cache.GetFailure()->hr == E_ACCESSDENIED);
- wil::ThreadFailureCache cacheNested;
- LOG_HR(E_FAIL); unsigned long errorLine = __LINE__;
- LOG_HR(E_FAIL);
- LOG_HR(E_FAIL);
- REQUIRE(cache.GetFailure()->hr == E_FAIL);
- REQUIRE(cache.GetFailure()->uLineNumber == errorLine);
- REQUIRE(cacheNested.GetFailure()->hr == E_FAIL);
- REQUIRE(cacheNested.GetFailure()->uLineNumber == errorLine);
- }
- }
- DWORD WINAPI ErrorCallbackThreadTest(_In_ LPVOID lpParameter)
- {
- try
- {
- HANDLE hEvent = reinterpret_cast<HANDLE>(lpParameter);
- for (size_t stress = 0; stress < 200; stress++)
- {
- Sleep(1); // allow the threadpool to saturate the thread count...
- TestErrorCallbacks();
- }
- THROW_IF_WIN32_BOOL_FALSE(::SetEvent(hEvent));
- }
- catch (...)
- {
- FAIL();
- }
- return 1;
- }
- void StressErrorCallbacks()
- {
- auto restore = witest::AssignTemporaryValue(&wil::g_fResultOutputDebugString, false);
- constexpr size_t threadCount = 20;
- wil::unique_event eventArray[threadCount];
- for (size_t index = 0; index < threadCount; index++)
- {
- eventArray[index].create();
- #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- THROW_IF_WIN32_BOOL_FALSE(::QueueUserWorkItem(ErrorCallbackThreadTest, eventArray[index].get(), 0));
- #else
- ErrorCallbackThreadTest(eventArray[index].get());
- #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
- }
- for (size_t index = 0; index < threadCount; index++)
- {
- eventArray[index].wait();
- }
- }
- TEST_CASE("WindowsInternalTests::ResultMacrosStress", "[LocalOnly][result_macros][stress]")
- {
- auto restore = witest::AssignTemporaryValue(&wil::g_pfnResultLoggingCallback, EmptyResultMacrosLoggingCallback);
- StressErrorCallbacks();
- }
- #endif
- #define E_AD HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)
- void SetAD()
- {
- ::SetLastError(ERROR_ACCESS_DENIED);
- }
- class AlternateAccessDeniedException
- {
- };
- #ifdef WIL_ENABLE_EXCEPTIONS
- class DerivedAccessDeniedException : public wil::ResultException
- {
- public:
- DerivedAccessDeniedException() : ResultException(E_AD) {}
- };
- HRESULT __stdcall TestResultCaughtFromException() WI_NOEXCEPT
- {
- try
- {
- throw;
- }
- catch (AlternateAccessDeniedException)
- {
- return E_AD;
- }
- catch (...)
- {
- }
- return S_OK;
- }
- #endif
- HANDLE hValid = reinterpret_cast<HANDLE>(1);
- HANDLE& hValidRef() { return hValid; }
- HANDLE hNull = NULL;
- HANDLE hInvalid = INVALID_HANDLE_VALUE;
- void* pValid = reinterpret_cast<void *>(1);
- void*& pValidRef() { return pValid; }
- void* pNull = nullptr;
- void*& pNullRef() { return pNull; }
- bool fTrue = true;
- bool& fTrueRef() { return fTrue; }
- bool fFalse = false;
- bool& fFalseRef() { return fFalse; }
- BOOL fTRUE = TRUE;
- BOOL& fTRUERef() { return fTRUE; }
- BOOL fFALSE = FALSE;
- DWORD errSuccess = ERROR_SUCCESS;
- DWORD& errSuccessRef() { return errSuccess; }
- HRESULT hrOK = S_OK;
- HRESULT& hrOKRef() { return hrOK; }
- HRESULT hrFAIL = E_FAIL;
- HRESULT& hrFAILRef() { return hrFAIL; }
- const HRESULT E_hrOutOfPaper = HRESULT_FROM_WIN32(ERROR_OUT_OF_PAPER);
- NTSTATUS ntOK = STATUS_SUCCESS;
- NTSTATUS& ntOKRef() { return ntOK; }
- NTSTATUS ntFAIL = STATUS_NO_MEMORY;
- NTSTATUS& ntFAILRef() { return ntFAIL; }
- const HRESULT S_hrNtOkay = wil::details::NtStatusToHr(STATUS_SUCCESS);
- const HRESULT E_hrNtAssertionFailure = wil::details::NtStatusToHr(STATUS_ASSERTION_FAILURE);
- wil::StoredFailureInfo g_log;
- void __stdcall ResultMacrosLoggingCallback(wil::FailureInfo *pFailure, PWSTR, size_t) WI_NOEXCEPT
- {
- g_log = *pFailure;
- }
- enum class EType
- {
- None = 0x00,
- Expected = 0x02,
- Msg = 0x04,
- FailFast = 0x08, // overall fail fast (throw exception on successful result code, for example)
- FailFastMacro = 0x10, // explicit use of fast fail fast (FAIL_FAST_IF...)
- NoContext = 0x20 // file and line info can be wrong (throw does not happen in context to code)
- };
- DEFINE_ENUM_FLAG_OPERATORS(EType);
- template <typename TLambda>
- bool VerifyResult(unsigned int lineNumber, EType type, HRESULT hr, TLambda&& lambda)
- {
- bool succeeded = true;
- #ifdef WIL_ENABLE_EXCEPTIONS
- try
- {
- #endif
- HRESULT lambdaResult = E_FAIL;
- bool didFailFast = true;
- {
- didFailFast = witest::DoesCodeCrash([&]()
- {
- lambdaResult = lambda();
- });
- }
- if (WI_IsFlagSet(type, EType::FailFast))
- {
- REQUIRE(didFailFast);
- }
- else
- {
- if (WI_IsFlagClear(type, EType::Expected))
- {
- if (SUCCEEDED(hr))
- {
- REQUIRE(hr == lambdaResult);
- REQUIRE(lineNumber != g_log.GetFailureInfo().uLineNumber);
- REQUIRE(!didFailFast);
- }
- else
- {
- REQUIRE((WI_IsFlagSet(type, EType::NoContext) || (g_log.GetFailureInfo().uLineNumber == lineNumber)));
- REQUIRE(g_log.GetFailureInfo().hr == hr);
- REQUIRE((WI_IsFlagClear(type, EType::Msg) || (nullptr != wcsstr(g_log.GetFailureInfo().pszMessage, L"msg"))));
- REQUIRE((WI_IsFlagClear(type, EType::FailFastMacro) || (didFailFast)));
- REQUIRE((WI_IsFlagSet(type, EType::FailFastMacro) || (!didFailFast)));
- }
- }
- }
- #ifdef WIL_ENABLE_EXCEPTIONS
- }
- catch (...)
- {
- succeeded = false;
- }
- #endif
- // Ensure we come out clean...
- ::SetLastError(ERROR_SUCCESS);
- return succeeded;
- }
- #ifdef WIL_ENABLE_EXCEPTIONS
- template <typename TLambda>
- HRESULT TranslateException(TLambda&& lambda)
- {
- try
- {
- lambda();
- }
- catch (wil::ResultException &re)
- {
- return re.GetErrorCode();
- }
- #ifdef __cplusplus_winrt
- catch (Platform::Exception ^pe)
- {
- return wil::details::GetErrorCode(pe);
- }
- #endif
- catch (...)
- {
- FAIL();
- }
- return S_OK;
- }
- #endif
- #define REQUIRE_RETURNS(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::None, hr, lambda))
- #define REQUIRE_RETURNS_MSG(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::Msg, hr, lambda))
- #define REQUIRE_RETURNS_EXPECTED(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::Expected, hr, lambda))
- #ifdef WIL_ENABLE_EXCEPTIONS
- #define REQUIRE_THROWS_RESULT(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::None, hr, [&] { return TranslateException(lambda); }))
- #define REQUIRE_THROWS_MSG(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::Msg, hr, [&] { return TranslateException(lambda); }))
- #else
- #define REQUIRE_THROWS_RESULT(hr, lambda)
- #define REQUIRE_THROWS_MSG(hr, lambda)
- #endif
- #define REQUIRE_LOG(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::None, hr, [&] { auto fn = (lambda); fn(); return hr; }))
- #define REQUIRE_LOG_MSG(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::Msg, hr, [&] { auto fn = (lambda); fn(); return hr; }))
- #define REQUIRE_FAILFAST(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::FailFastMacro, hr, [&] { auto fn = (lambda); fn(); return hr; }))
- #define REQUIRE_FAILFAST_MSG(hr, lambda) REQUIRE(VerifyResult(__LINE__, EType::FailFastMacro | EType::Msg, hr, [&] { auto fn = (lambda); fn(); return hr; }))
- #define REQUIRE_FAILFAST_UNSPECIFIED(lambda) REQUIRE(VerifyResult(__LINE__, EType::FailFast, S_OK, [&] { auto fn = (lambda); fn(); return S_OK; }))
- TEST_CASE("WindowsInternalTests::ResultMacros", "[result_macros]")
- {
- auto restoreLoggingCallback = witest::AssignTemporaryValue(&wil::g_pfnResultLoggingCallback, ResultMacrosLoggingCallback);
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto restoreExceptionCallback = witest::AssignTemporaryValue(&wil::g_pfnResultFromCaughtException, TestResultCaughtFromException);
- #endif
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR(MDEC(hrOKRef())); });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR(MDEC(hrOKRef())); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_FAIL, [] { RETURN_HR(E_FAIL); });
- REQUIRE_RETURNS_MSG(E_FAIL, [] { RETURN_HR_MSG(E_FAIL, "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_FAIL, [] { THROW_HR(E_FAIL); });
- REQUIRE_THROWS_MSG(E_FAIL, [] { THROW_HR_MSG(E_FAIL, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_FAIL, [] { LOG_HR(E_FAIL); });
- REQUIRE_LOG_MSG(E_FAIL, [] { LOG_HR_MSG(E_FAIL, "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_FAIL, [] { FAIL_FAST_HR(E_FAIL); });
- REQUIRE_FAILFAST_MSG(E_FAIL, [] { FAIL_FAST_HR_MSG(E_FAIL, "msg: %d", __LINE__); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { ::SetLastError(0); FAIL_FAST_LAST_ERROR(); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { ::SetLastError(0); FAIL_FAST_LAST_ERROR_MSG("msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_AD, [] { SetAD(); RETURN_LAST_ERROR(); });
- REQUIRE_RETURNS_MSG(E_AD, [] { SetAD(); RETURN_LAST_ERROR_MSG("msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_AD, [] { SetAD(); THROW_LAST_ERROR(); });
- REQUIRE_THROWS_MSG(E_AD, [] { SetAD(); THROW_LAST_ERROR_MSG("msg: %d", __LINE__); });
- REQUIRE_LOG(E_AD, [] { SetAD(); LOG_LAST_ERROR(); });
- REQUIRE_LOG_MSG(E_AD, [] { SetAD(); LOG_LAST_ERROR_MSG("msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_AD, [] { SetAD(); FAIL_FAST_LAST_ERROR(); });
- REQUIRE_FAILFAST_MSG(E_AD, [] { SetAD(); FAIL_FAST_LAST_ERROR_MSG("msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_WIN32(MDEC(errSuccessRef())); });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_WIN32_MSG(MDEC(errSuccessRef()), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_WIN32(MDEC(errSuccessRef())); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_WIN32_MSG(MDEC(errSuccessRef()), "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_AD, [] { RETURN_WIN32(ERROR_ACCESS_DENIED); });
- REQUIRE_RETURNS_MSG(E_AD, [] { RETURN_WIN32_MSG(ERROR_ACCESS_DENIED, "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_AD, [] { THROW_WIN32(ERROR_ACCESS_DENIED); });
- REQUIRE_THROWS_MSG(E_AD, [] { THROW_WIN32_MSG(ERROR_ACCESS_DENIED, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_AD, [] { LOG_WIN32(ERROR_ACCESS_DENIED); });
- REQUIRE_LOG_MSG(E_AD, [] { LOG_WIN32_MSG(ERROR_ACCESS_DENIED, "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_AD, [] { FAIL_FAST_WIN32(ERROR_ACCESS_DENIED); });
- REQUIRE_FAILFAST_MSG(E_AD, [] { FAIL_FAST_WIN32_MSG(ERROR_ACCESS_DENIED, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_IF_FAILED(MDEC(hrOKRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_IF_FAILED_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_IF_FAILED_EXPECTED(MDEC(hrOKRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(S_OK == THROW_IF_FAILED(MDEC(hrOKRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(S_OK == THROW_IF_FAILED_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(S_OK == LOG_IF_FAILED(MDEC(hrOKRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(S_OK == LOG_IF_FAILED_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(S_OK == FAIL_FAST_IF_FAILED(MDEC(hrOKRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(S_OK == FAIL_FAST_IF_FAILED_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(E_FAIL, [] { RETURN_IF_FAILED(E_FAIL); return S_OK; });
- REQUIRE_RETURNS_MSG(E_FAIL, [] { RETURN_IF_FAILED_MSG(E_FAIL, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { RETURN_IF_FAILED_EXPECTED(E_FAIL); return S_OK; });
- REQUIRE_THROWS_RESULT(E_FAIL, [] { THROW_IF_FAILED(E_FAIL); });
- REQUIRE_THROWS_MSG(E_FAIL, [] { THROW_IF_FAILED_MSG(E_FAIL, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(E_FAIL == LOG_IF_FAILED(E_FAIL)); });
- REQUIRE_LOG_MSG(E_FAIL, [] { REQUIRE(E_FAIL == LOG_IF_FAILED_MSG(E_FAIL, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_FAIL, [] { FAIL_FAST_IF_FAILED(E_FAIL); });
- REQUIRE_FAILFAST_MSG(E_FAIL, [] { FAIL_FAST_IF_FAILED_MSG(E_FAIL, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_IF_WIN32_BOOL_FALSE(MDEC(fTRUERef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_IF_WIN32_BOOL_FALSE_MSG(MDEC(fTRUERef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(MDEC(fTRUERef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(fTRUE == THROW_IF_WIN32_BOOL_FALSE(MDEC(fTRUERef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(fTRUE == THROW_IF_WIN32_BOOL_FALSE_MSG(MDEC(fTRUERef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(fTRUE == LOG_IF_WIN32_BOOL_FALSE(MDEC(fTRUERef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(fTRUE == LOG_IF_WIN32_BOOL_FALSE_MSG(MDEC(fTRUERef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(fTRUE == FAIL_FAST_IF_WIN32_BOOL_FALSE(MDEC(fTRUERef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(fTRUE == FAIL_FAST_IF_WIN32_BOOL_FALSE_MSG(MDEC(fTRUERef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(E_AD, [] { SetAD(); RETURN_IF_WIN32_BOOL_FALSE(fFALSE); return S_OK; });
- REQUIRE_RETURNS_MSG(E_AD, [] { SetAD(); RETURN_IF_WIN32_BOOL_FALSE_MSG(fFALSE, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_AD, [] { SetAD(); RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(fFALSE); return S_OK; });
- REQUIRE_THROWS_RESULT(E_AD, [] { SetAD(); THROW_IF_WIN32_BOOL_FALSE(fFALSE); });
- REQUIRE_THROWS_MSG(E_AD, [] { SetAD(); THROW_IF_WIN32_BOOL_FALSE_MSG(fFALSE, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_AD, [] { SetAD(); REQUIRE(fFALSE == LOG_IF_WIN32_BOOL_FALSE(fFALSE)); });
- REQUIRE_LOG_MSG(E_AD, [] { SetAD(); REQUIRE(fFALSE == LOG_IF_WIN32_BOOL_FALSE_MSG(fFALSE, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_AD, [] { SetAD(); FAIL_FAST_IF_WIN32_BOOL_FALSE(fFALSE); });
- REQUIRE_FAILFAST_MSG(E_AD, [] { SetAD(); FAIL_FAST_IF_WIN32_BOOL_FALSE_MSG(fFALSE, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_IF_WIN32_ERROR(MDEC(hrOKRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_IF_WIN32_ERROR_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_IF_WIN32_ERROR_EXPECTED(MDEC(hrOKRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(S_OK == THROW_IF_WIN32_ERROR(MDEC(hrOKRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(S_OK == THROW_IF_WIN32_ERROR_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(S_OK == LOG_IF_WIN32_ERROR(MDEC(hrOKRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(S_OK == LOG_IF_WIN32_ERROR_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(S_OK == FAIL_FAST_IF_WIN32_ERROR(MDEC(hrOKRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(S_OK == FAIL_FAST_IF_WIN32_ERROR_MSG(MDEC(hrOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(E_hrOutOfPaper, [] { RETURN_IF_WIN32_ERROR(ERROR_OUT_OF_PAPER); return S_OK; });
- REQUIRE_RETURNS_MSG(E_hrOutOfPaper, [] { RETURN_IF_WIN32_ERROR_MSG(ERROR_OUT_OF_PAPER, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_hrOutOfPaper, [] { RETURN_IF_WIN32_ERROR_EXPECTED(ERROR_OUT_OF_PAPER); return S_OK; });
- REQUIRE_THROWS_RESULT(E_hrOutOfPaper, [] { THROW_IF_WIN32_ERROR(ERROR_OUT_OF_PAPER); });
- REQUIRE_THROWS_MSG(E_hrOutOfPaper, [] { THROW_IF_WIN32_ERROR_MSG(ERROR_OUT_OF_PAPER, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_hrOutOfPaper, [] { REQUIRE(ERROR_OUT_OF_PAPER == LOG_IF_WIN32_ERROR(ERROR_OUT_OF_PAPER)); });
- REQUIRE_LOG_MSG(E_hrOutOfPaper, [] { REQUIRE(ERROR_OUT_OF_PAPER == LOG_IF_WIN32_ERROR_MSG(ERROR_OUT_OF_PAPER, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_hrOutOfPaper, [] { FAIL_FAST_IF_WIN32_ERROR(ERROR_OUT_OF_PAPER); });
- REQUIRE_FAILFAST_MSG(E_hrOutOfPaper, [] { FAIL_FAST_IF_WIN32_ERROR_MSG(ERROR_OUT_OF_PAPER, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_hrNtOkay, [] { RETURN_NTSTATUS(MDEC(ntOKRef())); });
- REQUIRE_RETURNS_MSG(S_hrNtOkay, [] { RETURN_NTSTATUS_MSG(MDEC(ntOKRef()), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_NTSTATUS(MDEC(ntOKRef())); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_NTSTATUS_MSG(MDEC(ntOKRef()), "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_hrNtAssertionFailure, [] { RETURN_NTSTATUS(STATUS_ASSERTION_FAILURE); });
- REQUIRE_RETURNS_MSG(E_hrNtAssertionFailure, [] { RETURN_NTSTATUS_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_hrNtAssertionFailure, [] { THROW_NTSTATUS(STATUS_ASSERTION_FAILURE); });
- REQUIRE_THROWS_MSG(E_hrNtAssertionFailure, [] { THROW_NTSTATUS_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_hrNtAssertionFailure, [] { LOG_NTSTATUS(STATUS_ASSERTION_FAILURE); });
- REQUIRE_LOG_MSG(E_hrNtAssertionFailure, [] { LOG_NTSTATUS_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_hrNtAssertionFailure, [] { FAIL_FAST_NTSTATUS(STATUS_ASSERTION_FAILURE); });
- REQUIRE_FAILFAST_MSG(E_hrNtAssertionFailure, [] { FAIL_FAST_NTSTATUS_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__); });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_IF_NTSTATUS_FAILED_MSG(MDEC(ntOKRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_IF_NTSTATUS_FAILED_EXPECTED(MDEC(ntOKRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(STATUS_WAIT_0 == THROW_IF_NTSTATUS_FAILED(MDEC(ntOKRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(STATUS_WAIT_0 == THROW_IF_NTSTATUS_FAILED_MSG(MDEC(ntOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(STATUS_WAIT_0 == LOG_IF_NTSTATUS_FAILED(MDEC(ntOKRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(STATUS_WAIT_0 == LOG_IF_NTSTATUS_FAILED_MSG(MDEC(ntOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(STATUS_WAIT_0 == FAIL_FAST_IF_NTSTATUS_FAILED(MDEC(ntOKRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(STATUS_WAIT_0 == FAIL_FAST_IF_NTSTATUS_FAILED_MSG(MDEC(ntOKRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(E_hrNtAssertionFailure, [] { RETURN_IF_NTSTATUS_FAILED(STATUS_ASSERTION_FAILURE); return S_OK; });
- REQUIRE_RETURNS_MSG(E_hrNtAssertionFailure, [] { RETURN_IF_NTSTATUS_FAILED_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_hrNtAssertionFailure, [] { RETURN_IF_NTSTATUS_FAILED_EXPECTED(STATUS_ASSERTION_FAILURE); return S_OK; });
- REQUIRE_THROWS_RESULT(E_hrNtAssertionFailure, [] { THROW_IF_NTSTATUS_FAILED(STATUS_ASSERTION_FAILURE); });
- REQUIRE_THROWS_MSG(E_hrNtAssertionFailure, [] { THROW_IF_NTSTATUS_FAILED_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_hrNtAssertionFailure, [] { REQUIRE(STATUS_ASSERTION_FAILURE == static_cast<DWORD>(LOG_IF_NTSTATUS_FAILED(STATUS_ASSERTION_FAILURE))); });
- REQUIRE_LOG_MSG(E_hrNtAssertionFailure, [] { REQUIRE(STATUS_ASSERTION_FAILURE == static_cast<DWORD>(LOG_IF_NTSTATUS_FAILED_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__))); });
- REQUIRE_FAILFAST(E_hrNtAssertionFailure, [] { FAIL_FAST_IF_NTSTATUS_FAILED(STATUS_ASSERTION_FAILURE); });
- REQUIRE_FAILFAST_MSG(E_hrNtAssertionFailure, [] { FAIL_FAST_IF_NTSTATUS_FAILED_MSG(STATUS_ASSERTION_FAILURE, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_OUTOFMEMORY, [] { RETURN_IF_NTSTATUS_FAILED(STATUS_NO_MEMORY); return S_OK; });
- REQUIRE_RETURNS_MSG(E_OUTOFMEMORY, [] { RETURN_IF_NTSTATUS_FAILED_MSG(STATUS_NO_MEMORY, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_OUTOFMEMORY, [] { RETURN_IF_NTSTATUS_FAILED_EXPECTED(STATUS_NO_MEMORY); return S_OK; });
- REQUIRE_THROWS_RESULT(E_OUTOFMEMORY, [] { THROW_IF_NTSTATUS_FAILED(STATUS_NO_MEMORY); });
- REQUIRE_THROWS_MSG(E_OUTOFMEMORY, [] { THROW_IF_NTSTATUS_FAILED_MSG(STATUS_NO_MEMORY, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_OUTOFMEMORY, [] { REQUIRE(STATUS_NO_MEMORY == static_cast<DWORD>(LOG_IF_NTSTATUS_FAILED(STATUS_NO_MEMORY))); });
- REQUIRE_LOG_MSG(E_OUTOFMEMORY, [] { REQUIRE(STATUS_NO_MEMORY == static_cast<DWORD>(LOG_IF_NTSTATUS_FAILED_MSG(STATUS_NO_MEMORY, "msg: %d", __LINE__))); });
- REQUIRE_FAILFAST(E_OUTOFMEMORY, [] { FAIL_FAST_IF_NTSTATUS_FAILED(STATUS_NO_MEMORY); });
- REQUIRE_FAILFAST_MSG(E_OUTOFMEMORY, [] { FAIL_FAST_IF_NTSTATUS_FAILED_MSG(STATUS_NO_MEMORY, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_IF_NULL_ALLOC(MDEC(pValidRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_IF_NULL_ALLOC_MSG(MDEC(pValidRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_IF_NULL_ALLOC_EXPECTED(MDEC(pValidRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(pValid == THROW_IF_NULL_ALLOC(MDEC(pValidRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(pValid == THROW_IF_NULL_ALLOC_MSG(MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(pValid == LOG_IF_NULL_ALLOC(MDEC(pValidRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(pValid == LOG_IF_NULL_ALLOC_MSG(MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(pValid == FAIL_FAST_IF_NULL_ALLOC(MDEC(pValidRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(pValid == FAIL_FAST_IF_NULL_ALLOC_MSG(MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(E_OUTOFMEMORY, [] { RETURN_IF_NULL_ALLOC(pNull); return S_OK; });
- REQUIRE_RETURNS_MSG(E_OUTOFMEMORY, [] { RETURN_IF_NULL_ALLOC_MSG(pNull, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_OUTOFMEMORY, [] { RETURN_IF_NULL_ALLOC_EXPECTED(pNull); return S_OK; });
- REQUIRE_THROWS_RESULT(E_OUTOFMEMORY, [] { THROW_IF_NULL_ALLOC(pNull); });
- REQUIRE_THROWS_MSG(E_OUTOFMEMORY, [] { THROW_IF_NULL_ALLOC_MSG(pNull, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_OUTOFMEMORY, [] { REQUIRE(pNull == LOG_IF_NULL_ALLOC(pNull)); });
- REQUIRE_LOG_MSG(E_OUTOFMEMORY, [] { REQUIRE(pNull == LOG_IF_NULL_ALLOC_MSG(pNull, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_OUTOFMEMORY, [] { FAIL_FAST_IF_NULL_ALLOC(pNull); });
- REQUIRE_FAILFAST_MSG(E_OUTOFMEMORY, [] { FAIL_FAST_IF_NULL_ALLOC_MSG(pNull, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF(MDEC(S_OK), MDEC(fTrueRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_MSG(MDEC(S_OK), MDEC(fTrueRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_EXPECTED(MDEC(S_OK), MDEC(fTrueRef())); return S_OK; });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR_IF(MDEC(S_OK), MDEC(fTrueRef())); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR_IF_MSG(MDEC(S_OK), MDEC(fTrueRef()), "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_FAIL, [] { RETURN_HR_IF(E_FAIL, fTrue); return S_OK; });
- REQUIRE_RETURNS_MSG(E_FAIL, [] { RETURN_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { RETURN_HR_IF_EXPECTED(E_FAIL, fTrue); return S_OK; });
- REQUIRE_THROWS_RESULT(E_FAIL, [] { THROW_HR_IF(E_FAIL, fTrue); });
- REQUIRE_THROWS_MSG(E_FAIL, [] { THROW_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(fTrue == LOG_HR_IF(E_FAIL, fTrue)); });
- REQUIRE_LOG_MSG(E_FAIL, [] { REQUIRE(fTrue == LOG_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_FAIL, [] { FAIL_FAST_HR_IF(E_FAIL, fTrue); });
- REQUIRE_FAILFAST_MSG(E_FAIL, [] { FAIL_FAST_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF(MDEC(S_OK), MDEC(fTrueRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_MSG(MDEC(S_OK), MDEC(fTrueRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_EXPECTED(MDEC(S_OK), MDEC(fTrueRef())); return S_OK; });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR_IF(MDEC(S_OK), MDEC(fTrueRef())); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR_IF_MSG(MDEC(S_OK), MDEC(fTrueRef()), "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_FAIL, [] { RETURN_HR_IF(E_FAIL, fTrue); return S_OK; });
- REQUIRE_RETURNS_MSG(E_FAIL, [] { RETURN_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { RETURN_HR_IF_EXPECTED(E_FAIL, fTrue); return S_OK; });
- REQUIRE_THROWS_RESULT(E_FAIL, [] { THROW_HR_IF(E_FAIL, fTrue); });
- REQUIRE_THROWS_MSG(E_FAIL, [] { THROW_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(fTrue == LOG_HR_IF(E_FAIL, fTrue)); });
- REQUIRE_LOG_MSG(E_FAIL, [] { REQUIRE(fTrue == LOG_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_FAIL, [] { FAIL_FAST_HR_IF(E_FAIL, fTrue); });
- REQUIRE_FAILFAST_MSG(E_FAIL, [] { FAIL_FAST_HR_IF_MSG(E_FAIL, fTrue, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF(MDEC(S_OK), MDEC(fFalseRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_EXPECTED(MDEC(S_OK), MDEC(fFalseRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF(MDEC(S_OK), MDEC(fFalseRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF(MDEC(S_OK), MDEC(fFalseRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF(MDEC(S_OK), MDEC(fFalseRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF(E_FAIL, MDEC(fFalseRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_EXPECTED(E_FAIL, MDEC(fFalseRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF(E_FAIL, MDEC(fFalseRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF(E_FAIL, MDEC(fFalseRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF(E_FAIL, MDEC(fFalseRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF(MDEC(S_OK), MDEC(fFalseRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_EXPECTED(MDEC(S_OK), MDEC(fFalseRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF(MDEC(S_OK), MDEC(fFalseRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF(MDEC(S_OK), MDEC(fFalseRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF(MDEC(S_OK), MDEC(fFalseRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF_MSG(MDEC(S_OK), MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF(E_FAIL, MDEC(fFalseRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_EXPECTED(E_FAIL, MDEC(fFalseRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF(E_FAIL, MDEC(fFalseRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(fFalse == THROW_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF(E_FAIL, MDEC(fFalseRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(fFalse == LOG_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF(E_FAIL, MDEC(fFalseRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_HR_IF_MSG(E_FAIL, MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF_NULL(S_OK, pNull); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_NULL_MSG(S_OK, pNull, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_NULL_EXPECTED(S_OK, pNull); return S_OK; });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR_IF_NULL(S_OK, pNull); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_HR_IF_NULL_MSG(S_OK, pNull, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_FAIL, [] { RETURN_HR_IF_NULL(E_FAIL, pNull); return S_OK; });
- REQUIRE_RETURNS_MSG(E_FAIL, [] { RETURN_HR_IF_NULL_MSG(E_FAIL, pNull, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { RETURN_HR_IF_NULL_EXPECTED(E_FAIL, pNull); return S_OK; });
- REQUIRE_THROWS_RESULT(E_FAIL, [] { THROW_HR_IF_NULL(E_FAIL, pNull); });
- REQUIRE_THROWS_MSG(E_FAIL, [] { THROW_HR_IF_NULL_MSG(E_FAIL, pNull, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(pNull == LOG_HR_IF_NULL(E_FAIL, pNull)); });
- REQUIRE_LOG_MSG(E_FAIL, [] { REQUIRE(pNull == LOG_HR_IF_NULL_MSG(E_FAIL, pNull, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_FAIL, [] { FAIL_FAST_HR_IF_NULL(E_FAIL, pNull); });
- REQUIRE_FAILFAST_MSG(E_FAIL, [] { FAIL_FAST_HR_IF_NULL_MSG(E_FAIL, pNull, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF_NULL(MDEC(S_OK), MDEC(pValidRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_NULL_MSG(MDEC(S_OK), MDEC(pValidRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_NULL_EXPECTED(MDEC(S_OK), MDEC(pValidRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(pValid == THROW_HR_IF_NULL(MDEC(S_OK), MDEC(pValidRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(pValid == THROW_HR_IF_NULL_MSG(MDEC(S_OK), MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(pValid == LOG_HR_IF_NULL(MDEC(S_OK), MDEC(pValidRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(pValid == LOG_HR_IF_NULL_MSG(MDEC(S_OK), MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(pValid == FAIL_FAST_HR_IF_NULL(MDEC(S_OK), MDEC(pValidRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(pValid == FAIL_FAST_HR_IF_NULL_MSG(MDEC(S_OK), MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_HR_IF_NULL(E_FAIL, MDEC(pValidRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_HR_IF_NULL_MSG(E_FAIL, MDEC(pValidRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_HR_IF_NULL_EXPECTED(E_FAIL, MDEC(pValidRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(pValid == THROW_HR_IF_NULL(E_FAIL, MDEC(pValidRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(pValid == THROW_HR_IF_NULL_MSG(E_FAIL, MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(pValid == LOG_HR_IF_NULL(E_FAIL, MDEC(pValidRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(pValid == LOG_HR_IF_NULL_MSG(E_FAIL, MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(pValid == FAIL_FAST_HR_IF_NULL(E_FAIL, MDEC(pValidRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(pValid == FAIL_FAST_HR_IF_NULL_MSG(E_FAIL, MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { ::SetLastError(0); FAIL_FAST_LAST_ERROR_IF(fTrue); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { ::SetLastError(0); FAIL_FAST_LAST_ERROR_IF_MSG(fTrue, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_AD, [] { SetAD(); RETURN_LAST_ERROR_IF(fTrue); return S_OK; });
- REQUIRE_RETURNS_MSG(E_AD, [] { SetAD(); RETURN_LAST_ERROR_IF_MSG(fTrue, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_AD, [] { SetAD(); RETURN_LAST_ERROR_IF_EXPECTED(fTrue); return S_OK; });
- REQUIRE_THROWS_RESULT(E_AD, [] { SetAD(); THROW_LAST_ERROR_IF(fTrue); });
- REQUIRE_THROWS_MSG(E_AD, [] { SetAD(); THROW_LAST_ERROR_IF_MSG(fTrue, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_AD, [] { SetAD(); REQUIRE(fTrue == LOG_LAST_ERROR_IF(fTrue)); });
- REQUIRE_LOG_MSG(E_AD, [] { SetAD(); REQUIRE(fTrue == LOG_LAST_ERROR_IF_MSG(fTrue, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_AD, [] { SetAD(); FAIL_FAST_LAST_ERROR_IF(fTrue); });
- REQUIRE_FAILFAST_MSG(E_AD, [] { SetAD(); FAIL_FAST_LAST_ERROR_IF_MSG(fTrue, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_LAST_ERROR_IF(MDEC(fFalseRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_LAST_ERROR_IF_MSG(MDEC(fFalseRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_LAST_ERROR_IF_EXPECTED(MDEC(fFalseRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(fFalse == THROW_LAST_ERROR_IF(MDEC(fFalseRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(fFalse == THROW_LAST_ERROR_IF_MSG(MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(fFalse == LOG_LAST_ERROR_IF(MDEC(fFalseRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(fFalse == LOG_LAST_ERROR_IF_MSG(MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_LAST_ERROR_IF(MDEC(fFalseRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_LAST_ERROR_IF_MSG(MDEC(fFalseRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { ::SetLastError(0); FAIL_FAST_LAST_ERROR_IF_NULL(pNull); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { ::SetLastError(0); FAIL_FAST_LAST_ERROR_IF_NULL_MSG(pNull, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_AD, [] { SetAD(); RETURN_LAST_ERROR_IF_NULL(pNull); return S_OK; });
- REQUIRE_RETURNS_MSG(E_AD, [] { SetAD(); RETURN_LAST_ERROR_IF_NULL_MSG(pNull, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_AD, [] { SetAD(); RETURN_LAST_ERROR_IF_NULL_EXPECTED(pNull); return S_OK; });
- REQUIRE_THROWS_RESULT(E_AD, [] { SetAD(); THROW_LAST_ERROR_IF_NULL(pNull); });
- REQUIRE_THROWS_MSG(E_AD, [] { SetAD(); THROW_LAST_ERROR_IF_NULL_MSG(pNull, "msg: %d", __LINE__); });
- REQUIRE_LOG(E_AD, [] { SetAD(); REQUIRE(pNull == LOG_LAST_ERROR_IF_NULL(pNull)); });
- REQUIRE_LOG_MSG(E_AD, [] { SetAD(); REQUIRE(pNull == LOG_LAST_ERROR_IF_NULL_MSG(pNull, "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(E_AD, [] { SetAD(); FAIL_FAST_LAST_ERROR_IF_NULL(pNull); });
- REQUIRE_FAILFAST_MSG(E_AD, [] { SetAD(); FAIL_FAST_LAST_ERROR_IF_NULL_MSG(pNull, "msg: %d", __LINE__); });
- REQUIRE_RETURNS(S_OK, [] { RETURN_LAST_ERROR_IF_NULL(MDEC(pValidRef())); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { RETURN_LAST_ERROR_IF_NULL_MSG(MDEC(pValidRef()), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_LAST_ERROR_IF_NULL_EXPECTED(MDEC(pValidRef())); return S_OK; });
- REQUIRE_THROWS_RESULT(S_OK, [] { REQUIRE(pNull != THROW_LAST_ERROR_IF_NULL(MDEC(pValidRef()))); });
- REQUIRE_THROWS_MSG(S_OK, [] { REQUIRE(pNull != THROW_LAST_ERROR_IF_NULL_MSG(MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(pNull != LOG_LAST_ERROR_IF_NULL(MDEC(pValidRef()))); });
- REQUIRE_LOG_MSG(S_OK, [] { REQUIRE(pNull != LOG_LAST_ERROR_IF_NULL_MSG(MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(pNull != FAIL_FAST_LAST_ERROR_IF_NULL(MDEC(pValidRef()))); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { REQUIRE(pNull != FAIL_FAST_LAST_ERROR_IF_NULL_MSG(MDEC(pValidRef()), "msg: %d", __LINE__)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(true == SUCCEEDED_LOG(MDEC(S_OK))); });
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(false == SUCCEEDED_LOG(E_FAIL)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(false == FAILED_LOG(MDEC(S_OK))); });
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(true == FAILED_LOG(E_FAIL)); });
- REQUIRE_LOG(ERROR_SUCCESS, [] { REQUIRE(true == SUCCEEDED_WIN32_LOG(MDEC(ERROR_SUCCESS))); });
- REQUIRE_LOG(HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), [] { REQUIRE(false == SUCCEEDED_WIN32_LOG(ERROR_ACCESS_DENIED)); });
- REQUIRE_LOG(ERROR_SUCCESS, [] { REQUIRE(false == FAILED_WIN32_LOG(MDEC(ERROR_SUCCESS))); });
- REQUIRE_LOG(HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), [] { REQUIRE(true == FAILED_WIN32_LOG(ERROR_ACCESS_DENIED)); });
- REQUIRE_LOG(ntOK, [] { REQUIRE(true == SUCCEEDED_NTSTATUS_LOG(MDEC(ntOK))); });
- REQUIRE_LOG(wil::details::NtStatusToHr(ntFAIL), [] { REQUIRE(false == SUCCEEDED_NTSTATUS_LOG(ntFAIL)); });
- REQUIRE_LOG(ntOK, [] { REQUIRE(false == FAILED_NTSTATUS_LOG(MDEC(ntOK))); });
- REQUIRE_LOG(wil::details::NtStatusToHr(ntFAIL), [] { REQUIRE(true == FAILED_NTSTATUS_LOG(ntFAIL)); });
- // FAIL_FAST_IMMEDIATE* directly invokes __fastfail, which we can't catch, so disabled for now
- // REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_IMMEDIATE(); });
- // REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_IMMEDIATE_IF_FAILED(E_FAIL); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(S_OK == FAIL_FAST_IMMEDIATE_IF_FAILED(MDEC(S_OK))); });
- // REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_IMMEDIATE_IF(fTrue); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(fFalse == FAIL_FAST_IMMEDIATE_IF(MDEC(fFalseRef()))); });
- // REQUIRE_FAILFAST_UNSPECIFIED([] { FAIL_FAST_IMMEDIATE_IF_NULL(pNull); });
- REQUIRE_FAILFAST(S_OK, [] { REQUIRE(pValid == FAIL_FAST_IMMEDIATE_IF_NULL(MDEC(pValidRef()))); });
- #ifdef WIL_ENABLE_EXCEPTIONS
- REQUIRE_RETURNS(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_RETURN(); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_RETURN_MSG("msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_RETURN_EXPECTED(); return S_OK; });
- REQUIRE_LOG(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_LOG(); });
- REQUIRE_LOG_MSG(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_LOG_MSG("msg: %d", __LINE__); });
- REQUIRE_FAILFAST(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_FAIL_FAST(); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_FAIL_FAST_MSG("msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_THROW_NORMALIZED(); });
- REQUIRE_THROWS_MSG(S_OK, [] { try { THROW_IF_FAILED(hrOK); } CATCH_THROW_NORMALIZED_MSG("msg: %d", __LINE__); });
- REQUIRE_RETURNS(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_RETURN(); return S_OK; });
- REQUIRE_RETURNS_MSG(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_RETURN_MSG("msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_RETURN_EXPECTED(); return S_OK; });
- REQUIRE_LOG(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_LOG(); });
- REQUIRE_LOG_MSG(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_LOG_MSG("msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_FAIL_FAST(); });
- REQUIRE_FAILFAST_MSG(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_FAIL_FAST_MSG("msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_THROW_NORMALIZED(); });
- REQUIRE_THROWS_MSG(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_THROW_NORMALIZED_MSG("msg: %d", __LINE__); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { try { if (FAILED(hrFAIL)) { throw E_FAIL; } } CATCH_FAIL_FAST(); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { try { if (FAILED(hrFAIL)) { throw E_FAIL; } } CATCH_FAIL_FAST_MSG("msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_AD, [] { THROW_EXCEPTION(MDEC(DerivedAccessDeniedException())); });
- REQUIRE_THROWS_MSG(E_AD, [] { THROW_EXCEPTION_MSG(MDEC(DerivedAccessDeniedException()), "msg: %d", __LINE__); });
- REQUIRE_LOG(E_AD, [] { try { throw AlternateAccessDeniedException(); } CATCH_LOG(); });
- REQUIRE_THROWS_RESULT(E_AD, [] { try { throw AlternateAccessDeniedException(); } CATCH_THROW_NORMALIZED(); });
- REQUIRE_RETURNS(S_OK, [] { return wil::ResultFromException([] { THROW_IF_FAILED(hrOK); }); });
- REQUIRE_RETURNS(E_FAIL, [] { return wil::ResultFromException([] { THROW_IF_FAILED(hrFAIL); }); });
- REQUIRE(E_AD == wil::ResultFromException([] { throw AlternateAccessDeniedException(); }));
- try { THROW_HR(E_FAIL); }
- catch (...) { REQUIRE(E_FAIL == wil::ResultFromCaughtException()); };
- #endif
- #ifdef WIL_ENABLE_EXCEPTIONS
- REQUIRE_LOG(E_FAIL, [] { try { THROW_IF_FAILED(hrFAIL); } CATCH_LOG(); });
- #endif
- REQUIRE_RETURNS(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; RETURN_IF_NULL_ALLOC(MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; RETURN_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; RETURN_IF_NULL_ALLOC_EXPECTED(MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); RETURN_IF_NULL_ALLOC(MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); RETURN_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); RETURN_IF_NULL_ALLOC_EXPECTED(MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; RETURN_HR_IF_NULL(E_OUTOFMEMORY, MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; RETURN_HR_IF_NULL_MSG(E_OUTOFMEMORY, pInt, "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; RETURN_HR_IF_NULL_EXPECTED(E_OUTOFMEMORY, MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); RETURN_HR_IF_NULL(E_OUTOFMEMORY, MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); RETURN_HR_IF_NULL_MSG(E_OUTOFMEMORY, MDEC(pInt), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); RETURN_HR_IF_NULL_EXPECTED(E_OUTOFMEMORY, MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); RETURN_LAST_ERROR_IF_NULL(MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS_MSG(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); RETURN_LAST_ERROR_IF_NULL_MSG(MDEC(pInt), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); RETURN_LAST_ERROR_IF_NULL_EXPECTED(MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); SetAD(); RETURN_LAST_ERROR_IF_NULL(MDEC(pInt)); return S_OK; });
- REQUIRE_RETURNS_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); SetAD(); RETURN_LAST_ERROR_IF_NULL_MSG(MDEC(pInt), "msg: %d", __LINE__); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); SetAD(); RETURN_LAST_ERROR_IF_NULL_EXPECTED(MDEC(pInt)); return S_OK; });
- REQUIRE_THROWS_RESULT(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; THROW_IF_NULL_ALLOC(MDEC(pInt)); });
- REQUIRE_THROWS_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; THROW_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_LOG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; LOG_IF_NULL_ALLOC(MDEC(pInt)); });
- REQUIRE_LOG_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; LOG_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; FAIL_FAST_IF_NULL_ALLOC(MDEC(pInt)); });
- REQUIRE_FAILFAST_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; FAIL_FAST_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); THROW_IF_NULL_ALLOC(MDEC(pInt)); });
- REQUIRE_THROWS_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); THROW_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_LOG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); LOG_IF_NULL_ALLOC(MDEC(pInt)); });
- REQUIRE_LOG_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); LOG_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_IF_NULL_ALLOC(MDEC(pInt)); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_IF_NULL_ALLOC_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_LOG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; LOG_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(pInt)); });
- REQUIRE_LOG_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; LOG_HR_IF_NULL_MSG(MDEC(E_OUTOFMEMORY), MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_FAIL, [] { std::unique_ptr<int> pInt; FAIL_FAST_HR_IF_NULL(MDEC(E_FAIL), MDEC(pInt)); });
- REQUIRE_FAILFAST_MSG(E_FAIL, [] { std::unique_ptr<int> pInt; FAIL_FAST_HR_IF_NULL_MSG(MDEC(E_FAIL), MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; THROW_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(pInt)); });
- REQUIRE_THROWS_MSG(E_OUTOFMEMORY, [] { std::unique_ptr<int> pInt; THROW_HR_IF_NULL_MSG(MDEC(E_OUTOFMEMORY), MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_LOG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); LOG_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(pInt)); });
- REQUIRE_LOG_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); LOG_HR_IF_NULL_MSG(MDEC(E_OUTOFMEMORY), MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_HR_IF_NULL(MDEC(E_FAIL), MDEC(pInt)); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_HR_IF_NULL_MSG(MDEC(E_FAIL), MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); THROW_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(pInt)); });
- REQUIRE_THROWS_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); THROW_HR_IF_NULL_MSG(MDEC(E_OUTOFMEMORY), MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_LOG(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); LOG_LAST_ERROR_IF_NULL(MDEC(pInt)); });
- REQUIRE_LOG_MSG(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); LOG_LAST_ERROR_IF_NULL_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); FAIL_FAST_LAST_ERROR_IF_NULL(pInt); });
- REQUIRE_FAILFAST_MSG(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); FAIL_FAST_LAST_ERROR_IF_NULL_MSG(pInt, "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); THROW_LAST_ERROR_IF_NULL(MDEC(pInt)); });
- REQUIRE_THROWS_MSG(E_AD, [] { std::unique_ptr<int> pInt; SetAD(); THROW_LAST_ERROR_IF_NULL_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_LOG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); LOG_LAST_ERROR_IF_NULL(MDEC(pInt)); });
- REQUIRE_LOG_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); LOG_LAST_ERROR_IF_NULL_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- REQUIRE_FAILFAST(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_LAST_ERROR_IF_NULL(pInt); });
- REQUIRE_FAILFAST_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_LAST_ERROR_IF_NULL_MSG(pInt, "msg: %d", __LINE__); });
- REQUIRE_THROWS_RESULT(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); THROW_LAST_ERROR_IF_NULL(MDEC(pInt)); });
- REQUIRE_THROWS_MSG(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); THROW_LAST_ERROR_IF_NULL_MSG(MDEC(pInt), "msg: %d", __LINE__); });
- // REQUIRE_FAILFAST_UNSPECIFIED([] { std::unique_ptr<int> pInt; FAIL_FAST_IMMEDIATE_IF_NULL(pNull); });
- REQUIRE_FAILFAST(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_IMMEDIATE_IF_NULL(MDEC(pValidRef())); });
- REQUIRE_FAILFAST_UNSPECIFIED([] { std::unique_ptr<int> pInt; FAIL_FAST_IF_NULL(pNull); });
- REQUIRE_FAILFAST(S_OK, [] { std::unique_ptr<int> pInt(new int(5)); FAIL_FAST_IF_NULL(MDEC(pInt)); });
- REQUIRE_RETURNS(E_OUTOFMEMORY, [] { Microsoft::WRL::ComPtr<IUnknown> ptr; RETURN_IF_NULL_ALLOC(MDEC(ptr)); return S_OK; });
- REQUIRE_LOG(E_OUTOFMEMORY, [] { Microsoft::WRL::ComPtr<IUnknown> ptr; LOG_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(ptr)); });
- REQUIRE_RETURNS(E_OUTOFMEMORY, [] { std::shared_ptr<int> ptr; RETURN_IF_NULL_ALLOC(MDEC(ptr)); return S_OK; });
- REQUIRE_LOG(E_OUTOFMEMORY, [] { std::shared_ptr<int> ptr; LOG_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(ptr)); });
- REQUIRE_RETURNS(S_OK, [] { std::shared_ptr<int> ptr(new int(5)); RETURN_IF_NULL_ALLOC(MDEC(ptr)); return S_OK; });
- REQUIRE_LOG(S_OK, [] { std::shared_ptr<int> ptr(new int(5)); LOG_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(ptr)); });
- #ifdef __cplusplus_winrt
- REQUIRE_RETURNS(E_OUTOFMEMORY, [] { Platform::String^ str(nullptr); RETURN_IF_NULL_ALLOC(MDEC(str)); return S_OK; });
- REQUIRE_LOG(E_OUTOFMEMORY, [] { Platform::String^ str(nullptr); LOG_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(str)); });
- REQUIRE_RETURNS(S_OK, [] { Platform::String^ str(L"a"); RETURN_IF_NULL_ALLOC(MDEC(str)); return S_OK; });
- REQUIRE_LOG(S_OK, [] { Platform::String^ str(L"a"); LOG_HR_IF_NULL(MDEC(E_OUTOFMEMORY), MDEC(str)); });
- #endif
- }
- #define WRAP_LAMBDA(code) [&] {code;};
- //these macros should all have compile errors due to use of an invalid type
- void InvalidTypeChecks()
- {
- std::unique_ptr<int> boolCastClass;
- std::vector<int> noBoolCastClass;
- //WRAP_LAMBDA(RETURN_IF_FAILED(fTrue));
- //WRAP_LAMBDA(RETURN_IF_FAILED(fTRUE));
- //WRAP_LAMBDA(RETURN_IF_FAILED(boolCastClass));
- //WRAP_LAMBDA(RETURN_IF_FAILED(noBoolCastClass));
- //WRAP_LAMBDA(RETURN_IF_FAILED(errSuccess));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE(fTrue));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE(noBoolCastClass));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE(hrOK));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE(errSuccess));
- //WRAP_LAMBDA(RETURN_HR_IF(errSuccess, false));
- //WRAP_LAMBDA(RETURN_HR_IF(errSuccess, true));
- //WRAP_LAMBDA(RETURN_HR_IF(hrOK, noBoolCastClass));
- //WRAP_LAMBDA(RETURN_HR_IF(hrOK, hrOK));
- //WRAP_LAMBDA(RETURN_HR_IF(hrOK, errSuccess));
- //WRAP_LAMBDA(RETURN_HR_IF_NULL(errSuccess, nullptr));
- //WRAP_LAMBDA(RETURN_HR_IF_NULL(errSuccess, pValid));
- //WRAP_LAMBDA(RETURN_LAST_ERROR_IF(noBoolCastClass));
- //WRAP_LAMBDA(RETURN_LAST_ERROR_IF(errSuccess));
- //WRAP_LAMBDA(RETURN_LAST_ERROR_IF(hrOK));
- //WRAP_LAMBDA(RETURN_IF_FAILED_EXPECTED(fTrue));
- //WRAP_LAMBDA(RETURN_IF_FAILED_EXPECTED(fTRUE));
- //WRAP_LAMBDA(RETURN_IF_FAILED_EXPECTED(boolCastClass));
- //WRAP_LAMBDA(RETURN_IF_FAILED_EXPECTED(noBoolCastClass));
- //WRAP_LAMBDA(RETURN_IF_FAILED_EXPECTED(errSuccess));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(fTrue));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(noBoolCastClass));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(hrOK));
- //WRAP_LAMBDA(RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(errSuccess));
- //LOG_IF_FAILED(fTrue);
- //LOG_IF_FAILED(fTRUE);
- //LOG_IF_FAILED(boolCastClass);
- //LOG_IF_FAILED(noBoolCastClass);
- //LOG_IF_FAILED(errSuccess);
- //LOG_IF_WIN32_BOOL_FALSE(fTrue);
- //LOG_IF_WIN32_BOOL_FALSE(noBoolCastClass);
- //LOG_IF_WIN32_BOOL_FALSE(hrOK);
- //LOG_IF_WIN32_BOOL_FALSE(errSuccess);
- //LOG_HR_IF(errSuccess, false);
- //LOG_HR_IF(errSuccess, true);
- //LOG_HR_IF(hrOK, noBoolCastClass);
- //LOG_HR_IF(hrOK, hrOK);
- //LOG_HR_IF(hrOK, errSuccess);
- //FAIL_FAST_IF_FAILED(fTrue);
- //FAIL_FAST_IF_FAILED(fTRUE);
- //FAIL_FAST_IF_FAILED(boolCastClass);
- //FAIL_FAST_IF_FAILED(noBoolCastClass);
- //FAIL_FAST_IF_FAILED(errSuccess);
- //FAIL_FAST_IF_WIN32_BOOL_FALSE(fTrue);
- //FAIL_FAST_IF_WIN32_BOOL_FALSE(noBoolCastClass);
- //FAIL_FAST_IF_WIN32_BOOL_FALSE(hrOK);
- //FAIL_FAST_IF_WIN32_BOOL_FALSE(errSuccess);
- //FAIL_FAST_HR_IF(errSuccess, false);
- //FAIL_FAST_HR_IF(errSuccess, true);
- //FAIL_FAST_HR_IF(hrOK, noBoolCastClass);
- //FAIL_FAST_HR_IF(hrOK, hrOK);
- //FAIL_FAST_HR_IF(hrOK, errSuccess);
- //THROW_IF_FAILED(fTrue);
- //THROW_IF_FAILED(fTRUE);
- //THROW_IF_FAILED(boolCastClass);
- //THROW_IF_FAILED(noBoolCastClass);
- //THROW_IF_FAILED(errSuccess);
- //THROW_IF_WIN32_BOOL_FALSE(fTrue);
- //THROW_IF_WIN32_BOOL_FALSE(noBoolCastClass);
- //THROW_IF_WIN32_BOOL_FALSE(hrOK);
- //THROW_IF_WIN32_BOOL_FALSE(errSuccess);
- //THROW_HR_IF(errSuccess, false);
- //THROW_HR_IF(errSuccess, true);
- //THROW_HR_IF(hrOK, noBoolCastClass);
- //THROW_HR_IF(hrOK, hrOK);
- //THROW_HR_IF(hrOK, errSuccess);
- //FAIL_FAST_IF(noBoolCastClass);
- //FAIL_FAST_IF(hrOK);
- //FAIL_FAST_IF(errSuccess);
- //FAIL_FAST_IMMEDIATE_IF_FAILED(fTrue);
- //FAIL_FAST_IMMEDIATE_IF_FAILED(fTRUE);
- //FAIL_FAST_IMMEDIATE_IF_FAILED(boolCastClass);
- //FAIL_FAST_IMMEDIATE_IF_FAILED(noBoolCastClass);
- //FAIL_FAST_IMMEDIATE_IF_FAILED(errSuccess);
- //FAIL_FAST_IMMEDIATE_IF(noBoolCastClass);
- //FAIL_FAST_IMMEDIATE_IF(hrOK);
- //FAIL_FAST_IMMEDIATE_IF(errSuccess);
- }
- TEST_CASE("WindowsInternalTests::UniqueHandle", "[resource][unique_any]")
- {
- {
- // default construction test
- wil::unique_handle spHandle;
- REQUIRE(spHandle.get() == nullptr);
- // null ptr assignment creation
- wil::unique_handle spNullHandle = nullptr;
- REQUIRE(spNullHandle.get() == nullptr);
- // explicit construction from the invalid value
- wil::unique_handle spInvalidHandle(nullptr);
- REQUIRE(spInvalidHandle.get() == nullptr);
- // valid handle creation
- wil::unique_handle spValidHandle(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- REQUIRE(spValidHandle.get() != nullptr);
- auto const handleValue = spValidHandle.get();
- // r-value construction
- wil::unique_handle spMoveHandle = wistd::move(spValidHandle);
- REQUIRE(spValidHandle.get() == nullptr);
- REQUIRE(spMoveHandle.get() == handleValue);
- // nullptr-assignment
- spNullHandle = nullptr;
- REQUIRE(spNullHandle.get() == nullptr);
- // r-value assignment
- spValidHandle = wistd::move(spMoveHandle);
- REQUIRE(spValidHandle.get() == handleValue);
- REQUIRE(spMoveHandle.get() == nullptr);
- // swap
- spValidHandle.swap(spMoveHandle);
- REQUIRE(spValidHandle.get() == nullptr);
- REQUIRE(spMoveHandle.get() == handleValue);
- // operator bool
- REQUIRE_FALSE(spValidHandle);
- REQUIRE(spMoveHandle);
- // release
- auto ptrValidHandle = spValidHandle.release();
- auto ptrMoveHandle = spMoveHandle.release();
- REQUIRE(ptrValidHandle == nullptr);
- REQUIRE(ptrMoveHandle == handleValue);
- REQUIRE(spValidHandle.get() == nullptr);
- REQUIRE(spMoveHandle.get() == nullptr);
- // reset
- spValidHandle.reset();
- spMoveHandle.reset();
- REQUIRE(spValidHandle.get() == nullptr);
- REQUIRE(spMoveHandle.get() == nullptr);
- spValidHandle.reset(ptrValidHandle);
- spMoveHandle.reset(ptrMoveHandle);
- REQUIRE(spValidHandle.get() == nullptr);
- REQUIRE(spMoveHandle.get() == handleValue);
- spNullHandle.reset(nullptr);
- REQUIRE(spNullHandle.get() == nullptr);
- // address
- REQUIRE(*spMoveHandle.addressof() == handleValue);
- REQUIRE(*spMoveHandle.put() == nullptr);
- *spMoveHandle.put() = ::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0);
- REQUIRE(spMoveHandle);
- REQUIRE(*(&spMoveHandle) == nullptr);
- *(&spMoveHandle) = ::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0);
- REQUIRE(spMoveHandle);
- }
- {
- // default construction test
- wil::unique_hfile spHandle;
- REQUIRE(spHandle.get() == INVALID_HANDLE_VALUE);
- // implicit construction from the invalid value
- wil::unique_hfile spNullHandle; // = nullptr; // method explicitly disabled as nullptr isn't the invalid value
- REQUIRE(spNullHandle.get() == INVALID_HANDLE_VALUE);
- // assignment from the invalid value
- // spNullHandle = nullptr; // method explicitly disabled as nullptr isn't the invalid value
- REQUIRE(spNullHandle.get() == INVALID_HANDLE_VALUE);
- // explicit construction from the invalid value
- wil::unique_hfile spInvalidHandle(INVALID_HANDLE_VALUE);
- REQUIRE(spInvalidHandle.get() == INVALID_HANDLE_VALUE);
- // valid handle creation
- wchar_t tempFileName[MAX_PATH];
- REQUIRE_SUCCEEDED(witest::GetTempFileName(tempFileName));
- #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- CREATEFILE2_EXTENDED_PARAMETERS params = { sizeof(params) };
- params.dwFileAttributes = FILE_ATTRIBUTE_TEMPORARY;
- wil::unique_hfile spValidHandle(::CreateFile2(tempFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE, CREATE_ALWAYS, ¶ms));
- #else
- wil::unique_hfile spValidHandle(::CreateFileW(tempFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, nullptr));
- #endif
- ::DeleteFileW(tempFileName);
- REQUIRE(spValidHandle.get() != INVALID_HANDLE_VALUE);
- auto const handleValue = spValidHandle.get();
- // r-value construction
- wil::unique_hfile spMoveHandle = wistd::move(spValidHandle);
- REQUIRE(spValidHandle.get() == INVALID_HANDLE_VALUE);
- REQUIRE(spMoveHandle.get() == handleValue);
- // nullptr-assignment -- uncomment to check intentional compilation error
- // spNullHandle = nullptr;
- // r-value assignment
- spValidHandle = wistd::move(spMoveHandle);
- REQUIRE(spValidHandle.get() == handleValue);
- REQUIRE(spMoveHandle.get() == INVALID_HANDLE_VALUE);
- // swap
- spValidHandle.swap(spMoveHandle);
- REQUIRE(spValidHandle.get() == INVALID_HANDLE_VALUE);
- REQUIRE(spMoveHandle.get() == handleValue);
- // operator bool
- REQUIRE_FALSE(spValidHandle);
- REQUIRE(spMoveHandle);
- // release
- auto ptrValidHandle = spValidHandle.release();
- auto ptrMoveHandle = spMoveHandle.release();
- REQUIRE(ptrValidHandle == INVALID_HANDLE_VALUE);
- REQUIRE(ptrMoveHandle == handleValue);
- REQUIRE(spValidHandle.get() == INVALID_HANDLE_VALUE);
- REQUIRE(spMoveHandle.get() == INVALID_HANDLE_VALUE);
- // reset
- spValidHandle.reset();
- spMoveHandle.reset();
- REQUIRE(spValidHandle.get() == INVALID_HANDLE_VALUE);
- REQUIRE(spMoveHandle.get() == INVALID_HANDLE_VALUE);
- spValidHandle.reset(ptrValidHandle);
- spMoveHandle.reset(ptrMoveHandle);
- REQUIRE(spValidHandle.get() == INVALID_HANDLE_VALUE);
- REQUIRE(spMoveHandle.get() == handleValue);
- // uncomment to test intentional compilation error due to conflict with INVALID_HANDLE_VALUE
- // spNullHandle.reset(nullptr);
- // address
- REQUIRE(*spMoveHandle.addressof() == handleValue);
- REQUIRE(*(&spMoveHandle) == INVALID_HANDLE_VALUE);
- wchar_t tempFileName2[MAX_PATH];
- REQUIRE_SUCCEEDED(witest::GetTempFileName(tempFileName2));
- #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- CREATEFILE2_EXTENDED_PARAMETERS params2 = { sizeof(params2) };
- params2.dwFileAttributes = FILE_ATTRIBUTE_TEMPORARY;
- *(&spMoveHandle) = ::CreateFile2(tempFileName2, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE, CREATE_ALWAYS, ¶ms2);
- #else
- *(&spMoveHandle) = ::CreateFileW(tempFileName2, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, nullptr);
- #endif
- ::DeleteFileW(tempFileName2);
- REQUIRE(spMoveHandle);
- // ensure that mistaken nullptr usage is not valid...
- spMoveHandle.reset();
- *(&spMoveHandle) = nullptr;
- REQUIRE_FALSE(spMoveHandle);
- }
- auto hFirst = ::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0);
- auto hSecond= ::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0);
- wil::unique_handle spLeft(hFirst);
- wil::unique_handle spRight(hSecond);
- REQUIRE(spRight.get() == hSecond);
- REQUIRE(spLeft.get() == hFirst);
- swap(spLeft, spRight);
- REQUIRE(spLeft.get() == hSecond);
- REQUIRE(spRight.get() == hFirst);
- swap(spLeft, spRight);
- REQUIRE((spLeft.get() == spRight.get()) == (spLeft == spRight));
- REQUIRE((spLeft.get() != spRight.get()) == (spLeft != spRight));
- REQUIRE((spLeft.get() < spRight.get()) == (spLeft < spRight));
- REQUIRE((spLeft.get() <= spRight.get()) == (spLeft <= spRight));
- REQUIRE((spLeft.get() >= spRight.get()) == (spLeft >= spRight));
- REQUIRE((spLeft.get() > spRight.get()) == (spLeft > spRight));
- // test stl container use (hash & std::less)
- #ifdef WIL_ENABLE_EXCEPTIONS
- std::unordered_set<wil::unique_handle> hashSet;
- hashSet.insert(std::move(spLeft));
- hashSet.insert(std::move(spRight));
- std::multiset<wil::unique_handle> set;
- set.insert(std::move(spLeft));
- set.insert(std::move(spRight));
- #endif
- }
- #ifdef WIL_ENABLE_EXCEPTIONS
- TEST_CASE("WindowsInternalTests::SharedHandle", "[resource][shared_any]")
- {
- // default construction
- wil::shared_handle spHandle;
- REQUIRE(spHandle.get() == nullptr);
- // pointer construction
- wil::shared_handle spValid(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- auto ptr = spValid.get();
- REQUIRE(spValid.get() != nullptr);
- // null construction
- wil::shared_handle spNull = nullptr;
- REQUIRE(spNull.get() == nullptr);
- // Present to verify that it doesn't compile (disabled)
- // wil::shared_hfile spFile = nullptr;
- // copy construction
- wil::shared_handle spCopy = spValid;
- REQUIRE(spCopy.get() == ptr);
- // r-value construction
- wil::shared_handle spMove = wistd::move(spCopy);
- REQUIRE(spMove.get() == ptr);
- REQUIRE(spCopy.get() == nullptr);
- // unique handle construction
- wil::shared_handle spFromUnique = wil::unique_handle(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- REQUIRE(spFromUnique.get() != nullptr);
- // direct assignment
- wil::shared_handle spAssign;
- spAssign = spValid;
- REQUIRE(spAssign.get() == ptr);
- // empty reset
- spFromUnique.reset();
- REQUIRE(spFromUnique.get() == nullptr);
- // reset against unique ptr
- spFromUnique.reset(wil::unique_handle(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0)));
- REQUIRE(spFromUnique.get() != nullptr);
- // reset against raw pointer
- spAssign.reset(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- REQUIRE(spAssign.get() != nullptr);
- REQUIRE(spAssign.get() != ptr);
- // ref-count checks
- REQUIRE(spAssign.use_count() == 1);
- // bool operator
- REQUIRE(spAssign);
- spAssign.reset();
- REQUIRE_FALSE(spAssign);
- // swap and compare
- wil::shared_handle sp1(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- wil::shared_handle sp2(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- auto ptr1 = sp1.get();
- auto ptr2 = sp2.get();
- sp1.swap(sp2);
- REQUIRE(sp1.get() == ptr2);
- REQUIRE(sp2.get() == ptr1);
- swap(sp1, sp2);
- REQUIRE(sp1.get() == ptr1);
- REQUIRE(sp2.get() == ptr2);
- REQUIRE((ptr1 == ptr2) == (sp1 == sp2));
- REQUIRE((ptr1 != ptr2) == (sp1 != sp2));
- REQUIRE((ptr1 < ptr2) == (sp1 < sp2));
- REQUIRE((ptr1 <= ptr2) == (sp1 <= sp2));
- REQUIRE((ptr1 > ptr2) == (sp1 > sp2));
- REQUIRE((ptr1 >= ptr2) == (sp1 >= sp2));
- // construction
- wil::weak_handle wh;
- REQUIRE_FALSE(wh.lock());
- wil::weak_handle wh1 = sp1;
- REQUIRE(wh1.lock());
- REQUIRE(wh1.lock().get() == ptr1);
- wil::weak_handle wh1copy = wh1;
- REQUIRE(wh1copy.lock());
- // assignment
- wh = wh1;
- REQUIRE(wh.lock().get() == ptr1);
- wh = sp2;
- REQUIRE(wh.lock().get() == ptr2);
- // reset
- wh.reset();
- REQUIRE_FALSE(wh.lock());
- // expiration
- wh = sp1;
- sp1.reset();
- REQUIRE(wh.expired());
- REQUIRE_FALSE(wh.lock());
- // swap
- wh1 = sp1;
- wil::weak_handle wh2 = sp2;
- ptr1 = sp1.get();
- ptr2 = sp2.get();
- REQUIRE(wh1.lock().get() == ptr1);
- REQUIRE(wh2.lock().get() == ptr2);
- wh1.swap(wh2);
- REQUIRE(wh1.lock().get() == ptr2);
- REQUIRE(wh2.lock().get() == ptr1);
- swap(wh1, wh2);
- REQUIRE(wh1.lock().get() == ptr1);
- REQUIRE(wh2.lock().get() == ptr2);
- // put
- sp1.reset(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- REQUIRE(sp1);
- sp1.put(); // frees the pointer...
- REQUIRE_FALSE(sp1);
- sp2 = sp1;
- REQUIRE_FALSE(sp2);
- *sp1.put() = ::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0);
- REQUIRE(sp1);
- REQUIRE_FALSE(sp2);
- // address
- sp1.reset(::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0));
- REQUIRE(sp1);
- &sp1; // frees the pointer...
- REQUIRE_FALSE(sp1);
- sp2 = sp1;
- REQUIRE_FALSE(sp2);
- *(&sp1) = ::CreateEventEx(nullptr, nullptr, CREATE_EVENT_INITIAL_SET, 0);
- REQUIRE(sp1);
- REQUIRE_FALSE(sp2);
- // test stl container use (hash & std::less)
- std::unordered_set<wil::shared_handle> hashSet;
- hashSet.insert(sp1);
- hashSet.insert(sp2);
- std::set<wil::shared_handle> set;
- set.insert(sp1);
- set.insert(sp2);
- }
- #endif
- template <typename event_t>
- void EventTestCommon()
- {
- // Constructor tests...
- event_t e1;
- REQUIRE_FALSE(e1);
- event_t e2(::CreateEventEx(nullptr, nullptr, 0, 0));
- REQUIRE(e2);
- wil::unique_handle h1(::CreateEventEx(nullptr, nullptr, 0, 0));
- REQUIRE(h1);
- event_t e3(h1.release());
- REQUIRE(e3);
- REQUIRE_FALSE(h1);
- event_t e4(std::move(e2));
- REQUIRE(e4);
- REQUIRE_FALSE(e2);
- // inherited address tests...
- REQUIRE(e4);
- &e4;
- REQUIRE_FALSE(e4);
- auto hFill = ::CreateEventEx(nullptr, nullptr, 0, 0);
- *(&e4) = hFill;
- REQUIRE(e4);
- REQUIRE(*e4.addressof() == hFill);
- REQUIRE(e4);
- // assignment...
- event_t e5;
- e5 = std::move(e4);
- REQUIRE(e5);
- REQUIRE_FALSE(e4);
- // various event-based tests
- event_t eManual;
- eManual.create(wil::EventOptions::ManualReset);
- REQUIRE_FALSE(eManual.is_signaled());
- eManual.SetEvent();
- REQUIRE(eManual.is_signaled());
- eManual.ResetEvent();
- REQUIRE_FALSE(eManual.is_signaled());
- {
- auto exit = eManual.SetEvent_scope_exit();
- REQUIRE_FALSE(eManual.is_signaled());
- }
- REQUIRE(eManual.is_signaled());
- {
- auto exit = eManual.ResetEvent_scope_exit();
- REQUIRE(eManual.is_signaled());
- }
- REQUIRE_FALSE(eManual.is_signaled());
- REQUIRE_FALSE(eManual.wait(50));
- REQUIRE_FALSE(wil::handle_wait(eManual.get(), 50));
- eManual.SetEvent();
- REQUIRE(eManual.wait(50));
- REQUIRE(wil::handle_wait(eManual.get(), 50));
- REQUIRE(eManual.wait(50));
- REQUIRE(eManual.try_create(wil::EventOptions::ManualReset, L"IExist"));
- REQUIRE_FALSE(eManual.try_open(L"IDontExist"));
- }
- template <typename mutex_t>
- void MutexTestCommon()
- {
- // Constructor tests...
- mutex_t m1;
- REQUIRE_FALSE(m1);
- mutex_t m2(::CreateMutexEx(nullptr, nullptr, 0, 0));
- REQUIRE(m2);
- wil::unique_handle h1(::CreateMutexEx(nullptr, nullptr, 0, 0));
- REQUIRE(h1);
- mutex_t m3(h1.release());
- REQUIRE(m3);
- REQUIRE_FALSE(h1);
- mutex_t m4(std::move(m2));
- REQUIRE(m4);
- REQUIRE_FALSE(m2);
- // inherited address tests...
- REQUIRE(m4);
- &m4;
- REQUIRE_FALSE(m4);
- auto hFill = ::CreateMutexEx(nullptr, nullptr, 0, 0);
- *(&m4) = hFill;
- REQUIRE(m4);
- REQUIRE(*m4.addressof() == hFill);
- REQUIRE(m4);
- // assignment...
- mutex_t m5;
- m5 = std::move(m4);
- REQUIRE(m5);
- REQUIRE_FALSE(m4);
- // various mutex-based tests
- mutex_t eManual;
- eManual.create(nullptr, CREATE_MUTEX_INITIAL_OWNER);
- eManual.ReleaseMutex();
- eManual.create(nullptr, CREATE_MUTEX_INITIAL_OWNER);
- {
- auto release = eManual.ReleaseMutex_scope_exit();
- }
- {
- DWORD dwStatus;
- auto release = eManual.acquire(&dwStatus);
- REQUIRE(release);
- REQUIRE(dwStatus == WAIT_OBJECT_0);
- }
- // pass-through methods -- test compilation;
- REQUIRE(eManual.try_create(L"FOO-TEST"));
- REQUIRE(eManual.try_open(L"FOO-TEST"));
- }
- template <typename semaphore_t>
- void SemaphoreTestCommon()
- {
- // Constructor tests...
- semaphore_t m1;
- REQUIRE_FALSE(m1);
- semaphore_t m2(::CreateSemaphoreEx(nullptr, 1, 1, nullptr, 0, 0));
- REQUIRE(m2);
- wil::unique_handle h1(::CreateSemaphoreEx(nullptr, 1, 1, nullptr, 0, 0));
- REQUIRE(h1);
- semaphore_t m3(h1.release());
- REQUIRE(m3);
- REQUIRE_FALSE(h1);
- semaphore_t m4(std::move(m2));
- REQUIRE(m4);
- REQUIRE_FALSE(m2);
- // inherited address tests...
- REQUIRE(m4);
- &m4;
- REQUIRE_FALSE(m4);
- auto hFill = ::CreateSemaphoreEx(nullptr, 1, 1, nullptr, 0, 0);
- *(&m4) = hFill;
- REQUIRE(m4);
- REQUIRE(*m4.addressof() == hFill);
- REQUIRE(m4);
- // assignment...
- semaphore_t m5;
- m5 = std::move(m4);
- REQUIRE(m5);
- REQUIRE_FALSE(m4);
- // various semaphore-based tests
- semaphore_t eManual;
- eManual.create(1, 1);
- WaitForSingleObjectEx(eManual.get(), INFINITE, true);
- eManual.ReleaseSemaphore();
- eManual.create(1, 1);
- WaitForSingleObjectEx(eManual.get(), INFINITE, true);
- {
- auto release = eManual.ReleaseSemaphore_scope_exit();
- }
- {
- DWORD dwStatus;
- auto release = eManual.acquire(&dwStatus);
- REQUIRE(release);
- REQUIRE(dwStatus == WAIT_OBJECT_0);
- }
- // pass-through methods -- test compilation;
- REQUIRE(eManual.try_create(1, 1, L"BAR-TEST"));
- REQUIRE(eManual.try_open(L"BAR-TEST"));
- }
- template <typename test_t>
- void MutexRaiiTests()
- {
- test_t var1;
- var1.create();
- {
- REQUIRE(var1.acquire());
- }
- // try_create
- bool exists = false;
- REQUIRE(var1.try_create(L"wiltestmutex", 0, MUTEX_ALL_ACCESS, nullptr, &exists));
- REQUIRE_FALSE(exists);
- test_t var2;
- REQUIRE(var2.try_create(L"wiltestmutex", 0, MUTEX_ALL_ACCESS, nullptr, &exists));
- REQUIRE(exists);
- test_t var3;
- REQUIRE_FALSE(var3.try_create(L"\\illegal\\chars\\too\\\\many\\\\namespaces", 0, MUTEX_ALL_ACCESS, nullptr, &exists));
- REQUIRE(::GetLastError() != ERROR_SUCCESS);
- // try_open
- test_t var4;
- REQUIRE_FALSE(var4.try_open(L"\\illegal\\chars\\too\\\\many\\\\namespaces"));
- REQUIRE(::GetLastError() != ERROR_SUCCESS);
- REQUIRE(var4.try_open(L"wiltestmutex"));
- }
- template <typename test_t>
- void SemaphoreRaiiTests()
- {
- test_t var1;
- var1.create(1, 1);
- {
- REQUIRE(var1.acquire());
- }
- // try_create
- bool exists = false;
- REQUIRE(var1.try_create(1, 1, L"wiltestsemaphore", MUTEX_ALL_ACCESS, nullptr, &exists));
- REQUIRE_FALSE(exists);
- test_t var2;
- REQUIRE(var2.try_create(1, 1, L"wiltestsemaphore", MUTEX_ALL_ACCESS, nullptr, &exists));
- REQUIRE(exists);
- test_t var3;
- REQUIRE_FALSE(var3.try_create(1, 1, L"\\illegal\\chars\\too\\\\many\\\\namespaces", MUTEX_ALL_ACCESS, nullptr, &exists));
- REQUIRE(::GetLastError() != ERROR_SUCCESS);
- // try_open
- test_t var4;
- REQUIRE_FALSE(var4.try_open(L"\\illegal\\chars\\too\\\\many\\\\namespaces"));
- REQUIRE(::GetLastError() != ERROR_SUCCESS);
- REQUIRE(var4.try_open(L"wiltestsemaphore"));
- }
- TEST_CASE("WindowsInternalTests::HandleWrappers", "[resource][unique_any]")
- {
- EventTestCommon<wil::unique_event_nothrow>();
- EventTestCommon<wil::unique_event_failfast>();
- // intentionally disabled in the non-exception version...
- // wil::unique_event_nothrow testEvent2(wil::EventOptions::ManualReset);
- wil::unique_event_failfast testEvent3(wil::EventOptions::ManualReset);
- #ifdef WIL_ENABLE_EXCEPTIONS
- EventTestCommon<wil::unique_event>();
- wil::unique_event testEvent(wil::EventOptions::ManualReset);
- {
- REQUIRE_FALSE(wil::event_is_signaled(testEvent.get()));
- auto eventSet = wil::SetEvent_scope_exit(testEvent.get());
- REQUIRE_FALSE(wil::event_is_signaled(testEvent.get()));
- }
- {
- REQUIRE(wil::event_is_signaled(testEvent.get()));
- auto eventSet = wil::ResetEvent_scope_exit(testEvent.get());
- REQUIRE(wil::event_is_signaled(testEvent.get()));
- }
- REQUIRE_FALSE(wil::event_is_signaled(testEvent.get()));
- REQUIRE_FALSE(wil::handle_wait(testEvent.get(), 0));
- // Exception-based - no return
- testEvent.create(wil::EventOptions::ManualReset);
- #endif
- // Error-code based -- returns HR
- wil::unique_event_nothrow testEventNoExcept;
- REQUIRE(SUCCEEDED(testEventNoExcept.create(wil::EventOptions::ManualReset)));
- MutexTestCommon<wil::unique_mutex_nothrow>();
- MutexTestCommon<wil::unique_mutex_failfast>();
- MutexRaiiTests<wil::unique_mutex_nothrow>();
- MutexRaiiTests<wil::unique_mutex_failfast>();
- // intentionally disabled in the non-exception version...
- // wil::unique_mutex_nothrow testMutex2(L"FOO-TEST-2");
- wil::unique_mutex_failfast testMutex3(L"FOO-TEST-3");
- #ifdef WIL_ENABLE_EXCEPTIONS
- MutexTestCommon<wil::unique_mutex>();
- MutexRaiiTests<wil::unique_mutex>();
- wil::unique_mutex testMutex(L"FOO-TEST");
- WaitForSingleObjectEx(testMutex.get(), INFINITE, TRUE);
- {
- auto release = wil::ReleaseMutex_scope_exit(testMutex.get());
- }
- // Exception-based - no return
- testMutex.create(nullptr);
- #endif
- // Error-code based -- returns HR
- wil::unique_mutex_nothrow testMutexNoExcept;
- REQUIRE(SUCCEEDED(testMutexNoExcept.create(nullptr)));
- SemaphoreTestCommon<wil::unique_semaphore_nothrow>();
- SemaphoreTestCommon<wil::unique_semaphore_failfast>();
- SemaphoreRaiiTests<wil::unique_semaphore_nothrow>();
- SemaphoreRaiiTests<wil::unique_semaphore_failfast>();
- // intentionally disabled in the non-exception version...
- // wil::unique_semaphore_nothrow testSemaphore2(1, 1);
- wil::unique_semaphore_failfast testSemaphore3(1, 1);
- #ifdef WIL_ENABLE_EXCEPTIONS
- SemaphoreTestCommon<wil::unique_semaphore>();
- SemaphoreRaiiTests<wil::unique_semaphore>();
- wil::unique_semaphore testSemaphore(1, 1);
- WaitForSingleObjectEx(testSemaphore.get(), INFINITE, true);
- {
- auto release = wil::ReleaseSemaphore_scope_exit(testSemaphore.get());
- }
- // Exception-based - no return
- testSemaphore.create(1, 1);
- #endif
- // Error-code based -- returns HR
- wil::unique_semaphore_nothrow testSemaphoreNoExcept;
- REQUIRE(SUCCEEDED(testSemaphoreNoExcept.create(1, 1)));
- auto unique_cotaskmem_string_failfast1 = wil::make_cotaskmem_string_failfast(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_cotaskmem_string_failfast1.get()) == 0);
- auto unique_cotaskmem_string_nothrow1 = wil::make_cotaskmem_string_nothrow(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_cotaskmem_string_nothrow1.get()) == 0);
- auto unique_cotaskmem_string_nothrow2 = wil::make_cotaskmem_string_nothrow(L"");
- REQUIRE(wcscmp(L"", unique_cotaskmem_string_nothrow2.get()) == 0);
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto unique_cotaskmem_string_te1 = wil::make_cotaskmem_string(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_cotaskmem_string_te1.get()) == 0);
- auto unique_cotaskmem_string_te2 = wil::make_cotaskmem_string(L"");
- REQUIRE(wcscmp(L"", unique_cotaskmem_string_te2.get()) == 0);
- auto unique_cotaskmem_string_range1 = wil::make_cotaskmem_string(L"Foo", 2);
- REQUIRE(wcscmp(L"Fo", unique_cotaskmem_string_range1.get()) == 0);
- auto unique_cotaskmem_string_range2 = wil::make_cotaskmem_string(nullptr, 2);
- unique_cotaskmem_string_range2.get()[0] = L'F';
- unique_cotaskmem_string_range2.get()[1] = L'o';
- REQUIRE(wcscmp(L"Fo", unique_cotaskmem_string_range2.get()) == 0);
- auto unique_cotaskmem_string_range3 = wil::make_cotaskmem_string(nullptr, 0);
- REQUIRE(wcscmp(L"", unique_cotaskmem_string_range3.get()) == 0);
- #endif
- #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- {
- auto verify = MakeSecureDeleterMallocSpy();
- REQUIRE_SUCCEEDED(::CoRegisterMallocSpy(verify.Get()));
- auto removeSpy = wil::scope_exit([&] { ::CoRevokeMallocSpy(); });
- auto unique_cotaskmem_string_secure_failfast1 = wil::make_cotaskmem_string_secure_failfast(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_cotaskmem_string_secure_failfast1.get()) == 0);
- auto unique_cotaskmem_string_secure_nothrow1 = wil::make_cotaskmem_string_secure_nothrow(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_cotaskmem_string_secure_nothrow1.get()) == 0);
- auto unique_cotaskmem_string_secure_nothrow2 = wil::make_cotaskmem_string_secure_nothrow(L"");
- REQUIRE(wcscmp(L"", unique_cotaskmem_string_secure_nothrow2.get()) == 0);
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto unique_cotaskmem_string_secure_te1 = wil::make_cotaskmem_string_secure(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_cotaskmem_string_secure_te1.get()) == 0);
- auto unique_cotaskmem_string_secure_te2 = wil::make_cotaskmem_string_secure(L"");
- REQUIRE(wcscmp(L"", unique_cotaskmem_string_secure_te2.get()) == 0);
- #endif
- }
- auto unique_hlocal_string_failfast1 = wil::make_hlocal_string_failfast(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_hlocal_string_failfast1.get()) == 0);
- auto unique_hlocal_string_nothrow1 = wil::make_hlocal_string_nothrow(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_hlocal_string_nothrow1.get()) == 0);
- auto unique_hlocal_string_nothrow2 = wil::make_hlocal_string_nothrow(L"");
- REQUIRE(wcscmp(L"", unique_hlocal_string_nothrow2.get()) == 0);
- auto unique_hlocal_ansistring_failfast1 = wil::make_hlocal_ansistring_failfast("Foo");
- REQUIRE(strcmp("Foo", unique_hlocal_ansistring_failfast1.get()) == 0);
- auto unique_hlocal_ansistring_nothrow1 = wil::make_hlocal_ansistring_nothrow("Foo");
- REQUIRE(strcmp("Foo", unique_hlocal_ansistring_nothrow1.get()) == 0);
- auto unique_hlocal_ansistring_nothrow2 = wil::make_hlocal_ansistring_nothrow("");
- REQUIRE(strcmp("", unique_hlocal_ansistring_nothrow2.get()) == 0);
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto unique_hlocal_string_te1 = wil::make_hlocal_string(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_hlocal_string_te1.get()) == 0);
- auto unique_hlocal_string_te2 = wil::make_hlocal_string(L"");
- REQUIRE(wcscmp(L"", unique_hlocal_string_te2.get()) == 0);
- auto unique_hlocal_string_range1 = wil::make_hlocal_string(L"Foo", 2);
- REQUIRE(wcscmp(L"Fo", unique_hlocal_string_range1.get()) == 0);
- auto unique_hlocal_string_range2 = wil::make_hlocal_string(nullptr, 2);
- unique_hlocal_string_range2.get()[0] = L'F';
- unique_hlocal_string_range2.get()[1] = L'o';
- REQUIRE(wcscmp(L"Fo", unique_hlocal_string_range2.get()) == 0);
- auto unique_hlocal_string_range3 = wil::make_hlocal_string(nullptr, 0);
- REQUIRE(wcscmp(L"", unique_hlocal_string_range3.get()) == 0);
- auto unique_hlocal_ansistring_te1 = wil::make_hlocal_ansistring("Foo");
- REQUIRE(strcmp("Foo", unique_hlocal_ansistring_te1.get()) == 0);
- auto unique_hlocal_ansistring_te2 = wil::make_hlocal_ansistring("");
- REQUIRE(strcmp("", unique_hlocal_ansistring_te2.get()) == 0);
- auto unique_hlocal_ansistring_range1 = wil::make_hlocal_ansistring("Foo", 2);
- REQUIRE(strcmp("Fo", unique_hlocal_ansistring_range1.get()) == 0);
- auto unique_hlocal_ansistring_range2 = wil::make_hlocal_ansistring(nullptr, 2);
- unique_hlocal_ansistring_range2.get()[0] = L'F';
- unique_hlocal_ansistring_range2.get()[1] = L'o';
- REQUIRE(strcmp("Fo", unique_hlocal_ansistring_range2.get()) == 0);
- auto unique_hlocal_ansistring_range3 = wil::make_hlocal_ansistring(nullptr, 0);
- REQUIRE(strcmp("", unique_hlocal_ansistring_range3.get()) == 0);
- #endif
- {
- auto verify = MakeSecureDeleterMallocSpy();
- REQUIRE_SUCCEEDED(::CoRegisterMallocSpy(verify.Get()));
- auto removeSpy = wil::scope_exit([&] { ::CoRevokeMallocSpy(); });
- auto unique_hlocal_string_secure_failfast1 = wil::make_hlocal_string_secure_failfast(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_hlocal_string_secure_failfast1.get()) == 0);
- auto unique_hlocal_string_secure_nothrow1 = wil::make_hlocal_string_secure_nothrow(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_hlocal_string_secure_nothrow1.get()) == 0);
- auto unique_hlocal_string_secure_nothrow2 = wil::make_hlocal_string_secure_nothrow(L"");
- REQUIRE(wcscmp(L"", unique_hlocal_string_secure_nothrow2.get()) == 0);
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto unique_hlocal_string_secure_te1 = wil::make_hlocal_string_secure(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_hlocal_string_secure_te1.get()) == 0);
- auto unique_hlocal_string_secure_te2 = wil::make_hlocal_string_secure(L"");
- REQUIRE(wcscmp(L"", unique_hlocal_string_secure_te2.get()) == 0);
- #endif
- }
- auto unique_process_heap_string_failfast1 = wil::make_process_heap_string_failfast(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_process_heap_string_failfast1.get()) == 0);
- auto unique_process_heap_string_nothrow1 = wil::make_process_heap_string_nothrow(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_process_heap_string_nothrow1.get()) == 0);
- auto unique_process_heap_string_nothrow2 = wil::make_process_heap_string_nothrow(L"");
- REQUIRE(wcscmp(L"", unique_process_heap_string_nothrow2.get()) == 0);
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto unique_process_heap_string_te1 = wil::make_process_heap_string(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_process_heap_string_te1.get()) == 0);
- auto unique_process_heap_string_te2 = wil::make_process_heap_string(L"");
- REQUIRE(wcscmp(L"", unique_process_heap_string_te2.get()) == 0);
- auto unique_process_heap_string_range1 = wil::make_process_heap_string(L"Foo", 2);
- REQUIRE(wcscmp(L"Fo", unique_process_heap_string_range1.get()) == 0);
- auto unique_process_heap_string_range2 = wil::make_process_heap_string(nullptr, 2);
- unique_process_heap_string_range2.get()[0] = L'F';
- unique_process_heap_string_range2.get()[1] = L'o';
- REQUIRE(wcscmp(L"Fo", unique_process_heap_string_range2.get()) == 0);
- auto unique_process_heap_string_range3 = wil::make_process_heap_string(nullptr, 0);
- REQUIRE(wcscmp(L"", unique_process_heap_string_range3.get()) == 0);
- #endif
- #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
- auto unique_bstr_failfast1 = wil::make_bstr_failfast(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_bstr_failfast1.get()) == 0);
- auto unique_bstr_nothrow1 = wil::make_bstr_nothrow(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_bstr_nothrow1.get()) == 0);
- auto unique_bstr_nothrow2 = wil::make_bstr_nothrow(L"");
- REQUIRE(wcscmp(L"", unique_bstr_nothrow2.get()) == 0);
- auto unique_variant_bstr_failfast1 = wil::make_variant_bstr_failfast(L"Foo");
- REQUIRE(wcscmp(L"Foo", V_UNION(unique_variant_bstr_failfast1.addressof(), bstrVal)) == 0);
- auto unique_variant_bstr_nothrow1 = wil::make_variant_bstr_nothrow(L"Foo");
- REQUIRE(wcscmp(L"Foo", V_UNION(unique_variant_bstr_nothrow1.addressof(), bstrVal)) == 0);
- auto unique_variant_bstr_nothrow2 = wil::make_variant_bstr_nothrow(L"");
- REQUIRE(wcscmp(L"", V_UNION(unique_variant_bstr_nothrow2.addressof(), bstrVal)) == 0);
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto unique_bstr_te1 = wil::make_bstr(L"Foo");
- REQUIRE(wcscmp(L"Foo", unique_bstr_te1.get()) == 0);
- auto unique_bstr_te2 = wil::make_bstr(L"");
- REQUIRE(wcscmp(L"", unique_bstr_te2.get()) == 0);
- auto unique_variant_bstr_te1 = wil::make_variant_bstr(L"Foo");
- REQUIRE(wcscmp(L"Foo", V_UNION(unique_variant_bstr_te1.addressof(), bstrVal)) == 0);
- auto unique_variant_bstr_te2 = wil::make_variant_bstr(L"");
- REQUIRE(wcscmp(L"", V_UNION(unique_variant_bstr_te2.addressof(), bstrVal)) == 0);
- auto testString = wil::make_cotaskmem_string(L"Foo");
- {
- auto cleanupMemory = wil::SecureZeroMemory_scope_exit(testString.get());
- }
- REQUIRE(0 == testString.get()[0]);
- auto testString2 = wil::make_cotaskmem_string(L"Bar");
- {
- auto cleanupMemory = wil::SecureZeroMemory_scope_exit(testString2.get(), wcslen(testString2.get()) * sizeof(testString2.get()[0]));
- }
- REQUIRE(0 == testString2.get()[0]);
- #endif
- }
- TEST_CASE("WindowsInternalTests::Locking", "[resource]")
- {
- {
- SRWLOCK rwlock = SRWLOCK_INIT;
- {
- auto lock = wil::AcquireSRWLockExclusive(&rwlock);
- REQUIRE(lock);
- auto lockRecursive = wil::TryAcquireSRWLockExclusive(&rwlock);
- REQUIRE_FALSE(lockRecursive);
- auto lockRecursiveShared = wil::TryAcquireSRWLockShared(&rwlock);
- REQUIRE_FALSE(lockRecursiveShared);
- }
- {
- auto lock = wil::AcquireSRWLockShared(&rwlock);
- REQUIRE(lock);
- auto lockRecursive = wil::TryAcquireSRWLockShared(&rwlock);
- REQUIRE(lockRecursive);
- auto lockRecursiveExclusive = wil::TryAcquireSRWLockExclusive(&rwlock);
- REQUIRE_FALSE(lockRecursiveExclusive);
- }
- {
- auto lock = wil::TryAcquireSRWLockExclusive(&rwlock);
- REQUIRE(lock);
- }
- {
- auto lock = wil::TryAcquireSRWLockShared(&rwlock);
- REQUIRE(lock);
- }
- }
- {
- wil::srwlock rwlock;
- {
- auto lock = rwlock.lock_exclusive();
- REQUIRE(lock);
- auto lockRecursive = rwlock.try_lock_exclusive();
- REQUIRE_FALSE(lockRecursive);
- auto lockRecursiveShared = rwlock.try_lock_shared();
- REQUIRE_FALSE(lockRecursiveShared);
- }
- {
- auto lock = rwlock.lock_shared();
- REQUIRE(lock);
- auto lockRecursive = rwlock.try_lock_shared();
- REQUIRE(lockRecursive);
- auto lockRecursiveExclusive = rwlock.try_lock_exclusive();
- REQUIRE_FALSE(lockRecursiveExclusive);
- }
- {
- auto lock = rwlock.try_lock_exclusive();
- REQUIRE(lock);
- }
- {
- auto lock = rwlock.try_lock_shared();
- REQUIRE(lock);
- }
- }
- {
- CRITICAL_SECTION cs;
- ::InitializeCriticalSectionEx(&cs, 0, 0);
- {
- auto lock = wil::EnterCriticalSection(&cs);
- REQUIRE(lock);
- auto tryLock = wil::TryEnterCriticalSection(&cs);
- REQUIRE(tryLock);
- }
- ::DeleteCriticalSection(&cs);
- }
- {
- wil::critical_section cs;
- auto lock = cs.lock();
- REQUIRE(lock);
- auto tryLock = cs.try_lock();
- REQUIRE(tryLock);
- }
- }
- #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- TEST_CASE("WindowsInternalTests::GDIWrappers", "[resource]")
- {
- {
- auto dc = wil::GetDC(::GetDesktopWindow());
- }
- {
- auto dc = wil::GetWindowDC(::GetDesktopWindow());
- }
- {
- auto dc = wil::BeginPaint(::GetDesktopWindow());
- wil::unique_hbrush brush(::CreateSolidBrush(0xffffff));
- auto select = wil::SelectObject(dc.get(), brush.get());
- }
- }
- #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
- void TestOutHandle(_Out_ HANDLE *pHandle)
- {
- *pHandle = nullptr;
- }
- void TestOutAlloc(_Out_ int **ppInt)
- {
- *ppInt = new int(5);
- }
- void TestCoTask(_Outptr_result_buffer_(*charCount) PWSTR *ppsz, size_t *charCount)
- {
- *charCount = 0;
- PWSTR psz = static_cast<PWSTR>(::CoTaskMemAlloc(10));
- if (psz != nullptr)
- {
- *charCount = 5;
- *psz = L'\0';
- }
- *ppsz = psz;
- }
- void TestVoid(_Out_ void **ppv)
- {
- *ppv = nullptr;
- }
- void TestByte(_Out_ BYTE **ppByte)
- {
- *ppByte = nullptr;
- }
- struct my_deleter
- {
- template <typename T>
- void operator()(T* p) const
- {
- delete p;
- }
- };
- TEST_CASE("WindowsInternalTests::WistdTests", "[resource][wistd]")
- {
- wil::unique_handle spHandle;
- TestOutHandle(wil::out_param(spHandle));
- wistd::unique_ptr<int> spInt;
- TestOutAlloc(wil::out_param(spInt));
- std::unique_ptr<int> spIntStd;
- TestOutAlloc(wil::out_param(spIntStd));
- wil::unique_cotaskmem_string spsz0;
- size_t count;
- TestCoTask(wil::out_param(spsz0), &count);
- std::unique_ptr<wchar_t[], wil::cotaskmem_deleter> spsz1;
- TestCoTask(wil::out_param(spsz1), &count);
- wistd::unique_ptr<wchar_t[], wil::cotaskmem_deleter> spsz2;
- TestCoTask(wil::out_param(spsz2), &count);
- wil::unique_cotaskmem_ptr<wchar_t[]> spsz3;
- TestCoTask(wil::out_param(spsz3), &count);
- wil::unique_cotaskmem_ptr<void> spv;
- TestVoid(wil::out_param(spv));
- std::unique_ptr<int> spIntStd2;
- TestByte(wil::out_param_ptr<BYTE**>(spIntStd2));
- struct Nothing
- {
- int n;
- Nothing(int param) : n(param) {}
- void Method() {}
- };
- auto spff = wil::make_unique_failfast<Nothing>(3);
- auto sp = wil::make_unique_nothrow<Nothing>(3);
- REQUIRE(sp);
- #ifdef WIL_ENABLE_EXCEPTIONS
- THROW_IF_NULL_ALLOC(sp.get());
- THROW_IF_NULL_ALLOC(sp);
- #endif
- sp->Method();
- decltype(sp) sp2;
- sp2 = wistd::move(sp);
- sp2.get();
- wistd::unique_ptr<int> spConstruct;
- wistd::unique_ptr<int> spConstruct2 = nullptr;
- spConstruct = nullptr;
- wistd::unique_ptr<int> spConstruct3(new int(3));
- my_deleter d;
- wistd::unique_ptr<int, my_deleter> spConstruct4(new int(4), d);
- wistd::unique_ptr<int, my_deleter> spConstruct5(new int(5), my_deleter());
- wistd::unique_ptr<int> spConstruct6(wistd::unique_ptr<int>(new int(6)));
- spConstruct = std::move(spConstruct2);
- spConstruct.swap(spConstruct2);
- REQUIRE(*spConstruct4 == 4);
- spConstruct4.get();
- if (spConstruct4)
- {
- }
- spConstruct.reset();
- spConstruct.release();
- auto spTooBig = wil::make_unique_nothrow<int[]>(static_cast<size_t>(-1));
- REQUIRE_FALSE(spTooBig);
- // REQUIRE_FAILFAST_UNSPECIFIED([]{ auto spTooBigFF = wil::make_unique_failfast<int[]>(static_cast<size_t>(-1)); });
- object_counter_state state;
- count = 0;
- {
- object_counter c{ state };
- REQUIRE(state.instance_count() == 1);
- wistd::function<void(int)> fn = [&count, c](int param)
- {
- count += param;
- };
- REQUIRE(state.instance_count() == 2);
- fn(3);
- REQUIRE(count == 3);
- }
- REQUIRE(state.instance_count() == 0);
- count = 0;
- {
- wistd::function<void(int)> fn;
- {
- object_counter c{ state };
- REQUIRE(state.instance_count() == 1);
- fn = [&count, c](int param)
- {
- count += param;
- };
- REQUIRE(state.instance_count() == 2);
- }
- REQUIRE(state.instance_count() == 1);
- fn(3);
- REQUIRE(count == 3);
- }
- {
- // Size Check -- the current implementation allows for 10 pointers to be passed through the lambda
- int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12;
- (void)a11; (void)a12;
- wistd::function<void()> fn = [&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10]()
- {
- (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8; (void)a9; (void)a10;
- };
- auto fnCopy = fn;
- // Uncomment to double-check static assert. Reports:
- // "The sizeof(wistd::function) has grown too large for the reserved buffer (10 pointers). Refactor to reduce size of the capture."
- // wistd::function<void()> fn2 = [&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11]()
- // {
- // a1; a2; a3; a4; a5; a6; a7; a8; a9; a10; a11;
- // };
- }
- }
- template <typename test_t, typename lambda_t>
- void NullptrRaiiTests(lambda_t const &fnCreate)
- {
- // nullptr_t construct
- test_t var1 = nullptr; // implicit
- REQUIRE_FALSE(var1);
- test_t var2(nullptr); // explicit
- REQUIRE_FALSE(var2);
- // nullptr_t assingment
- var1.reset(fnCreate());
- REQUIRE(var1);
- var1 = nullptr;
- REQUIRE_FALSE(var1);
- // nullptr_t reset
- var1.reset(fnCreate());
- REQUIRE(var1);
- var1.reset(nullptr);
- REQUIRE_FALSE(var1);
- }
- template <typename test_t, typename lambda_t>
- void ReleaseRaiiTests(lambda_t const &fnCreate)
- {
- test_t var1(fnCreate());
- REQUIRE(var1);
- auto ptr = var1.release();
- REQUIRE_FALSE(var1);
- REQUIRE(ptr != test_t::policy::invalid_value());
- REQUIRE(var1.get() == test_t::policy::invalid_value());
- var1.reset(ptr);
- }
- template <typename test_t, typename lambda_t>
- void GetRaiiTests(lambda_t const &fnCreate)
- {
- test_t var1;
- REQUIRE_FALSE(var1);
- REQUIRE(var1.get() == test_t::policy::invalid_value());
- var1.reset(fnCreate());
- REQUIRE(var1);
- REQUIRE(var1.get() != test_t::policy::invalid_value());
- }
- template <typename test_t, typename lambda_t>
- void SharedRaiiTests(lambda_t const &fnCreate)
- {
- // copy construction
- test_t var1(fnCreate());
- REQUIRE(var1);
- test_t var2 = var1; // implicit
- REQUIRE(var1);
- REQUIRE(var2);
- test_t var3(var1); // explicit
- // copy assignment
- test_t var4(fnCreate());
- test_t var5;
- var5 = var4;
- REQUIRE(var5);
- REQUIRE(var4);
- // r-value construction from unique_ptr
- typename test_t::unique_t unique1(fnCreate());
- test_t var7(std::move(unique1)); // explicit
- REQUIRE(var7);
- REQUIRE_FALSE(unique1);
- typename test_t::unique_t unique2(fnCreate());
- test_t var8 = std::move(unique2); // implicit
- REQUIRE(var8);
- REQUIRE_FALSE(unique2);
- // r-value assignment from unique_ptr
- var8.reset();
- REQUIRE_FALSE(var8);
- unique2.reset(fnCreate());
- var8 = std::move(unique2);
- REQUIRE(var8);
- REQUIRE_FALSE(unique2);
- // use_count()
- REQUIRE(var8.use_count() == 1);
- auto var9 = var8;
- REQUIRE(var8.use_count() == 2);
- }
- template <typename test_t, typename lambda_t>
- void WeakRaiiTests(lambda_t const &fnCreate)
- {
- typedef typename test_t::shared_t shared_type;
- // base constructor
- test_t weak1;
- // construct from shared
- shared_type shared1(fnCreate());
- test_t weak2 = shared1; // implicit
- test_t weak3(shared1); // explicit
- // construct from weak
- test_t weak4 = weak2; // implicit
- test_t weak5(weak2); // explicit
- // assign from weak
- weak2 = weak5;
- // assign from shared
- weak2 = shared1;
- // reset
- weak2.reset();
- REQUIRE_FALSE(weak2.lock());
- // swap
- test_t swap1 = shared1;
- test_t swap2;
- REQUIRE(swap1.lock());
- REQUIRE_FALSE(swap2.lock());
- swap1.swap(swap2);
- REQUIRE_FALSE(swap1.lock());
- REQUIRE(swap2.lock());
- // expired
- REQUIRE_FALSE(swap2.expired());
- shared1.reset();
- REQUIRE(swap2.expired());
- // lock
- shared1.reset(fnCreate());
- weak1 = shared1;
- auto shared2 = weak1.lock();
- REQUIRE(shared2);
- shared2.reset();
- REQUIRE(weak1.lock());
- shared1.reset();
- shared2 = weak1.lock();
- REQUIRE_FALSE(shared2);
- }
- template <typename test_t, typename lambda_t>
- void AddressRaiiTests(lambda_t const &fnCreate)
- {
- test_t var1(fnCreate());
- REQUIRE(var1);
- &var1;
- REQUIRE_FALSE(var1); // the address operator does an auto-release
- *(&var1) = fnCreate();
- REQUIRE(var1);
- var1.put();
- REQUIRE_FALSE(var1); // verify that 'put()' does an auto-release
- *var1.put() = fnCreate();
- REQUIRE(var1);
- REQUIRE(var1.addressof() != nullptr);
- REQUIRE(var1); // verify that 'addressof()' does not auto-release
- }
- template <typename test_t, typename lambda_t>
- void BasicRaiiTests(lambda_t const &fnCreate)
- {
- auto invalidHandle = test_t::policy::invalid_value();
- // no-constructor construction
- test_t var1;
- REQUIRE_FALSE(var1);
- // construct from a given resource
- test_t var2(fnCreate()); // r-value
- REQUIRE(var2);
- test_t var3(invalidHandle); // l-value
- REQUIRE_FALSE(var3);
- // r-value construct from the same type
- test_t var4(std::move(var2)); // explicit
- REQUIRE(var4);
- REQUIRE_FALSE(var2);
- test_t varMove(fnCreate());
- test_t var4implicit = std::move(varMove); // implicit
- REQUIRE(var4implicit);
- // move assignment
- var2 = std::move(var4);
- REQUIRE(var2);
- REQUIRE_FALSE(var4);
- // swap
- var2.swap(var4);
- REQUIRE(var4);
- REQUIRE_FALSE(var2);
- // explicit bool cast
- REQUIRE(static_cast<bool>(var4));
- REQUIRE_FALSE(static_cast<bool>(var2));
- // reset
- var4.reset();
- REQUIRE_FALSE(var4);
- var4.reset(fnCreate()); // r-value
- REQUIRE(var4);
- var4.reset(invalidHandle); // l-value
- REQUIRE_FALSE(var4);
- }
- template <typename test_t>
- void EventRaiiTests()
- {
- test_t var1;
- var1.create(wil::EventOptions::ManualReset);
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- // SetEvent/ResetEvent
- var1.SetEvent();
- REQUIRE(wil::event_is_signaled(var1.get()));
- var1.ResetEvent();
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- // SetEvent/ResetEvent scope_exit
- {
- auto exit = var1.SetEvent_scope_exit();
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- }
- REQUIRE(wil::event_is_signaled(var1.get()));
- {
- auto exit = var1.ResetEvent_scope_exit();
- REQUIRE(wil::event_is_signaled(var1.get()));
- }
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- // is_signaled
- REQUIRE_FALSE(var1.is_signaled());
- // wait
- REQUIRE_FALSE(var1.wait(50));
- // try_create
- bool exists = false;
- REQUIRE(var1.try_create(wil::EventOptions::ManualReset, L"wiltestevent", nullptr, &exists));
- REQUIRE_FALSE(exists);
- test_t var2;
- REQUIRE(var2.try_create(wil::EventOptions::ManualReset, L"wiltestevent", nullptr, &exists));
- REQUIRE(exists);
- test_t var3;
- REQUIRE_FALSE(var3.try_create(wil::EventOptions::ManualReset, L"\\illegal\\chars\\too\\\\many\\\\namespaces", nullptr, &exists));
- REQUIRE(::GetLastError() != ERROR_SUCCESS);
- // try_open
- test_t var4;
- REQUIRE_FALSE(var4.try_open(L"\\illegal\\chars\\too\\\\many\\\\namespaces"));
- REQUIRE(::GetLastError() != ERROR_SUCCESS);
- REQUIRE(var4.try_open(L"wiltestevent"));
- }
- void EventTests()
- {
- static_assert(sizeof(wil::unique_event_nothrow) == sizeof(HANDLE), "event_t should be sizeof(HANDLE) to allow for raw array utilization");
- auto fnCreate = []() { return CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, 0); };
- BasicRaiiTests<wil::unique_event_nothrow>(fnCreate);
- NullptrRaiiTests<wil::unique_event_nothrow>(fnCreate);
- GetRaiiTests<wil::unique_event_nothrow>(fnCreate);
- ReleaseRaiiTests<wil::unique_event_nothrow>(fnCreate);
- AddressRaiiTests<wil::unique_event_nothrow>(fnCreate);
- EventRaiiTests<wil::unique_event_nothrow>();
- BasicRaiiTests<wil::unique_event_failfast>(fnCreate);
- NullptrRaiiTests<wil::unique_event_failfast>(fnCreate);
- GetRaiiTests<wil::unique_event_failfast>(fnCreate);
- ReleaseRaiiTests<wil::unique_event_failfast>(fnCreate);
- AddressRaiiTests<wil::unique_event_failfast>(fnCreate);
- EventRaiiTests<wil::unique_event_failfast>();
- wil::unique_event_nothrow event4;
- REQUIRE(S_OK == event4.create(wil::EventOptions::ManualReset));
- REQUIRE(FAILED(event4.create(wil::EventOptions::ManualReset, L"\\illegal\\chars\\too\\\\many\\\\namespaces")));
- #ifdef WIL_ENABLE_EXCEPTIONS
- static_assert(sizeof(wil::unique_event) == sizeof(HANDLE), "event_t should be sizeof(HANDLE) to allow for raw array utilization");
- BasicRaiiTests<wil::unique_event>(fnCreate);
- NullptrRaiiTests<wil::unique_event>(fnCreate);
- GetRaiiTests<wil::unique_event>(fnCreate);
- ReleaseRaiiTests<wil::unique_event>(fnCreate);
- AddressRaiiTests<wil::unique_event>(fnCreate);
- EventRaiiTests<wil::unique_event>();
- BasicRaiiTests<wil::shared_event>(fnCreate);
- NullptrRaiiTests<wil::shared_event>(fnCreate);
- GetRaiiTests<wil::shared_event>(fnCreate);
- AddressRaiiTests<wil::shared_event>(fnCreate);
- SharedRaiiTests<wil::shared_event>(fnCreate);
- EventRaiiTests<wil::shared_event>();
- WeakRaiiTests<wil::weak_event>(fnCreate);
- // explicitly disabled
- // wil::unique_event_nothrow event1(wil::EventOptions::ManualReset);
- wil::unique_event event2(wil::EventOptions::ManualReset);
- wil::shared_event event3(wil::EventOptions::ManualReset);
- event2.create(wil::EventOptions::ManualReset);
- REQUIRE(event2);
- event3.create(wil::EventOptions::ManualReset);
- REQUIRE(event3);
- REQUIRE_THROWS(event2.create(wil::EventOptions::ManualReset, L"\\illegal\\chars\\too\\\\many\\\\namespaces") );
- REQUIRE_THROWS(event3.create(wil::EventOptions::ManualReset, L"\\illegal\\chars\\too\\\\many\\\\namespaces") );
- wil::unique_event var1(wil::EventOptions::ManualReset);
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- {
- auto autoset = wil::SetEvent_scope_exit(var1.get());
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- REQUIRE(autoset.get() == var1.get());
- // &autoset; // verified disabled
- // autoset.addressof(); // verified disabled
- }
- REQUIRE(wil::event_is_signaled(var1.get()));
- {
- auto autoreset = wil::ResetEvent_scope_exit(var1.get());
- REQUIRE(wil::event_is_signaled(var1.get()));
- autoreset.reset();
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- }
- {
- auto autoset = wil::SetEvent_scope_exit(var1.get());
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- autoset.release();
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- }
- REQUIRE_FALSE(wil::event_is_signaled(var1.get()));
- #endif
- }
- typedef wil::unique_struct<PROPVARIANT, decltype(&::PropVariantClear), ::PropVariantClear> unique_prop_variant_no_init;
- void SetPropVariantValue(_In_ int intVal, _Out_ PROPVARIANT* ppropvar)
- {
- ppropvar->intVal = intVal;
- ppropvar->vt = VT_INT;
- }
- template<typename T>
- void TestUniquePropVariant()
- {
- {
- wil::unique_prop_variant spPropVariant;
- REQUIRE(spPropVariant.vt == VT_EMPTY);
- }
- // constructor test
- {
- PROPVARIANT propVariant;
- SetPropVariantValue(12, &propVariant);
- T spPropVariant(propVariant);
- REQUIRE(((spPropVariant.intVal == 12) && (spPropVariant.vt == VT_INT)));
- T spPropVariant2(wistd::move(propVariant));
- REQUIRE(((spPropVariant2.intVal == 12) && (spPropVariant2.vt == VT_INT)));
- //spPropVariant = propVariant; // deleted function
- //spPropVariant = wistd::move(propVariant); // deleted function
- //spPropVariant.swap(propVariant); //deleted function
- }
- // move constructor
- {
- T spPropVariant;
- SetPropVariantValue(12, &spPropVariant);
- REQUIRE(((spPropVariant.intVal == 12) && (spPropVariant.vt == VT_INT)));
- T spPropVariant2(wistd::move(spPropVariant));
- REQUIRE(spPropVariant.vt == VT_EMPTY);
- REQUIRE(((spPropVariant2.intVal == 12) && (spPropVariant2.vt == VT_INT)));
- //T spPropVariant3(spPropVariant); // deleted function
- //spPropVariant2 = spPropVariant; // deleted function
- }
- // move operator
- {
- T spPropVariant;
- SetPropVariantValue(12, &spPropVariant);
- T spPropVariant2 = wistd::move(spPropVariant);
- REQUIRE(spPropVariant.vt == VT_EMPTY);
- REQUIRE(((spPropVariant2.intVal == 12) && (spPropVariant2.vt == VT_INT)));
- }
- // reset
- {
- PROPVARIANT propVariant;
- SetPropVariantValue(22, &propVariant);
- T spPropVariant;
- SetPropVariantValue(12, &spPropVariant);
- T spPropVariant2;
- //spPropVariant2.reset(spPropVariant); // deleted function
- spPropVariant.reset(propVariant);
- REQUIRE(spPropVariant.intVal == 22);
- REQUIRE(propVariant.intVal == 22);
- spPropVariant.reset();
- REQUIRE(spPropVariant.vt == VT_EMPTY);
- }
- // swap
- {
- T spPropVariant;
- SetPropVariantValue(12, &spPropVariant);
- T spPropVariant2;
- SetPropVariantValue(22, &spPropVariant2);
- spPropVariant.swap(spPropVariant2);
- REQUIRE(spPropVariant.intVal == 22);
- REQUIRE(spPropVariant2.intVal == 12);
- }
- // release, addressof, reset_and_addressof
- {
- T spPropVariant;
- SetPropVariantValue(12, &spPropVariant);
- [](PROPVARIANT* propVariant)
- {
- REQUIRE(propVariant->vt == VT_EMPTY);
- }(spPropVariant.reset_and_addressof());
- SetPropVariantValue(12, &spPropVariant);
- PROPVARIANT* pPropVariant = spPropVariant.addressof();
- REQUIRE(pPropVariant->intVal == 12);
- REQUIRE(spPropVariant.intVal == 12);
- PROPVARIANT propVariant = spPropVariant.release();
- REQUIRE(propVariant.intVal == 12);
- REQUIRE(spPropVariant.vt == VT_EMPTY);
- }
- }
- TEST_CASE("WindowsInternalTests::ResourceTemplateTests", "[resource]")
- {
- EventTests();
- TestUniquePropVariant<wil::unique_prop_variant>();
- TestUniquePropVariant<unique_prop_variant_no_init>();
- }
- inline unsigned long long ToInt64(const FILETIME &ft)
- {
- return (static_cast<unsigned long long>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
- }
- inline FILETIME FromInt64(unsigned long long i64)
- {
- FILETIME ft = { static_cast<DWORD>(i64), static_cast<DWORD>(i64 >> 32) };
- return ft;
- }
- TEST_CASE("WindowsInternalTests::Win32HelperTests", "[win32_helpers]")
- {
- auto systemTime = wil::filetime::get_system_time();
- REQUIRE(ToInt64(systemTime) == wil::filetime::to_int64(systemTime));
- auto systemTime64 = wil::filetime::to_int64(systemTime);
- #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- auto ft1 = FromInt64(systemTime64);
- auto ft2 = wil::filetime::from_int64(systemTime64);
- REQUIRE(CompareFileTime(&ft1, &ft2) == 0);
- #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
- REQUIRE(systemTime64 == wil::filetime::to_int64(wil::filetime::from_int64(systemTime64)));
- REQUIRE((systemTime64 + wil::filetime_duration::one_hour) == (systemTime64 + (wil::filetime_duration::one_minute * 60)));
- auto systemTimePlusOneHour = wil::filetime::add(systemTime, wil::filetime_duration::one_hour);
- auto systemTimePlusOneHour64 = wil::filetime::to_int64(systemTimePlusOneHour);
- REQUIRE(systemTimePlusOneHour64 == (systemTime64 + wil::filetime_duration::one_hour));
- }
- TEST_CASE("WindowsInternalTests::RectHelperTests", "[win32_helpers]")
- {
- RECT rect{ 50, 100, 200, 300 };
- POINT leftEdgePoint{ 50, 150 };
- POINT topEdgePoint{ 100, 100 };
- POINT rightEdgePoint{ 200, 150 };
- POINT bottomEdgePoint{ 100, 300 };
- POINT insidePoint{ 150, 150};
- RECT emptyRectAtOrigin{};
- RECT emptyRectNotAtOrigin{ 50, 50, 50, 50 };
- RECT nonNormalizedRect{ 300, 300, 0, 0 };
- REQUIRE(wil::rect_width(rect) == 150);
- REQUIRE(wil::rect_height(rect) == 200);
- // rect_is_empty should work like user32's IsRectEmpty
- REQUIRE_FALSE(wil::rect_is_empty(rect));
- REQUIRE(wil::rect_is_empty(emptyRectAtOrigin));
- REQUIRE(wil::rect_is_empty(emptyRectNotAtOrigin));
- REQUIRE(wil::rect_is_empty(nonNormalizedRect));
- // rect_contains_point should work like user32's PtInRect
- REQUIRE(wil::rect_contains_point(rect, insidePoint));
- REQUIRE(wil::rect_contains_point(rect, leftEdgePoint));
- REQUIRE(wil::rect_contains_point(rect, topEdgePoint));
- REQUIRE_FALSE(wil::rect_contains_point(rect, rightEdgePoint));
- REQUIRE_FALSE(wil::rect_contains_point(rect, bottomEdgePoint));
- REQUIRE_FALSE(wil::rect_contains_point(nonNormalizedRect, insidePoint));
- auto rectFromSize = wil::rect_from_size<RECT>(50, 100, 150, 200);
- REQUIRE(rectFromSize.left == rect.left);
- REQUIRE(rectFromSize.top == rect.top);
- REQUIRE(rectFromSize.right == rect.right);
- REQUIRE(rectFromSize.bottom == rect.bottom);
- }
- TEST_CASE("WindowsInternalTests::InitOnceNonTests")
- {
- bool called = false;
- bool winner = false;
- INIT_ONCE init{};
- REQUIRE_FALSE(wil::init_once_initialized(init));
- // Call, but fail. Should transport the HRESULT back, but mark us as not the winner
- called = false;
- winner = false;
- REQUIRE(E_FAIL == wil::init_once_nothrow(init, [&] { called = true; return E_FAIL; }, &winner));
- REQUIRE_FALSE(wil::init_once_initialized(init));
- REQUIRE(called);
- REQUIRE_FALSE(winner);
- // Call, succeed. Should mark us as the winner.
- called = false;
- winner = false;
- REQUIRE_SUCCEEDED(wil::init_once_nothrow(init, [&] { called = true; return S_OK; }, &winner));
- REQUIRE(wil::init_once_initialized(init));
- REQUIRE(called);
- REQUIRE(winner);
- // Call again. Should not actually be invoked and should not be the winner
- called = false;
- winner = false;
- REQUIRE_SUCCEEDED(wil::init_once_nothrow(init, [&] { called = false; return S_OK; }, &winner));
- REQUIRE(wil::init_once_initialized(init));
- REQUIRE_FALSE(called);
- REQUIRE_FALSE(winner);
- // Call again. Still not invoked, but we don't care if we're the winner
- called = false;
- REQUIRE_SUCCEEDED(wil::init_once_nothrow(init, [&] { called = false; return S_OK; }));
- REQUIRE(wil::init_once_initialized(init));
- REQUIRE_FALSE(called);
- #ifdef WIL_ENABLE_EXCEPTIONS
- called = false;
- winner = false;
- init = {};
- // A thrown exception leaves the object un-initialized
- static volatile bool always_true = true; // So that the compiler can't determine that we unconditionally throw below (warning C4702)
- REQUIRE_THROWS_AS(winner = wil::init_once(init, [&] { called = true; THROW_HR_IF(E_FAIL, always_true); }), wil::ResultException);
- REQUIRE_FALSE(wil::init_once_initialized(init));
- REQUIRE(called);
- REQUIRE_FALSE(winner);
- // Success!
- called = false;
- winner = false;
- REQUIRE_NOTHROW(winner = wil::init_once(init, [&] { called = true; }));
- REQUIRE(wil::init_once_initialized(init));
- REQUIRE(called);
- REQUIRE(winner);
- // No-op success!
- called = false;
- winner = false;
- REQUIRE_NOTHROW(winner = wil::init_once(init, [&] { called = true; }));
- REQUIRE(wil::init_once_initialized(init));
- REQUIRE_FALSE(called);
- REQUIRE_FALSE(winner);
- #endif // WIL_ENABLE_EXCEPTIONS
- }
- #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- TEST_CASE("WindowsInternalTests::TestUniquePointerCases", "[resource][unique_any]")
- {
- // wil::unique_process_heap_ptr tests
- {
- wil::unique_process_heap_ptr<void> empty; // null case
- }
- {
- wil::unique_process_heap_ptr<void> heapMemory(::HeapAlloc(::GetProcessHeap(), 0, 100));
- REQUIRE(static_cast<bool>(heapMemory));
- }
- // wil::unique_cotaskmem_ptr tests
- {
- wil::unique_cotaskmem_ptr<void> empty; // null case
- }
- {
- wil::unique_cotaskmem_ptr<void> cotaskmemMemory(CoTaskMemAlloc(100));
- REQUIRE(static_cast<bool>(cotaskmemMemory));
- }
- {
- auto cotaskmemMemory = wil::make_unique_cotaskmem_nothrow<DWORD>(42);
- REQUIRE(static_cast<bool>(cotaskmemMemory));
- REQUIRE(*cotaskmemMemory == static_cast<DWORD>(42));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- auto cotaskmemMemory = wil::make_unique_cotaskmem_nothrow<S>();
- REQUIRE(static_cast<bool>(cotaskmemMemory));
- REQUIRE(cotaskmemMemory->s == static_cast<size_t>(42));
- }
- {
- auto cotaskmemArrayMemory = wil::make_unique_cotaskmem_nothrow<BYTE[]>(12);
- REQUIRE(static_cast<bool>(cotaskmemArrayMemory));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- const size_t size = 12;
- auto cotaskmemArrayMemory = wil::make_unique_cotaskmem_nothrow<S[]>(size);
- REQUIRE(static_cast<bool>(cotaskmemArrayMemory));
- bool verified = true;
- for (auto& elem : wil::make_range(cotaskmemArrayMemory.get(), size)) if (elem.s != 42) verified = false;
- REQUIRE(verified);
- }
- // wil::unique_cotaskmem_secure_ptr tests
- {
- wil::unique_cotaskmem_secure_ptr<void> empty; // null case
- }
- {
- wil::unique_cotaskmem_secure_ptr<void> cotaskmemMemory(CoTaskMemAlloc(100));
- REQUIRE(static_cast<bool>(cotaskmemMemory));
- }
- {
- auto cotaskmemMemory = wil::make_unique_cotaskmem_secure_nothrow<DWORD>(42);
- REQUIRE(static_cast<bool>(cotaskmemMemory));
- REQUIRE(*cotaskmemMemory == static_cast<DWORD>(42));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- auto cotaskmemMemory = wil::make_unique_cotaskmem_secure_nothrow<S>();
- REQUIRE(static_cast<bool>(cotaskmemMemory));
- REQUIRE(cotaskmemMemory->s == static_cast<size_t>(42));
- }
- {
- auto cotaskmemArrayMemory = wil::make_unique_cotaskmem_secure_nothrow<BYTE[]>(12);
- REQUIRE(static_cast<bool>(cotaskmemArrayMemory));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- const size_t size = 12;
- auto cotaskmemArrayMemory = wil::make_unique_cotaskmem_secure_nothrow<S[]>(size);
- REQUIRE(static_cast<bool>(cotaskmemArrayMemory));
- bool verified = true;
- for (auto& elem : wil::make_range(cotaskmemArrayMemory.get(), size)) if (elem.s != 42) verified = false;
- REQUIRE(verified);
- }
- // wil::unique_hlocal_ptr tests
- {
- wil::unique_hlocal_ptr<void> empty; // null case
- }
- {
- wil::unique_hlocal_ptr<void> localMemory(LocalAlloc(LPTR, 100));
- REQUIRE(static_cast<bool>(localMemory));
- }
- {
- auto localMemory = wil::make_unique_hlocal_nothrow<DWORD>(42);
- REQUIRE(static_cast<bool>(localMemory));
- REQUIRE(*localMemory == static_cast<DWORD>(42));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- auto localMemory = wil::make_unique_hlocal_nothrow<S>();
- REQUIRE(static_cast<bool>(localMemory));
- REQUIRE(localMemory->s == static_cast<size_t>(42));
- }
- {
- auto localArrayMemory = wil::make_unique_hlocal_nothrow<BYTE[]>(12);
- REQUIRE(static_cast<bool>(localArrayMemory));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- const size_t size = 12;
- auto localArrayMemory = wil::make_unique_hlocal_nothrow<S[]>(size);
- REQUIRE(static_cast<bool>(localArrayMemory));
- bool verified = true;
- for (auto& elem : wil::make_range(localArrayMemory.get(), size)) if (elem.s != 42) verified = false;
- REQUIRE(verified);
- }
- // wil::unique_hlocal_secure_ptr tests
- {
- wil::unique_hlocal_secure_ptr<void> empty; // null case
- }
- {
- wil::unique_hlocal_secure_ptr<void> localMemory(LocalAlloc(LPTR, 100));
- REQUIRE(static_cast<bool>(localMemory));
- }
- {
- auto localMemory = wil::make_unique_hlocal_secure_nothrow<DWORD>(42);
- REQUIRE(static_cast<bool>(localMemory));
- REQUIRE(*localMemory == static_cast<DWORD>(42));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- auto localMemory = wil::make_unique_hlocal_secure_nothrow<S>();
- REQUIRE(static_cast<bool>(localMemory));
- REQUIRE(localMemory->s == static_cast<size_t>(42));
- }
- {
- auto localArrayMemory = wil::make_unique_hlocal_secure_nothrow<BYTE[]>(12);
- REQUIRE(static_cast<bool>(localArrayMemory));
- }
- {
- struct S { size_t s; S() : s(42) {} };
- const size_t size = 12;
- auto localArrayMemory = wil::make_unique_hlocal_secure_nothrow<S[]>(size);
- REQUIRE(static_cast<bool>(localArrayMemory));
- bool verified = true;
- for (auto& elem : wil::make_range(localArrayMemory.get(), size)) if (elem.s != 42) verified = false;
- REQUIRE(verified);
- }
- // wil::unique_hglobal_ptr tests
- {
- wil::unique_hglobal_ptr<void> empty; // null case
- }
- {
- wil::unique_hglobal_ptr<void> globalMemory(GlobalAlloc(GPTR, 100));
- REQUIRE(static_cast<bool>(globalMemory));
- }
- {
- // The following uses are blocked due to a static assert failure
- //struct S { ~S() {} };
- //auto cotaskmemMemory = wil::make_unique_cotaskmem_nothrow<S>();
- //auto cotaskmemArrayMemory = wil::make_unique_cotaskmem_nothrow<S[]>(1);
- //auto cotaskmemMemory2 = wil::make_unique_cotaskmem_secure_nothrow<S>();
- //auto cotaskmemArrayMemory2 = wil::make_unique_cotaskmem_secure_nothrow<S[]>(1);
- //auto localMemory = wil::make_unique_hlocal_nothrow<S>();
- //auto localArrayMemory = wil::make_unique_hlocal_nothrow<S[]>(1);
- //auto localMemory2 = wil::make_unique_hlocal_secure_nothrow<S>();
- //auto localArrayMemory2 = wil::make_unique_hlocal_secure_nothrow<S[]>(1);
- }
- }
- #endif
- void GetDWORDArray(_Out_ size_t* count, _Outptr_result_buffer_(*count) DWORD** numbers)
- {
- const size_t size = 5;
- auto ptr = static_cast<DWORD*>(::CoTaskMemAlloc(sizeof(DWORD) * size));
- REQUIRE(ptr);
- ::ZeroMemory(ptr, sizeof(DWORD) * size);
- *numbers = ptr;
- *count = size;
- }
- void GetHSTRINGArray(_Out_ ULONG* count, _Outptr_result_buffer_(*count) HSTRING** strings)
- {
- const size_t size = 5;
- auto ptr = static_cast<HSTRING*>(::CoTaskMemAlloc(sizeof(HSTRING) * size));
- REQUIRE(ptr);
- for (UINT i = 0; i < size; ++i)
- {
- REQUIRE_SUCCEEDED(WindowsCreateString(L"test", static_cast<UINT32>(wcslen(L"test")), &ptr[i]));
- }
- *strings = ptr;
- *count = static_cast<ULONG>(size);
- }
- void GetPOINTArray(_Out_ UINT32* count, _Outptr_result_buffer_(*count) POINT** points)
- {
- const size_t size = 5;
- auto ptr = static_cast<POINT*>(::CoTaskMemAlloc(sizeof(POINT) * size));
- REQUIRE(ptr);
- for (UINT i = 0; i < size; ++i)
- {
- ptr[i].x = ptr[i].y = i;
- }
- *points = ptr;
- *count = static_cast<UINT32>(size);
- }
- #ifdef WIL_ENABLE_EXCEPTIONS
- void GetHANDLEArray(_Out_ size_t* count, _Outptr_result_buffer_(*count) HANDLE** events)
- {
- const size_t size = 5;
- HANDLE* ptr = reinterpret_cast<HANDLE*>(::CoTaskMemAlloc(sizeof(HANDLE) * size));
- for (auto& val : wil::make_range(ptr, size))
- {
- val = wil::unique_event(wil::EventOptions::ManualReset).release();
- }
- *events = ptr;
- *count = size;
- }
- #endif
- interface __declspec(uuid("EDCA4ADC-DF46-442A-A69D-FDFD8BC37B31")) IFakeObject : public IUnknown
- {
- STDMETHOD_(void, DoStuff)() = 0;
- };
- class ArrayTestObject : witest::AllocatedObject,
- public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, IFakeObject>
- {
- public:
- HRESULT RuntimeClassInitialize(UINT n) { m_number = n; return S_OK; };
- STDMETHOD_(void, DoStuff)() {}
- private:
- UINT m_number{};
- };
- void GetUnknownArray(_Out_ size_t* count, _Outptr_result_buffer_(*count) IFakeObject*** objects)
- {
- const size_t size = 5;
- auto ptr = reinterpret_cast<IFakeObject**>(::CoTaskMemAlloc(sizeof(IFakeObject*) * size));
- REQUIRE(ptr);
- for (UINT i = 0; i < size; ++i)
- {
- Microsoft::WRL::ComPtr<IFakeObject> obj;
- REQUIRE_SUCCEEDED(Microsoft::WRL::MakeAndInitialize<ArrayTestObject>(&obj, i));
- ptr[i] = obj.Detach();
- }
- *objects = ptr;
- *count = size;
- }
- #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- TEST_CASE("WindowsInternalTests::TestUniqueArrayCases", "[resource]")
- {
- // wil::unique_cotaskmem_array_ptr tests
- {
- wil::unique_cotaskmem_array_ptr<DWORD> values;
- GetDWORDArray(values.size_address(), &values);
- }
- {
- wil::unique_cotaskmem_array_ptr<wil::unique_hstring> strings;
- GetHSTRINGArray(strings.size_address<ULONG>(), &strings);
- for (ULONG i = 0; i < strings.size(); ++i)
- {
- REQUIRE(WindowsGetStringLen(strings[i]) == wcslen(L"test"));
- }
- }
- {
- wil::unique_cotaskmem_array_ptr<POINT> points;
- GetPOINTArray(points.size_address<UINT32>(), &points);
- for (ULONG i = 0; i < points.size(); ++i)
- {
- REQUIRE((ULONG)points[i].x == i);
- }
- }
- #ifdef WIL_ENABLE_EXCEPTIONS
- {
- wil::unique_cotaskmem_array_ptr<wil::unique_event> events;
- GetHANDLEArray(events.size_address(), &events);
- }
- {
- wil::unique_cotaskmem_array_ptr<wil::com_ptr<IFakeObject>> objects;
- GetUnknownArray(objects.size_address(), &objects);
- for (ULONG i = 0; i < objects.size(); ++i)
- {
- objects[i]->DoStuff();
- }
- }
- #endif
- {
- wil::unique_cotaskmem_array_ptr<DWORD> values = nullptr;
- REQUIRE(!values);
- REQUIRE(values.size() == 0);
- // move onto self
- values = wistd::move(values);
- REQUIRE(!values);
- // fetch
- GetDWORDArray(values.size_address(), &values);
- REQUIRE(!!values);
- REQUIRE(values.size() > 0);
- REQUIRE(!values.empty());
- // move onto self
- values = wistd::move(values);
- REQUIRE(!!values);
- decltype(values) values2(wistd::move(values));
- REQUIRE(!values);
- REQUIRE(!!values2);
- REQUIRE(values2.size() > 0);
- values = wistd::move(values2);
- REQUIRE(!!values);
- REQUIRE(!values2);
- values = nullptr;
- REQUIRE(!values);
- GetDWORDArray(values.size_address(), values.put());
- REQUIRE(!!values);
- values = nullptr;
- REQUIRE(!values);
- GetDWORDArray(values.size_address(), &values);
- REQUIRE(!!values);
- auto size = values.size();
- auto ptr = values.release();
- REQUIRE(!values);
- REQUIRE(values.empty());
- decltype(values) values3(ptr, size);
- REQUIRE(!!values3);
- REQUIRE(values3.size() == size);
- values3.swap(values);
- REQUIRE(!!values);
- REQUIRE(!values.empty());
- REQUIRE(!values3);
- REQUIRE(values3.empty());
- REQUIRE(!values.empty());
- size_t count = 0;
- for (auto it = values.begin(); it != values.end(); ++it)
- {
- ++count;
- }
- REQUIRE(count == values.size());
- count = 0;
- for (auto it = values.cbegin(); it != values.cend(); ++it)
- {
- ++count;
- }
- REQUIRE(count == values.size());
- for (size_t index = 0; index < values.size(); index++)
- {
- auto& val = values[index];
- REQUIRE(val == 0);
- }
- auto& front = values.front();
- REQUIRE(front == 0);
- auto& back = values.back();
- REQUIRE(back == 0);
- [](const wil::unique_cotaskmem_array_ptr<DWORD>& cvalues)
- {
- size_t count = 0;
- for (auto it = cvalues.begin(); it != cvalues.end(); ++it)
- {
- ++count;
- }
- REQUIRE(count == cvalues.size());
- for (size_t index = 0; index < cvalues.size(); index++)
- {
- auto& val = cvalues[index];
- REQUIRE(val == 0);
- }
- auto& front = cvalues.front();
- REQUIRE(front == 0);
- auto& back = cvalues.back();
- REQUIRE(back == 0);
- REQUIRE(cvalues.data() != nullptr);
- }(values);
- auto data1 = values.data();
- auto data2 = values.get();
- REQUIRE((data1 && (data1 == data2)));
- values.reset();
- REQUIRE(!values);
- REQUIRE(values.empty());
- GetDWORDArray(values2.size_address(), &values2);
- size = values2.size();
- ptr = values2.release();
- values.reset(ptr, size);
- REQUIRE(!!values);
- REQUIRE(!values.empty());
- REQUIRE(values2.put() == values2.addressof());
- REQUIRE(&values2 == values2.addressof());
- }
- }
- #endif
- #if !defined(__cplusplus_winrt) && (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- TEST_CASE("WindowsInternalTests::VerifyMakeAgileCallback", "[wrl]")
- {
- using namespace ABI::Windows::Foundation;
- class CallbackClient
- {
- public:
- HRESULT On(IMemoryBufferReference*, IInspectable*)
- {
- return S_OK;
- }
- };
- CallbackClient callbackClient;
- #ifdef WIL_ENABLE_EXCEPTIONS
- auto cbAgile = wil::MakeAgileCallback<ITypedEventHandler<IMemoryBufferReference*, IInspectable*>>([](IMemoryBufferReference*, IInspectable*) -> HRESULT
- {
- return S_OK;
- });
- REQUIRE(wil::is_agile(cbAgile));
- auto cbAgileWithMember = wil::MakeAgileCallback<ITypedEventHandler<IMemoryBufferReference*, IInspectable*>>(&callbackClient, &CallbackClient::On);
- REQUIRE(wil::is_agile(cbAgileWithMember));
- #endif
- auto cbAgileNoThrow = wil::MakeAgileCallbackNoThrow<ITypedEventHandler<IMemoryBufferReference*, IInspectable*>>([](IMemoryBufferReference*, IInspectable*) -> HRESULT
- {
- return S_OK;
- });
- REQUIRE(wil::is_agile(cbAgileNoThrow));
- auto cbAgileWithMemberNoThrow = wil::MakeAgileCallbackNoThrow<ITypedEventHandler<IMemoryBufferReference*, IInspectable*>>(&callbackClient, &CallbackClient::On);
- REQUIRE(wil::is_agile(cbAgileWithMemberNoThrow));
- }
- #endif
- TEST_CASE("WindowsInternalTests::Ranges", "[common]")
- {
- {
- int things[10]{};
- unsigned int count = 0;
- for (auto& m : wil::make_range(things, ARRAYSIZE(things)))
- {
- ++count;
- m = 1;
- }
- REQUIRE(ARRAYSIZE(things) == count);
- REQUIRE(1 == things[1]);
- }
- {
- int things[10]{};
- unsigned int count = 0;
- for (auto m : wil::make_range(things, ARRAYSIZE(things)))
- {
- ++count;
- m = 1;
- (void)m;
- }
- REQUIRE(ARRAYSIZE(things) == count);
- REQUIRE(0 == things[0]);
- }
- {
- int things[10]{};
- unsigned int count = 0;
- auto range = wil::make_range(things, ARRAYSIZE(things));
- for (auto m : range)
- {
- (void)m;
- ++count;
- }
- REQUIRE(ARRAYSIZE(things) == count);
- }
- {
- int things[10]{};
- unsigned int count = 0;
- const auto range = wil::make_range(things, ARRAYSIZE(things));
- for (auto m : range)
- {
- (void)m;
- ++count;
- }
- REQUIRE(ARRAYSIZE(things) == count);
- }
- }
- TEST_CASE("WindowsInternalTests::HStringTests", "[resource][unique_any]")
- {
- const wchar_t kittens[] = L"kittens";
- {
- wchar_t* bufferStorage = nullptr;
- wil::unique_hstring_buffer theBuffer;
- REQUIRE_SUCCEEDED(::WindowsPreallocateStringBuffer(ARRAYSIZE(kittens), &bufferStorage, &theBuffer));
- REQUIRE_SUCCEEDED(StringCchCopyW(bufferStorage, ARRAYSIZE(kittens), kittens));
- // Promote sets the promoted-to value but resets theBuffer
- wil::unique_hstring promoted;
- REQUIRE_SUCCEEDED(wil::make_hstring_from_buffer_nothrow(wistd::move(theBuffer), &promoted));
- REQUIRE(static_cast<bool>(promoted));
- REQUIRE_FALSE(static_cast<bool>(theBuffer));
- }
- {
- wchar_t* bufferStorage = nullptr;
- wil::unique_hstring_buffer theBuffer;
- REQUIRE_SUCCEEDED(::WindowsPreallocateStringBuffer(ARRAYSIZE(kittens), &bufferStorage, &theBuffer));
- REQUIRE_SUCCEEDED(StringCchCopyW(bufferStorage, ARRAYSIZE(kittens), kittens));
- // Failure to promote retains the buffer state
- REQUIRE_FAILED(wil::make_hstring_from_buffer_nothrow(wistd::move(theBuffer), nullptr));
- REQUIRE(static_cast<bool>(theBuffer));
- }
- #ifdef WIL_ENABLE_EXCEPTIONS
- {
- wchar_t* bufferStorage = nullptr;
- wil::unique_hstring_buffer theBuffer;
- THROW_IF_FAILED(::WindowsPreallocateStringBuffer(ARRAYSIZE(kittens), &bufferStorage, &theBuffer));
- THROW_IF_FAILED(StringCchCopyW(bufferStorage, ARRAYSIZE(kittens), kittens));
- wil::unique_hstring promoted;
- REQUIRE_NOTHROW(promoted = wil::make_hstring_from_buffer(wistd::move(theBuffer)));
- REQUIRE(static_cast<bool>(promoted));
- REQUIRE_FALSE(static_cast<bool>(theBuffer));
- }
- #endif
- }
- struct ThreadPoolWaitTestContext
- {
- volatile LONG Counter = 0;
- wil::unique_event_nothrow Event;
- };
- static void __stdcall ThreadPoolWaitTestCallback(
- _Inout_ PTP_CALLBACK_INSTANCE /*instance*/,
- _Inout_opt_ void* context,
- _Inout_ PTP_WAIT wait,
- _In_ TP_WAIT_RESULT /*waitResult*/)
- {
- ThreadPoolWaitTestContext& myContext = *reinterpret_cast<ThreadPoolWaitTestContext*>(context);
- SetThreadpoolWait(wait, myContext.Event.get(), nullptr);
- ::InterlockedIncrement(&myContext.Counter);
- }
- template <typename WaitResourceT>
- void ThreadPoolWaitTestHelper(bool requireExactCallbackCount)
- {
- ThreadPoolWaitTestContext myContext;
- REQUIRE_SUCCEEDED(myContext.Event.create());
- WaitResourceT wait;
- wait.reset(CreateThreadpoolWait(ThreadPoolWaitTestCallback, &myContext, nullptr));
- REQUIRE(wait);
- SetThreadpoolWait(wait.get(), myContext.Event.get(), nullptr);
- constexpr int loopCount = 5;
- for (int currCallbackCount = 0; currCallbackCount != loopCount; ++currCallbackCount)
- {
- // Signal event.
- myContext.Event.SetEvent();
- // Wait until 'myContext.Counter' increments by 1.
- for (int itr = 0; itr != 50 && currCallbackCount == myContext.Counter; ++itr)
- {
- Sleep(10);
- }
- // Ensure we didn't timeout
- REQUIRE(currCallbackCount + 1 == myContext.Counter);
- }
- // Signal one last event.
- myContext.Event.SetEvent();
- // Close thread-pool wait.
- wait.reset();
- myContext.Event.reset();
- // Verify counter.
- if (requireExactCallbackCount)
- {
- REQUIRE(loopCount + 1 == myContext.Counter);
- }
- else
- {
- REQUIRE((loopCount + 1 == myContext.Counter || loopCount == myContext.Counter));
- }
- }
- TEST_CASE("WindowsInternalTests::ThreadPoolWaitTest", "[resource][unique_threadpool_wait]")
- {
- ThreadPoolWaitTestHelper<wil::unique_threadpool_wait>(false);
- ThreadPoolWaitTestHelper<wil::unique_threadpool_wait_nocancel>(true);
- }
- struct ThreadPoolWaitWorkContext
- {
- volatile LONG Counter = 0;
- };
- static void __stdcall ThreadPoolWaitWorkCallback(
- _Inout_ PTP_CALLBACK_INSTANCE /*instance*/,
- _Inout_opt_ void* context,
- _Inout_ PTP_WORK /*work*/)
- {
- ThreadPoolWaitWorkContext& myContext = *reinterpret_cast<ThreadPoolWaitWorkContext*>(context);
- ::InterlockedIncrement(&myContext.Counter);
- }
- template <typename WaitResourceT>
- void ThreadPoolWaitWorkHelper(bool requireExactCallbackCount)
- {
- ThreadPoolWaitWorkContext myContext;
- WaitResourceT work;
- work.reset(CreateThreadpoolWork(ThreadPoolWaitWorkCallback, &myContext, nullptr));
- REQUIRE(work);
- constexpr int loopCount = 5;
- for (int itr = 0; itr != loopCount; ++itr)
- {
- SubmitThreadpoolWork(work.get());
- }
- work.reset();
- if (requireExactCallbackCount)
- {
- REQUIRE(loopCount == myContext.Counter);
- }
- else
- {
- REQUIRE(loopCount >= myContext.Counter);
- }
- }
- TEST_CASE("WindowsInternalTests::ThreadPoolWorkTest", "[resource][unique_threadpool_work]")
- {
- ThreadPoolWaitWorkHelper<wil::unique_threadpool_work>(false);
- ThreadPoolWaitWorkHelper<wil::unique_threadpool_work_nocancel>(true);
- }
- struct ThreadPoolTimerWorkContext
- {
- volatile LONG Counter = 0;
- wil::unique_event_nothrow Event;
- };
- static void __stdcall ThreadPoolTimerWorkCallback(
- _Inout_ PTP_CALLBACK_INSTANCE /*instance*/,
- _Inout_opt_ void* context,
- _Inout_ PTP_TIMER /*timer*/)
- {
- ThreadPoolTimerWorkContext& myContext = *reinterpret_cast<ThreadPoolTimerWorkContext*>(context);
- myContext.Event.SetEvent();
- ::InterlockedIncrement(&myContext.Counter);
- }
- template <typename TimerResourceT, typename DueTimeT, typename SetThreadpoolTimerT>
- void ThreadPoolTimerWorkHelper(SetThreadpoolTimerT const &setThreadpoolTimerFn, bool requireExactCallbackCount)
- {
- ThreadPoolTimerWorkContext myContext;
- REQUIRE_SUCCEEDED(myContext.Event.create());
- TimerResourceT timer;
- timer.reset(CreateThreadpoolTimer(ThreadPoolTimerWorkCallback, &myContext, nullptr));
- REQUIRE(timer);
- constexpr int loopCount = 5;
- for (int currCallbackCount = 0; currCallbackCount != loopCount; ++currCallbackCount)
- {
- // Schedule timer
- myContext.Event.ResetEvent();
- const auto allowedWindow = 0;
- LONGLONG dueTime = -5 * 10000I64; // 5ms
- setThreadpoolTimerFn(timer.get(), reinterpret_cast<DueTimeT *>(&dueTime), 0, allowedWindow);
- // Wait until 'myContext.Counter' increments by 1.
- REQUIRE(myContext.Event.wait(500));
- for (int itr = 0; itr != 50 && currCallbackCount == myContext.Counter; ++itr)
- {
- Sleep(10);
- }
- // Ensure we didn't timeout
- REQUIRE(currCallbackCount + 1 == myContext.Counter);
- }
- // Schedule one last timer.
- myContext.Event.ResetEvent();
- const auto allowedWindow = 0;
- LONGLONG dueTime = -5 * 10000I64; // 5ms
- setThreadpoolTimerFn(timer.get(), reinterpret_cast<DueTimeT *>(&dueTime), 0, allowedWindow);
- if (requireExactCallbackCount)
- {
- // Wait for the event to be set
- REQUIRE(myContext.Event.wait(500));
- }
- // Close timer.
- timer.reset();
- myContext.Event.reset();
- // Verify counter.
- if (requireExactCallbackCount)
- {
- REQUIRE(loopCount + 1 == myContext.Counter);
- }
- else
- {
- REQUIRE((loopCount + 1 == myContext.Counter || loopCount == myContext.Counter));
- }
- }
- TEST_CASE("WindowsInternalTests::ThreadPoolTimerTest", "[resource][unique_threadpool_timer]")
- {
- static_assert(sizeof(FILETIME) == sizeof(LONGLONG), "FILETIME and LONGLONG must be same size");
- ThreadPoolTimerWorkHelper<wil::unique_threadpool_timer, FILETIME>(SetThreadpoolTimer, false);
- ThreadPoolTimerWorkHelper<wil::unique_threadpool_timer_nocancel, FILETIME>(SetThreadpoolTimer, true);
- }
- #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- static void __stdcall SlimEventTrollCallback(
- _Inout_ PTP_CALLBACK_INSTANCE /*instance*/,
- _Inout_opt_ void* context,
- _Inout_ PTP_TIMER /*timer*/)
- {
- auto event = reinterpret_cast<wil::slim_event*>(context);
- // Wake up the thread without setting the event.
- // Note: This relies on the fact that the 'wil::slim_event' class only has a single member variable.
- WakeByAddressAll(event);
- }
- static void __stdcall SlimEventFriendlyCallback(
- _Inout_ PTP_CALLBACK_INSTANCE /*instance*/,
- _Inout_opt_ void* context,
- _Inout_ PTP_TIMER /*timer*/)
- {
- auto event = reinterpret_cast<wil::slim_event*>(context);
- event->SetEvent();
- }
- TEST_CASE("WindowsInternalTests::SlimEventTests", "[resource][slim_event]")
- {
- {
- wil::slim_event event;
- // Verify simple timeouts work on an auto-reset event.
- REQUIRE_FALSE(event.wait(/*timeout(ms)*/ 0));
- REQUIRE_FALSE(event.wait(/*timeout(ms)*/ 10));
- wil::unique_threadpool_timer trollTimer(CreateThreadpoolTimer(SlimEventTrollCallback, &event, nullptr));
- REQUIRE(trollTimer);
- FILETIME trollDueTime = wil::filetime::from_int64(0);
- SetThreadpoolTimer(trollTimer.get(), &trollDueTime, /*period(ms)*/ 5, /*window(ms)*/ 0);
- // Ensure we timeout in spite of being constantly woken up unnecessarily.
- REQUIRE_FALSE(event.wait(/*timeout(ms)*/ 100));
- wil::unique_threadpool_timer friendlyTimer(CreateThreadpoolTimer(SlimEventFriendlyCallback, &event, nullptr));
- REQUIRE(friendlyTimer);
- FILETIME friendlyDueTime = wil::filetime::from_int64(UINT64(-100 * wil::filetime_duration::one_millisecond)); // 100ms (relative to now)
- SetThreadpoolTimer(friendlyTimer.get(), &friendlyDueTime, /*period(ms)*/ 0, /*window(ms)*/ 0);
- // Now that the 'friendlyTimer' is queued, we should succeed.
- REQUIRE(event.wait(INFINITE));
- // Ensure event is auto-reset.
- REQUIRE_FALSE(event.wait(/*timeout(ms)*/ 100));
- }
- {
- wil::slim_event_manual_reset manualResetEvent;
- // Verify simple timeouts work on a manual-reset event.
- REQUIRE_FALSE(manualResetEvent.wait(/*timeout(ms)*/ 0));
- REQUIRE_FALSE(manualResetEvent.wait(/*timeout(ms)*/ 10));
- // Ensure multiple waits can occur on a manual-reset event.
- manualResetEvent.SetEvent();
- REQUIRE(manualResetEvent.wait());
- REQUIRE(manualResetEvent.wait(/*timeout(ms)*/ 100));
- REQUIRE(manualResetEvent.wait(INFINITE));
- // Verify 'ResetEvent' works.
- manualResetEvent.ResetEvent();
- REQUIRE_FALSE(manualResetEvent.wait(/*timeout(ms)*/ 10));
- }
- }
- #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- struct ConditionVariableCSCallbackContext
- {
- wil::condition_variable event;
- wil::critical_section lock;
- auto acquire() { return lock.lock(); }
- };
- struct ConditionVariableSRWCallbackContext
- {
- wil::condition_variable event;
- wil::srwlock lock;
- auto acquire() { return lock.lock_exclusive(); }
- };
- template <typename T>
- static void __stdcall ConditionVariableCallback(
- _Inout_ PTP_CALLBACK_INSTANCE /*Instance*/,
- _In_ void* Context)
- {
- auto callbackContext = reinterpret_cast<T*>(Context);
- // Acquire the lock to ensure we don't notify the condition variable before the other thread has
- // gone to sleep.
- auto gate = callbackContext->acquire();
- // Signal the condition variable.
- callbackContext->event.notify_all();
- }
- // A quick sanity check of the 'wil::condition_variable' type.
- TEST_CASE("WindowsInternalTests::ConditionVariableTests", "[resource][condition_variable]")
- {
- SECTION("Test 'wil::condition_variable' with 'wil::critical_section'")
- {
- ConditionVariableCSCallbackContext callbackContext;
- auto gate = callbackContext.lock.lock();
- // Schedule the thread that will wake up this thread.
- REQUIRE(TrySubmitThreadpoolCallback(ConditionVariableCallback<ConditionVariableCSCallbackContext>, &callbackContext, nullptr));
- // Wait on the condition variable.
- REQUIRE(callbackContext.event.wait_for(gate, /*timeout(ms)*/ 500));
- }
- SECTION("Test 'wil::condition_variable' with 'wil::srwlock'")
- {
- ConditionVariableSRWCallbackContext callbackContext;
- // Test exclusive lock.
- {
- auto gate = callbackContext.lock.lock_exclusive();
- // Schedule the thread that will wake up this thread.
- REQUIRE(TrySubmitThreadpoolCallback(ConditionVariableCallback<ConditionVariableSRWCallbackContext>, &callbackContext, nullptr));
- // Wait on the condition variable.
- REQUIRE(callbackContext.event.wait_for(gate, /*timeout(ms)*/ 500));
- }
- // Test shared lock.
- {
- auto gate = callbackContext.lock.lock_shared();
- // Schedule the thread that will wake up this thread.
- REQUIRE(TrySubmitThreadpoolCallback(ConditionVariableCallback<ConditionVariableSRWCallbackContext>, &callbackContext, nullptr));
- // Wait on the condition variable.
- REQUIRE(callbackContext.event.wait_for(gate, /*timeout(ms)*/ 500));
- }
- }
- }
- TEST_CASE("WindowsInternalTests::ReturnWithExpectedTests", "[result_macros]")
- {
- wil::g_pfnResultLoggingCallback = ResultMacrosLoggingCallback;
- // Succeeded
- REQUIRE_RETURNS_EXPECTED(S_OK, [] { RETURN_IF_FAILED_WITH_EXPECTED(MDEC(hrOKRef()), E_UNEXPECTED); return S_OK; });
- // Expected
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { RETURN_IF_FAILED_WITH_EXPECTED(E_FAIL, E_FAIL); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_UNEXPECTED, [] { RETURN_IF_FAILED_WITH_EXPECTED(E_UNEXPECTED, E_FAIL, E_UNEXPECTED, E_POINTER, E_INVALIDARG); return S_OK; });
- // Unexpected
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { RETURN_IF_FAILED_WITH_EXPECTED(E_FAIL, E_UNEXPECTED); return S_OK; });
- REQUIRE_RETURNS_EXPECTED(E_FAIL, [] { RETURN_IF_FAILED_WITH_EXPECTED(E_FAIL, E_UNEXPECTED, E_POINTER, E_INVALIDARG); return S_OK; });
- }
- TEST_CASE("WindowsInternalTests::LogWithExpectedTests", "[result_macros]")
- {
- wil::g_pfnResultLoggingCallback = ResultMacrosLoggingCallback;
- // Succeeded
- REQUIRE_LOG(S_OK, [] { REQUIRE(S_OK == LOG_IF_FAILED_WITH_EXPECTED(MDEC(hrOKRef()), E_FAIL, E_INVALIDARG)); });
- // Expected
- REQUIRE_LOG(S_OK, [] { REQUIRE(E_UNEXPECTED == LOG_IF_FAILED_WITH_EXPECTED(E_UNEXPECTED, E_UNEXPECTED, E_INVALIDARG)); });
- REQUIRE_LOG(S_OK, [] { REQUIRE(E_UNEXPECTED == LOG_IF_FAILED_WITH_EXPECTED(E_UNEXPECTED, E_FAIL, E_UNEXPECTED, E_POINTER, E_INVALIDARG)); });
- // Unexpected
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(E_FAIL == LOG_IF_FAILED_WITH_EXPECTED(E_FAIL, E_UNEXPECTED)); });
- REQUIRE_LOG(E_FAIL, [] { REQUIRE(E_FAIL == LOG_IF_FAILED_WITH_EXPECTED(E_FAIL, E_UNEXPECTED, E_POINTER, E_INVALIDARG)); });
- }
- // Verifies that the shutdown-aware objects respect the alignment
- // of the wrapped object.
- template<template<typename> class Wrapper>
- void VerifyAlignment()
- {
- // Some of the wrappers require a method called ProcessShutdown(), so we'll give it one.
- struct alignment_sensitive_struct
- {
- // Use SLIST_HEADER as our poster child alignment-sensitive data type.
- SLIST_HEADER value;
- void ProcessShutdown() { }
- };
- static_assert(alignof(alignment_sensitive_struct) != alignof(char), "Need to choose a better alignment-sensitive type");
- // Create a custom structure that tries to force misalignment.
- struct attempted_misalignment
- {
- char c;
- Wrapper<alignment_sensitive_struct> wrapper;
- } possibly_misaligned{};
- static_assert(alignof(attempted_misalignment) == alignof(alignment_sensitive_struct), "Wrapper type does not respect alignment");
- // Verify that the wrapper type placed the inner object at proper alignment.
- // Note: use std::addressof in case the alignment_sensitive_struct overrides the & operator.
- REQUIRE(reinterpret_cast<uintptr_t>(std::addressof(possibly_misaligned.wrapper.get())) % alignof(alignment_sensitive_struct) == 0);
- }
- TEST_CASE("WindowsInternalTests::ShutdownAwareObjectAlignmentTests", "[result_macros]")
- {
- VerifyAlignment<wil::manually_managed_shutdown_aware_object>();
- VerifyAlignment<wil::shutdown_aware_object>();
- VerifyAlignment<wil::object_without_destructor_on_shutdown>();
- }
- #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- TEST_CASE("WindowsInternalTests::ModuleReference", "[wrl]")
- {
- REQUIRE(::Microsoft::WRL::GetModuleBase() == nullptr);
- // Executables don't have a ModuleBase, so we need to create one.
- struct FakeModuleBase : Microsoft::WRL::Details::ModuleBase
- {
- unsigned long count = 42;
- STDMETHOD_(unsigned long, IncrementObjectCount)()
- {
- return InterlockedIncrement(&count);
- }
- STDMETHOD_(unsigned long, DecrementObjectCount)()
- {
- return InterlockedDecrement(&count);
- }
- STDMETHOD_(unsigned long, GetObjectCount)() const
- {
- return count;
- }
- // Dummy implementations of everything else (never called).
- STDMETHOD_(const Microsoft::WRL::Details::CreatorMap**, GetFirstEntryPointer)() const { return nullptr; }
- STDMETHOD_(const Microsoft::WRL::Details::CreatorMap**, GetMidEntryPointer)() const { return nullptr; }
- STDMETHOD_(const Microsoft::WRL::Details::CreatorMap**, GetLastEntryPointer)() const { return nullptr; }
- STDMETHOD_(SRWLOCK*, GetLock)() const { return nullptr; }
- STDMETHOD(RegisterWinRTObject)(const wchar_t*, const wchar_t**, _Inout_ RO_REGISTRATION_COOKIE*, unsigned int) { return E_NOTIMPL; }
- STDMETHOD(UnregisterWinRTObject)(const wchar_t*, _In_ RO_REGISTRATION_COOKIE) { return E_NOTIMPL; }
- STDMETHOD(RegisterCOMObject)(const wchar_t*, _In_ IID*, _In_ IClassFactory**, _Inout_ DWORD*, unsigned int) { return E_NOTIMPL; }
- STDMETHOD(UnregisterCOMObject)(const wchar_t*, _Inout_ DWORD*, unsigned int) { return E_NOTIMPL; }
- };
- FakeModuleBase fake;
- auto peek_module_ref_count = []()
- {
- return ::Microsoft::WRL::GetModuleBase()->GetObjectCount();
- };
- auto initial = peek_module_ref_count();
- // Basic test: Construct and destruct.
- {
- auto module_ref = wil::wrl_module_reference();
- REQUIRE(peek_module_ref_count() == initial + 1);
- }
- REQUIRE(peek_module_ref_count() == initial);
- // Fancy test: Copy object with embedded reference.
- {
- struct object_with_ref
- {
- wil::wrl_module_reference ref;
- };
- object_with_ref o1;
- REQUIRE(peek_module_ref_count() == initial + 1);
- auto o2 = o1;
- REQUIRE(peek_module_ref_count() == initial + 2);
- o1 = o2;
- REQUIRE(peek_module_ref_count() == initial + 2);
- o2 = std::move(o1);
- REQUIRE(peek_module_ref_count() == initial + 2);
- }
- REQUIRE(peek_module_ref_count() == initial);
- }
- #endif
- #if defined(WIL_ENABLE_EXCEPTIONS) && (defined(NTDDI_WIN10_CO) ? \
- WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) : \
- WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES))
- TEST_CASE("WindowsInternalTests::VerifyModuleReferencesForThread", "[win32_helpers]")
- {
- bool success = true;
- std::thread([&]
- {
- auto moduleRef = wil::get_module_reference_for_thread();
- moduleRef.reset(); // results in exiting the thread
- // should never get here
- success = false;
- FAIL();
- }).join();
- REQUIRE(success);
- }
- #endif
- #pragma warning(pop)
|