catch_amalgamated.cpp 413 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811
  1. // Copyright Catch2 Authors
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.txt or copy at
  4. // https://www.boost.org/LICENSE_1_0.txt)
  5. // SPDX-License-Identifier: BSL-1.0
  6. // Catch v3.7.1
  7. // Generated: 2024-09-17 10:36:45.608896
  8. // ----------------------------------------------------------
  9. // This file is an amalgamation of multiple different files.
  10. // You probably shouldn't edit it directly.
  11. // ----------------------------------------------------------
  12. #include "catch_amalgamated.hpp"
  13. #ifndef CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
  14. #define CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
  15. #if defined(CATCH_PLATFORM_WINDOWS)
  16. // We might end up with the define made globally through the compiler,
  17. // and we don't want to trigger warnings for this
  18. #if !defined(NOMINMAX)
  19. # define NOMINMAX
  20. #endif
  21. #if !defined(WIN32_LEAN_AND_MEAN)
  22. # define WIN32_LEAN_AND_MEAN
  23. #endif
  24. #include <windows.h>
  25. #endif // defined(CATCH_PLATFORM_WINDOWS)
  26. #endif // CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
  27. namespace Catch {
  28. namespace Benchmark {
  29. namespace Detail {
  30. ChronometerConcept::~ChronometerConcept() = default;
  31. } // namespace Detail
  32. } // namespace Benchmark
  33. } // namespace Catch
  34. // Adapted from donated nonius code.
  35. #include <vector>
  36. namespace Catch {
  37. namespace Benchmark {
  38. namespace Detail {
  39. SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last) {
  40. if (!cfg.benchmarkNoAnalysis()) {
  41. std::vector<double> samples;
  42. samples.reserve(static_cast<size_t>(last - first));
  43. for (auto current = first; current != last; ++current) {
  44. samples.push_back( current->count() );
  45. }
  46. auto analysis = Catch::Benchmark::Detail::analyse_samples(
  47. cfg.benchmarkConfidenceInterval(),
  48. cfg.benchmarkResamples(),
  49. samples.data(),
  50. samples.data() + samples.size() );
  51. auto outliers = Catch::Benchmark::Detail::classify_outliers(
  52. samples.data(), samples.data() + samples.size() );
  53. auto wrap_estimate = [](Estimate<double> e) {
  54. return Estimate<FDuration> {
  55. FDuration(e.point),
  56. FDuration(e.lower_bound),
  57. FDuration(e.upper_bound),
  58. e.confidence_interval,
  59. };
  60. };
  61. std::vector<FDuration> samples2;
  62. samples2.reserve(samples.size());
  63. for (auto s : samples) {
  64. samples2.push_back( FDuration( s ) );
  65. }
  66. return {
  67. CATCH_MOVE(samples2),
  68. wrap_estimate(analysis.mean),
  69. wrap_estimate(analysis.standard_deviation),
  70. outliers,
  71. analysis.outlier_variance,
  72. };
  73. } else {
  74. std::vector<FDuration> samples;
  75. samples.reserve(static_cast<size_t>(last - first));
  76. FDuration mean = FDuration(0);
  77. int i = 0;
  78. for (auto it = first; it < last; ++it, ++i) {
  79. samples.push_back(*it);
  80. mean += *it;
  81. }
  82. mean /= i;
  83. return SampleAnalysis{
  84. CATCH_MOVE(samples),
  85. Estimate<FDuration>{ mean, mean, mean, 0.0 },
  86. Estimate<FDuration>{ FDuration( 0 ),
  87. FDuration( 0 ),
  88. FDuration( 0 ),
  89. 0.0 },
  90. OutlierClassification{},
  91. 0.0
  92. };
  93. }
  94. }
  95. } // namespace Detail
  96. } // namespace Benchmark
  97. } // namespace Catch
  98. namespace Catch {
  99. namespace Benchmark {
  100. namespace Detail {
  101. struct do_nothing {
  102. void operator()() const {}
  103. };
  104. BenchmarkFunction::callable::~callable() = default;
  105. BenchmarkFunction::BenchmarkFunction():
  106. f( new model<do_nothing>{ {} } ){}
  107. } // namespace Detail
  108. } // namespace Benchmark
  109. } // namespace Catch
  110. #include <exception>
  111. namespace Catch {
  112. namespace Benchmark {
  113. namespace Detail {
  114. struct optimized_away_error : std::exception {
  115. const char* what() const noexcept override;
  116. };
  117. const char* optimized_away_error::what() const noexcept {
  118. return "could not measure benchmark, maybe it was optimized away";
  119. }
  120. void throw_optimized_away_error() {
  121. Catch::throw_exception(optimized_away_error{});
  122. }
  123. } // namespace Detail
  124. } // namespace Benchmark
  125. } // namespace Catch
  126. // Adapted from donated nonius code.
  127. #include <algorithm>
  128. #include <cassert>
  129. #include <cmath>
  130. #include <cstddef>
  131. #include <numeric>
  132. #include <random>
  133. #if defined(CATCH_CONFIG_USE_ASYNC)
  134. #include <future>
  135. #endif
  136. namespace Catch {
  137. namespace Benchmark {
  138. namespace Detail {
  139. namespace {
  140. template <typename URng, typename Estimator>
  141. static sample
  142. resample( URng& rng,
  143. unsigned int resamples,
  144. double const* first,
  145. double const* last,
  146. Estimator& estimator ) {
  147. auto n = static_cast<size_t>( last - first );
  148. Catch::uniform_integer_distribution<size_t> dist( 0, n - 1 );
  149. sample out;
  150. out.reserve( resamples );
  151. std::vector<double> resampled;
  152. resampled.reserve( n );
  153. for ( size_t i = 0; i < resamples; ++i ) {
  154. resampled.clear();
  155. for ( size_t s = 0; s < n; ++s ) {
  156. resampled.push_back( first[dist( rng )] );
  157. }
  158. const auto estimate =
  159. estimator( resampled.data(), resampled.data() + resampled.size() );
  160. out.push_back( estimate );
  161. }
  162. std::sort( out.begin(), out.end() );
  163. return out;
  164. }
  165. static double outlier_variance( Estimate<double> mean,
  166. Estimate<double> stddev,
  167. int n ) {
  168. double sb = stddev.point;
  169. double mn = mean.point / n;
  170. double mg_min = mn / 2.;
  171. double sg = (std::min)( mg_min / 4., sb / std::sqrt( n ) );
  172. double sg2 = sg * sg;
  173. double sb2 = sb * sb;
  174. auto c_max = [n, mn, sb2, sg2]( double x ) -> double {
  175. double k = mn - x;
  176. double d = k * k;
  177. double nd = n * d;
  178. double k0 = -n * nd;
  179. double k1 = sb2 - n * sg2 + nd;
  180. double det = k1 * k1 - 4 * sg2 * k0;
  181. return static_cast<int>( -2. * k0 /
  182. ( k1 + std::sqrt( det ) ) );
  183. };
  184. auto var_out = [n, sb2, sg2]( double c ) {
  185. double nc = n - c;
  186. return ( nc / n ) * ( sb2 - nc * sg2 );
  187. };
  188. return (std::min)( var_out( 1 ),
  189. var_out(
  190. (std::min)( c_max( 0. ),
  191. c_max( mg_min ) ) ) ) /
  192. sb2;
  193. }
  194. static double erf_inv( double x ) {
  195. // Code accompanying the article "Approximating the erfinv
  196. // function" in GPU Computing Gems, Volume 2
  197. double w, p;
  198. w = -log( ( 1.0 - x ) * ( 1.0 + x ) );
  199. if ( w < 6.250000 ) {
  200. w = w - 3.125000;
  201. p = -3.6444120640178196996e-21;
  202. p = -1.685059138182016589e-19 + p * w;
  203. p = 1.2858480715256400167e-18 + p * w;
  204. p = 1.115787767802518096e-17 + p * w;
  205. p = -1.333171662854620906e-16 + p * w;
  206. p = 2.0972767875968561637e-17 + p * w;
  207. p = 6.6376381343583238325e-15 + p * w;
  208. p = -4.0545662729752068639e-14 + p * w;
  209. p = -8.1519341976054721522e-14 + p * w;
  210. p = 2.6335093153082322977e-12 + p * w;
  211. p = -1.2975133253453532498e-11 + p * w;
  212. p = -5.4154120542946279317e-11 + p * w;
  213. p = 1.051212273321532285e-09 + p * w;
  214. p = -4.1126339803469836976e-09 + p * w;
  215. p = -2.9070369957882005086e-08 + p * w;
  216. p = 4.2347877827932403518e-07 + p * w;
  217. p = -1.3654692000834678645e-06 + p * w;
  218. p = -1.3882523362786468719e-05 + p * w;
  219. p = 0.0001867342080340571352 + p * w;
  220. p = -0.00074070253416626697512 + p * w;
  221. p = -0.0060336708714301490533 + p * w;
  222. p = 0.24015818242558961693 + p * w;
  223. p = 1.6536545626831027356 + p * w;
  224. } else if ( w < 16.000000 ) {
  225. w = sqrt( w ) - 3.250000;
  226. p = 2.2137376921775787049e-09;
  227. p = 9.0756561938885390979e-08 + p * w;
  228. p = -2.7517406297064545428e-07 + p * w;
  229. p = 1.8239629214389227755e-08 + p * w;
  230. p = 1.5027403968909827627e-06 + p * w;
  231. p = -4.013867526981545969e-06 + p * w;
  232. p = 2.9234449089955446044e-06 + p * w;
  233. p = 1.2475304481671778723e-05 + p * w;
  234. p = -4.7318229009055733981e-05 + p * w;
  235. p = 6.8284851459573175448e-05 + p * w;
  236. p = 2.4031110387097893999e-05 + p * w;
  237. p = -0.0003550375203628474796 + p * w;
  238. p = 0.00095328937973738049703 + p * w;
  239. p = -0.0016882755560235047313 + p * w;
  240. p = 0.0024914420961078508066 + p * w;
  241. p = -0.0037512085075692412107 + p * w;
  242. p = 0.005370914553590063617 + p * w;
  243. p = 1.0052589676941592334 + p * w;
  244. p = 3.0838856104922207635 + p * w;
  245. } else {
  246. w = sqrt( w ) - 5.000000;
  247. p = -2.7109920616438573243e-11;
  248. p = -2.5556418169965252055e-10 + p * w;
  249. p = 1.5076572693500548083e-09 + p * w;
  250. p = -3.7894654401267369937e-09 + p * w;
  251. p = 7.6157012080783393804e-09 + p * w;
  252. p = -1.4960026627149240478e-08 + p * w;
  253. p = 2.9147953450901080826e-08 + p * w;
  254. p = -6.7711997758452339498e-08 + p * w;
  255. p = 2.2900482228026654717e-07 + p * w;
  256. p = -9.9298272942317002539e-07 + p * w;
  257. p = 4.5260625972231537039e-06 + p * w;
  258. p = -1.9681778105531670567e-05 + p * w;
  259. p = 7.5995277030017761139e-05 + p * w;
  260. p = -0.00021503011930044477347 + p * w;
  261. p = -0.00013871931833623122026 + p * w;
  262. p = 1.0103004648645343977 + p * w;
  263. p = 4.8499064014085844221 + p * w;
  264. }
  265. return p * x;
  266. }
  267. static double
  268. standard_deviation( double const* first, double const* last ) {
  269. auto m = Catch::Benchmark::Detail::mean( first, last );
  270. double variance =
  271. std::accumulate( first,
  272. last,
  273. 0.,
  274. [m]( double a, double b ) {
  275. double diff = b - m;
  276. return a + diff * diff;
  277. } ) /
  278. ( last - first );
  279. return std::sqrt( variance );
  280. }
  281. static sample jackknife( double ( *estimator )( double const*,
  282. double const* ),
  283. double* first,
  284. double* last ) {
  285. const auto second = first + 1;
  286. sample results;
  287. results.reserve( static_cast<size_t>( last - first ) );
  288. for ( auto it = first; it != last; ++it ) {
  289. std::iter_swap( it, first );
  290. results.push_back( estimator( second, last ) );
  291. }
  292. return results;
  293. }
  294. } // namespace
  295. } // namespace Detail
  296. } // namespace Benchmark
  297. } // namespace Catch
  298. namespace Catch {
  299. namespace Benchmark {
  300. namespace Detail {
  301. double weighted_average_quantile( int k,
  302. int q,
  303. double* first,
  304. double* last ) {
  305. auto count = last - first;
  306. double idx = (count - 1) * k / static_cast<double>(q);
  307. int j = static_cast<int>(idx);
  308. double g = idx - j;
  309. std::nth_element(first, first + j, last);
  310. auto xj = first[j];
  311. if ( Catch::Detail::directCompare( g, 0 ) ) {
  312. return xj;
  313. }
  314. auto xj1 = *std::min_element(first + (j + 1), last);
  315. return xj + g * (xj1 - xj);
  316. }
  317. OutlierClassification
  318. classify_outliers( double const* first, double const* last ) {
  319. std::vector<double> copy( first, last );
  320. auto q1 = weighted_average_quantile( 1, 4, copy.data(), copy.data() + copy.size() );
  321. auto q3 = weighted_average_quantile( 3, 4, copy.data(), copy.data() + copy.size() );
  322. auto iqr = q3 - q1;
  323. auto los = q1 - ( iqr * 3. );
  324. auto lom = q1 - ( iqr * 1.5 );
  325. auto him = q3 + ( iqr * 1.5 );
  326. auto his = q3 + ( iqr * 3. );
  327. OutlierClassification o;
  328. for ( ; first != last; ++first ) {
  329. const double t = *first;
  330. if ( t < los ) {
  331. ++o.low_severe;
  332. } else if ( t < lom ) {
  333. ++o.low_mild;
  334. } else if ( t > his ) {
  335. ++o.high_severe;
  336. } else if ( t > him ) {
  337. ++o.high_mild;
  338. }
  339. ++o.samples_seen;
  340. }
  341. return o;
  342. }
  343. double mean( double const* first, double const* last ) {
  344. auto count = last - first;
  345. double sum = 0.;
  346. while (first != last) {
  347. sum += *first;
  348. ++first;
  349. }
  350. return sum / static_cast<double>(count);
  351. }
  352. double normal_cdf( double x ) {
  353. return std::erfc( -x / std::sqrt( 2.0 ) ) / 2.0;
  354. }
  355. double erfc_inv(double x) {
  356. return erf_inv(1.0 - x);
  357. }
  358. double normal_quantile(double p) {
  359. static const double ROOT_TWO = std::sqrt(2.0);
  360. double result = 0.0;
  361. assert(p >= 0 && p <= 1);
  362. if (p < 0 || p > 1) {
  363. return result;
  364. }
  365. result = -erfc_inv(2.0 * p);
  366. // result *= normal distribution standard deviation (1.0) * sqrt(2)
  367. result *= /*sd * */ ROOT_TWO;
  368. // result += normal disttribution mean (0)
  369. return result;
  370. }
  371. Estimate<double>
  372. bootstrap( double confidence_level,
  373. double* first,
  374. double* last,
  375. sample const& resample,
  376. double ( *estimator )( double const*, double const* ) ) {
  377. auto n_samples = last - first;
  378. double point = estimator( first, last );
  379. // Degenerate case with a single sample
  380. if ( n_samples == 1 )
  381. return { point, point, point, confidence_level };
  382. sample jack = jackknife( estimator, first, last );
  383. double jack_mean =
  384. mean( jack.data(), jack.data() + jack.size() );
  385. double sum_squares = 0, sum_cubes = 0;
  386. for ( double x : jack ) {
  387. auto difference = jack_mean - x;
  388. auto square = difference * difference;
  389. auto cube = square * difference;
  390. sum_squares += square;
  391. sum_cubes += cube;
  392. }
  393. double accel = sum_cubes / ( 6 * std::pow( sum_squares, 1.5 ) );
  394. long n = static_cast<long>( resample.size() );
  395. double prob_n =
  396. std::count_if( resample.begin(),
  397. resample.end(),
  398. [point]( double x ) { return x < point; } ) /
  399. static_cast<double>( n );
  400. // degenerate case with uniform samples
  401. if ( Catch::Detail::directCompare( prob_n, 0. ) ) {
  402. return { point, point, point, confidence_level };
  403. }
  404. double bias = normal_quantile( prob_n );
  405. double z1 = normal_quantile( ( 1. - confidence_level ) / 2. );
  406. auto cumn = [n]( double x ) -> long {
  407. return std::lround( normal_cdf( x ) *
  408. static_cast<double>( n ) );
  409. };
  410. auto a = [bias, accel]( double b ) {
  411. return bias + b / ( 1. - accel * b );
  412. };
  413. double b1 = bias + z1;
  414. double b2 = bias - z1;
  415. double a1 = a( b1 );
  416. double a2 = a( b2 );
  417. auto lo = static_cast<size_t>( (std::max)( cumn( a1 ), 0l ) );
  418. auto hi =
  419. static_cast<size_t>( (std::min)( cumn( a2 ), n - 1 ) );
  420. return { point, resample[lo], resample[hi], confidence_level };
  421. }
  422. bootstrap_analysis analyse_samples(double confidence_level,
  423. unsigned int n_resamples,
  424. double* first,
  425. double* last) {
  426. auto mean = &Detail::mean;
  427. auto stddev = &standard_deviation;
  428. #if defined(CATCH_CONFIG_USE_ASYNC)
  429. auto Estimate = [=](double(*f)(double const*, double const*)) {
  430. std::random_device rd;
  431. auto seed = rd();
  432. return std::async(std::launch::async, [=] {
  433. SimplePcg32 rng( seed );
  434. auto resampled = resample(rng, n_resamples, first, last, f);
  435. return bootstrap(confidence_level, first, last, resampled, f);
  436. });
  437. };
  438. auto mean_future = Estimate(mean);
  439. auto stddev_future = Estimate(stddev);
  440. auto mean_estimate = mean_future.get();
  441. auto stddev_estimate = stddev_future.get();
  442. #else
  443. auto Estimate = [=](double(*f)(double const* , double const*)) {
  444. std::random_device rd;
  445. auto seed = rd();
  446. SimplePcg32 rng( seed );
  447. auto resampled = resample(rng, n_resamples, first, last, f);
  448. return bootstrap(confidence_level, first, last, resampled, f);
  449. };
  450. auto mean_estimate = Estimate(mean);
  451. auto stddev_estimate = Estimate(stddev);
  452. #endif // CATCH_USE_ASYNC
  453. auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
  454. double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n);
  455. return { mean_estimate, stddev_estimate, outlier_variance };
  456. }
  457. } // namespace Detail
  458. } // namespace Benchmark
  459. } // namespace Catch
  460. #include <cmath>
  461. #include <limits>
  462. namespace {
  463. // Performs equivalent check of std::fabs(lhs - rhs) <= margin
  464. // But without the subtraction to allow for INFINITY in comparison
  465. bool marginComparison(double lhs, double rhs, double margin) {
  466. return (lhs + margin >= rhs) && (rhs + margin >= lhs);
  467. }
  468. }
  469. namespace Catch {
  470. Approx::Approx ( double value )
  471. : m_epsilon( static_cast<double>(std::numeric_limits<float>::epsilon())*100. ),
  472. m_margin( 0.0 ),
  473. m_scale( 0.0 ),
  474. m_value( value )
  475. {}
  476. Approx Approx::custom() {
  477. return Approx( 0 );
  478. }
  479. Approx Approx::operator-() const {
  480. auto temp(*this);
  481. temp.m_value = -temp.m_value;
  482. return temp;
  483. }
  484. std::string Approx::toString() const {
  485. ReusableStringStream rss;
  486. rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
  487. return rss.str();
  488. }
  489. bool Approx::equalityComparisonImpl(const double other) const {
  490. // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
  491. // Thanks to Richard Harris for his help refining the scaled margin value
  492. return marginComparison(m_value, other, m_margin)
  493. || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
  494. }
  495. void Approx::setMargin(double newMargin) {
  496. CATCH_ENFORCE(newMargin >= 0,
  497. "Invalid Approx::margin: " << newMargin << '.'
  498. << " Approx::Margin has to be non-negative.");
  499. m_margin = newMargin;
  500. }
  501. void Approx::setEpsilon(double newEpsilon) {
  502. CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
  503. "Invalid Approx::epsilon: " << newEpsilon << '.'
  504. << " Approx::epsilon has to be in [0, 1]");
  505. m_epsilon = newEpsilon;
  506. }
  507. namespace literals {
  508. Approx operator ""_a(long double val) {
  509. return Approx(val);
  510. }
  511. Approx operator ""_a(unsigned long long val) {
  512. return Approx(val);
  513. }
  514. } // end namespace literals
  515. std::string StringMaker<Catch::Approx>::convert(Catch::Approx const& value) {
  516. return value.toString();
  517. }
  518. } // end namespace Catch
  519. namespace Catch {
  520. AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const& _lazyExpression):
  521. lazyExpression(_lazyExpression),
  522. resultType(_resultType) {}
  523. std::string AssertionResultData::reconstructExpression() const {
  524. if( reconstructedExpression.empty() ) {
  525. if( lazyExpression ) {
  526. ReusableStringStream rss;
  527. rss << lazyExpression;
  528. reconstructedExpression = rss.str();
  529. }
  530. }
  531. return reconstructedExpression;
  532. }
  533. AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData&& data )
  534. : m_info( info ),
  535. m_resultData( CATCH_MOVE(data) )
  536. {}
  537. // Result was a success
  538. bool AssertionResult::succeeded() const {
  539. return Catch::isOk( m_resultData.resultType );
  540. }
  541. // Result was a success, or failure is suppressed
  542. bool AssertionResult::isOk() const {
  543. return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
  544. }
  545. ResultWas::OfType AssertionResult::getResultType() const {
  546. return m_resultData.resultType;
  547. }
  548. bool AssertionResult::hasExpression() const {
  549. return !m_info.capturedExpression.empty();
  550. }
  551. bool AssertionResult::hasMessage() const {
  552. return !m_resultData.message.empty();
  553. }
  554. std::string AssertionResult::getExpression() const {
  555. // Possibly overallocating by 3 characters should be basically free
  556. std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
  557. if (isFalseTest(m_info.resultDisposition)) {
  558. expr += "!(";
  559. }
  560. expr += m_info.capturedExpression;
  561. if (isFalseTest(m_info.resultDisposition)) {
  562. expr += ')';
  563. }
  564. return expr;
  565. }
  566. std::string AssertionResult::getExpressionInMacro() const {
  567. if ( m_info.macroName.empty() ) {
  568. return static_cast<std::string>( m_info.capturedExpression );
  569. }
  570. std::string expr;
  571. expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
  572. expr += m_info.macroName;
  573. expr += "( ";
  574. expr += m_info.capturedExpression;
  575. expr += " )";
  576. return expr;
  577. }
  578. bool AssertionResult::hasExpandedExpression() const {
  579. return hasExpression() && getExpandedExpression() != getExpression();
  580. }
  581. std::string AssertionResult::getExpandedExpression() const {
  582. std::string expr = m_resultData.reconstructExpression();
  583. return expr.empty()
  584. ? getExpression()
  585. : expr;
  586. }
  587. StringRef AssertionResult::getMessage() const {
  588. return m_resultData.message;
  589. }
  590. SourceLineInfo AssertionResult::getSourceInfo() const {
  591. return m_info.lineInfo;
  592. }
  593. StringRef AssertionResult::getTestMacroName() const {
  594. return m_info.macroName;
  595. }
  596. } // end namespace Catch
  597. #include <fstream>
  598. namespace Catch {
  599. namespace {
  600. static bool enableBazelEnvSupport() {
  601. #if defined( CATCH_CONFIG_BAZEL_SUPPORT )
  602. return true;
  603. #else
  604. return Detail::getEnv( "BAZEL_TEST" ) != nullptr;
  605. #endif
  606. }
  607. struct bazelShardingOptions {
  608. unsigned int shardIndex, shardCount;
  609. std::string shardFilePath;
  610. };
  611. static Optional<bazelShardingOptions> readBazelShardingOptions() {
  612. const auto bazelShardIndex = Detail::getEnv( "TEST_SHARD_INDEX" );
  613. const auto bazelShardTotal = Detail::getEnv( "TEST_TOTAL_SHARDS" );
  614. const auto bazelShardInfoFile = Detail::getEnv( "TEST_SHARD_STATUS_FILE" );
  615. const bool has_all =
  616. bazelShardIndex && bazelShardTotal && bazelShardInfoFile;
  617. if ( !has_all ) {
  618. // We provide nice warning message if the input is
  619. // misconfigured.
  620. auto warn = []( const char* env_var ) {
  621. Catch::cerr()
  622. << "Warning: Bazel shard configuration is missing '"
  623. << env_var << "'. Shard configuration is skipped.\n";
  624. };
  625. if ( !bazelShardIndex ) {
  626. warn( "TEST_SHARD_INDEX" );
  627. }
  628. if ( !bazelShardTotal ) {
  629. warn( "TEST_TOTAL_SHARDS" );
  630. }
  631. if ( !bazelShardInfoFile ) {
  632. warn( "TEST_SHARD_STATUS_FILE" );
  633. }
  634. return {};
  635. }
  636. auto shardIndex = parseUInt( bazelShardIndex );
  637. if ( !shardIndex ) {
  638. Catch::cerr()
  639. << "Warning: could not parse 'TEST_SHARD_INDEX' ('" << bazelShardIndex
  640. << "') as unsigned int.\n";
  641. return {};
  642. }
  643. auto shardTotal = parseUInt( bazelShardTotal );
  644. if ( !shardTotal ) {
  645. Catch::cerr()
  646. << "Warning: could not parse 'TEST_TOTAL_SHARD' ('"
  647. << bazelShardTotal << "') as unsigned int.\n";
  648. return {};
  649. }
  650. return bazelShardingOptions{
  651. *shardIndex, *shardTotal, bazelShardInfoFile };
  652. }
  653. } // end namespace
  654. bool operator==( ProcessedReporterSpec const& lhs,
  655. ProcessedReporterSpec const& rhs ) {
  656. return lhs.name == rhs.name &&
  657. lhs.outputFilename == rhs.outputFilename &&
  658. lhs.colourMode == rhs.colourMode &&
  659. lhs.customOptions == rhs.customOptions;
  660. }
  661. Config::Config( ConfigData const& data ):
  662. m_data( data ) {
  663. // We need to trim filter specs to avoid trouble with superfluous
  664. // whitespace (esp. important for bdd macros, as those are manually
  665. // aligned with whitespace).
  666. for (auto& elem : m_data.testsOrTags) {
  667. elem = trim(elem);
  668. }
  669. for (auto& elem : m_data.sectionsToRun) {
  670. elem = trim(elem);
  671. }
  672. // Insert the default reporter if user hasn't asked for a specific one
  673. if ( m_data.reporterSpecifications.empty() ) {
  674. #if defined( CATCH_CONFIG_DEFAULT_REPORTER )
  675. const auto default_spec = CATCH_CONFIG_DEFAULT_REPORTER;
  676. #else
  677. const auto default_spec = "console";
  678. #endif
  679. auto parsed = parseReporterSpec(default_spec);
  680. CATCH_ENFORCE( parsed,
  681. "Cannot parse the provided default reporter spec: '"
  682. << default_spec << '\'' );
  683. m_data.reporterSpecifications.push_back( std::move( *parsed ) );
  684. }
  685. if ( enableBazelEnvSupport() ) {
  686. readBazelEnvVars();
  687. }
  688. // Bazel support can modify the test specs, so parsing has to happen
  689. // after reading Bazel env vars.
  690. TestSpecParser parser( ITagAliasRegistry::get() );
  691. if ( !m_data.testsOrTags.empty() ) {
  692. m_hasTestFilters = true;
  693. for ( auto const& testOrTags : m_data.testsOrTags ) {
  694. parser.parse( testOrTags );
  695. }
  696. }
  697. m_testSpec = parser.testSpec();
  698. // We now fixup the reporter specs to handle default output spec,
  699. // default colour spec, etc
  700. bool defaultOutputUsed = false;
  701. for ( auto const& reporterSpec : m_data.reporterSpecifications ) {
  702. // We do the default-output check separately, while always
  703. // using the default output below to make the code simpler
  704. // and avoid superfluous copies.
  705. if ( reporterSpec.outputFile().none() ) {
  706. CATCH_ENFORCE( !defaultOutputUsed,
  707. "Internal error: cannot use default output for "
  708. "multiple reporters" );
  709. defaultOutputUsed = true;
  710. }
  711. m_processedReporterSpecs.push_back( ProcessedReporterSpec{
  712. reporterSpec.name(),
  713. reporterSpec.outputFile() ? *reporterSpec.outputFile()
  714. : data.defaultOutputFilename,
  715. reporterSpec.colourMode().valueOr( data.defaultColourMode ),
  716. reporterSpec.customOptions() } );
  717. }
  718. }
  719. Config::~Config() = default;
  720. bool Config::listTests() const { return m_data.listTests; }
  721. bool Config::listTags() const { return m_data.listTags; }
  722. bool Config::listReporters() const { return m_data.listReporters; }
  723. bool Config::listListeners() const { return m_data.listListeners; }
  724. std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
  725. std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
  726. std::vector<ReporterSpec> const& Config::getReporterSpecs() const {
  727. return m_data.reporterSpecifications;
  728. }
  729. std::vector<ProcessedReporterSpec> const&
  730. Config::getProcessedReporterSpecs() const {
  731. return m_processedReporterSpecs;
  732. }
  733. TestSpec const& Config::testSpec() const { return m_testSpec; }
  734. bool Config::hasTestFilters() const { return m_hasTestFilters; }
  735. bool Config::showHelp() const { return m_data.showHelp; }
  736. // IConfig interface
  737. bool Config::allowThrows() const { return !m_data.noThrow; }
  738. StringRef Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
  739. bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
  740. bool Config::warnAboutMissingAssertions() const {
  741. return !!( m_data.warnings & WarnAbout::NoAssertions );
  742. }
  743. bool Config::warnAboutUnmatchedTestSpecs() const {
  744. return !!( m_data.warnings & WarnAbout::UnmatchedTestSpec );
  745. }
  746. bool Config::zeroTestsCountAsSuccess() const { return m_data.allowZeroTests; }
  747. ShowDurations Config::showDurations() const { return m_data.showDurations; }
  748. double Config::minDuration() const { return m_data.minDuration; }
  749. TestRunOrder Config::runOrder() const { return m_data.runOrder; }
  750. uint32_t Config::rngSeed() const { return m_data.rngSeed; }
  751. unsigned int Config::shardCount() const { return m_data.shardCount; }
  752. unsigned int Config::shardIndex() const { return m_data.shardIndex; }
  753. ColourMode Config::defaultColourMode() const { return m_data.defaultColourMode; }
  754. bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
  755. int Config::abortAfter() const { return m_data.abortAfter; }
  756. bool Config::showInvisibles() const { return m_data.showInvisibles; }
  757. Verbosity Config::verbosity() const { return m_data.verbosity; }
  758. bool Config::skipBenchmarks() const { return m_data.skipBenchmarks; }
  759. bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; }
  760. unsigned int Config::benchmarkSamples() const { return m_data.benchmarkSamples; }
  761. double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; }
  762. unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; }
  763. std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
  764. void Config::readBazelEnvVars() {
  765. // Register a JUnit reporter for Bazel. Bazel sets an environment
  766. // variable with the path to XML output. If this file is written to
  767. // during test, Bazel will not generate a default XML output.
  768. // This allows the XML output file to contain higher level of detail
  769. // than what is possible otherwise.
  770. const auto bazelOutputFile = Detail::getEnv( "XML_OUTPUT_FILE" );
  771. if ( bazelOutputFile ) {
  772. m_data.reporterSpecifications.push_back(
  773. { "junit", std::string( bazelOutputFile ), {}, {} } );
  774. }
  775. const auto bazelTestSpec = Detail::getEnv( "TESTBRIDGE_TEST_ONLY" );
  776. if ( bazelTestSpec ) {
  777. // Presumably the test spec from environment should overwrite
  778. // the one we got from CLI (if we got any)
  779. m_data.testsOrTags.clear();
  780. m_data.testsOrTags.push_back( bazelTestSpec );
  781. }
  782. const auto bazelShardOptions = readBazelShardingOptions();
  783. if ( bazelShardOptions ) {
  784. std::ofstream f( bazelShardOptions->shardFilePath,
  785. std::ios_base::out | std::ios_base::trunc );
  786. if ( f.is_open() ) {
  787. f << "";
  788. m_data.shardIndex = bazelShardOptions->shardIndex;
  789. m_data.shardCount = bazelShardOptions->shardCount;
  790. }
  791. }
  792. }
  793. } // end namespace Catch
  794. namespace Catch {
  795. std::uint32_t getSeed() {
  796. return getCurrentContext().getConfig()->rngSeed();
  797. }
  798. }
  799. #include <cassert>
  800. #include <stack>
  801. namespace Catch {
  802. ////////////////////////////////////////////////////////////////////////////
  803. ScopedMessage::ScopedMessage( MessageBuilder&& builder ):
  804. m_info( CATCH_MOVE(builder.m_info) ) {
  805. m_info.message = builder.m_stream.str();
  806. getResultCapture().pushScopedMessage( m_info );
  807. }
  808. ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
  809. m_info( CATCH_MOVE( old.m_info ) ) {
  810. old.m_moved = true;
  811. }
  812. ScopedMessage::~ScopedMessage() {
  813. if ( !uncaught_exceptions() && !m_moved ){
  814. getResultCapture().popScopedMessage(m_info);
  815. }
  816. }
  817. Capturer::Capturer( StringRef macroName,
  818. SourceLineInfo const& lineInfo,
  819. ResultWas::OfType resultType,
  820. StringRef names ):
  821. m_resultCapture( getResultCapture() ) {
  822. auto trimmed = [&] (size_t start, size_t end) {
  823. while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
  824. ++start;
  825. }
  826. while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {
  827. --end;
  828. }
  829. return names.substr(start, end - start + 1);
  830. };
  831. auto skipq = [&] (size_t start, char quote) {
  832. for (auto i = start + 1; i < names.size() ; ++i) {
  833. if (names[i] == quote)
  834. return i;
  835. if (names[i] == '\\')
  836. ++i;
  837. }
  838. CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");
  839. };
  840. size_t start = 0;
  841. std::stack<char> openings;
  842. for (size_t pos = 0; pos < names.size(); ++pos) {
  843. char c = names[pos];
  844. switch (c) {
  845. case '[':
  846. case '{':
  847. case '(':
  848. // It is basically impossible to disambiguate between
  849. // comparison and start of template args in this context
  850. // case '<':
  851. openings.push(c);
  852. break;
  853. case ']':
  854. case '}':
  855. case ')':
  856. // case '>':
  857. openings.pop();
  858. break;
  859. case '"':
  860. case '\'':
  861. pos = skipq(pos, c);
  862. break;
  863. case ',':
  864. if (start != pos && openings.empty()) {
  865. m_messages.emplace_back(macroName, lineInfo, resultType);
  866. m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
  867. m_messages.back().message += " := ";
  868. start = pos;
  869. }
  870. break;
  871. default:; // noop
  872. }
  873. }
  874. assert(openings.empty() && "Mismatched openings");
  875. m_messages.emplace_back(macroName, lineInfo, resultType);
  876. m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
  877. m_messages.back().message += " := ";
  878. }
  879. Capturer::~Capturer() {
  880. if ( !uncaught_exceptions() ){
  881. assert( m_captured == m_messages.size() );
  882. for( size_t i = 0; i < m_captured; ++i )
  883. m_resultCapture.popScopedMessage( m_messages[i] );
  884. }
  885. }
  886. void Capturer::captureValue( size_t index, std::string const& value ) {
  887. assert( index < m_messages.size() );
  888. m_messages[index].message += value;
  889. m_resultCapture.pushScopedMessage( m_messages[index] );
  890. m_captured++;
  891. }
  892. } // end namespace Catch
  893. #include <exception>
  894. namespace Catch {
  895. namespace {
  896. class RegistryHub : public IRegistryHub,
  897. public IMutableRegistryHub,
  898. private Detail::NonCopyable {
  899. public: // IRegistryHub
  900. RegistryHub() = default;
  901. ReporterRegistry const& getReporterRegistry() const override {
  902. return m_reporterRegistry;
  903. }
  904. ITestCaseRegistry const& getTestCaseRegistry() const override {
  905. return m_testCaseRegistry;
  906. }
  907. IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
  908. return m_exceptionTranslatorRegistry;
  909. }
  910. ITagAliasRegistry const& getTagAliasRegistry() const override {
  911. return m_tagAliasRegistry;
  912. }
  913. StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
  914. return m_exceptionRegistry;
  915. }
  916. public: // IMutableRegistryHub
  917. void registerReporter( std::string const& name, IReporterFactoryPtr factory ) override {
  918. m_reporterRegistry.registerReporter( name, CATCH_MOVE(factory) );
  919. }
  920. void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) override {
  921. m_reporterRegistry.registerListener( CATCH_MOVE(factory) );
  922. }
  923. void registerTest( Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker ) override {
  924. m_testCaseRegistry.registerTest( CATCH_MOVE(testInfo), CATCH_MOVE(invoker) );
  925. }
  926. void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) override {
  927. m_exceptionTranslatorRegistry.registerTranslator( CATCH_MOVE(translator) );
  928. }
  929. void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
  930. m_tagAliasRegistry.add( alias, tag, lineInfo );
  931. }
  932. void registerStartupException() noexcept override {
  933. #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  934. m_exceptionRegistry.add(std::current_exception());
  935. #else
  936. CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
  937. #endif
  938. }
  939. IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
  940. return m_enumValuesRegistry;
  941. }
  942. private:
  943. TestRegistry m_testCaseRegistry;
  944. ReporterRegistry m_reporterRegistry;
  945. ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
  946. TagAliasRegistry m_tagAliasRegistry;
  947. StartupExceptionRegistry m_exceptionRegistry;
  948. Detail::EnumValuesRegistry m_enumValuesRegistry;
  949. };
  950. }
  951. using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
  952. IRegistryHub const& getRegistryHub() {
  953. return RegistryHubSingleton::get();
  954. }
  955. IMutableRegistryHub& getMutableRegistryHub() {
  956. return RegistryHubSingleton::getMutable();
  957. }
  958. void cleanUp() {
  959. cleanupSingletons();
  960. cleanUpContext();
  961. }
  962. std::string translateActiveException() {
  963. return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
  964. }
  965. } // end namespace Catch
  966. #include <algorithm>
  967. #include <cassert>
  968. #include <exception>
  969. #include <iomanip>
  970. #include <set>
  971. namespace Catch {
  972. namespace {
  973. static constexpr int TestFailureExitCode = 42;
  974. static constexpr int UnspecifiedErrorExitCode = 1;
  975. static constexpr int AllTestsSkippedExitCode = 4;
  976. static constexpr int NoTestsRunExitCode = 2;
  977. static constexpr int UnmatchedTestSpecExitCode = 3;
  978. static constexpr int InvalidTestSpecExitCode = 5;
  979. IEventListenerPtr createReporter(std::string const& reporterName, ReporterConfig&& config) {
  980. auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config));
  981. CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << '\'');
  982. return reporter;
  983. }
  984. IEventListenerPtr prepareReporters(Config const* config) {
  985. if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()
  986. && config->getProcessedReporterSpecs().size() == 1) {
  987. auto const& spec = config->getProcessedReporterSpecs()[0];
  988. return createReporter(
  989. spec.name,
  990. ReporterConfig( config,
  991. makeStream( spec.outputFilename ),
  992. spec.colourMode,
  993. spec.customOptions ) );
  994. }
  995. auto multi = Detail::make_unique<MultiReporter>(config);
  996. auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
  997. for (auto const& listener : listeners) {
  998. multi->addListener(listener->create(config));
  999. }
  1000. for ( auto const& reporterSpec : config->getProcessedReporterSpecs() ) {
  1001. multi->addReporter( createReporter(
  1002. reporterSpec.name,
  1003. ReporterConfig( config,
  1004. makeStream( reporterSpec.outputFilename ),
  1005. reporterSpec.colourMode,
  1006. reporterSpec.customOptions ) ) );
  1007. }
  1008. return multi;
  1009. }
  1010. class TestGroup {
  1011. public:
  1012. explicit TestGroup(IEventListenerPtr&& reporter, Config const* config):
  1013. m_reporter(reporter.get()),
  1014. m_config{config},
  1015. m_context{config, CATCH_MOVE(reporter)} {
  1016. assert( m_config->testSpec().getInvalidSpecs().empty() &&
  1017. "Invalid test specs should be handled before running tests" );
  1018. auto const& allTestCases = getAllTestCasesSorted(*m_config);
  1019. auto const& testSpec = m_config->testSpec();
  1020. if ( !testSpec.hasFilters() ) {
  1021. for ( auto const& test : allTestCases ) {
  1022. if ( !test.getTestCaseInfo().isHidden() ) {
  1023. m_tests.emplace( &test );
  1024. }
  1025. }
  1026. } else {
  1027. m_matches =
  1028. testSpec.matchesByFilter( allTestCases, *m_config );
  1029. for ( auto const& match : m_matches ) {
  1030. m_tests.insert( match.tests.begin(),
  1031. match.tests.end() );
  1032. }
  1033. }
  1034. m_tests = createShard(m_tests, m_config->shardCount(), m_config->shardIndex());
  1035. }
  1036. Totals execute() {
  1037. Totals totals;
  1038. for (auto const& testCase : m_tests) {
  1039. if (!m_context.aborting())
  1040. totals += m_context.runTest(*testCase);
  1041. else
  1042. m_reporter->skipTest(testCase->getTestCaseInfo());
  1043. }
  1044. for (auto const& match : m_matches) {
  1045. if (match.tests.empty()) {
  1046. m_unmatchedTestSpecs = true;
  1047. m_reporter->noMatchingTestCases( match.name );
  1048. }
  1049. }
  1050. return totals;
  1051. }
  1052. bool hadUnmatchedTestSpecs() const {
  1053. return m_unmatchedTestSpecs;
  1054. }
  1055. private:
  1056. IEventListener* m_reporter;
  1057. Config const* m_config;
  1058. RunContext m_context;
  1059. std::set<TestCaseHandle const*> m_tests;
  1060. TestSpec::Matches m_matches;
  1061. bool m_unmatchedTestSpecs = false;
  1062. };
  1063. void applyFilenamesAsTags() {
  1064. for (auto const& testInfo : getRegistryHub().getTestCaseRegistry().getAllInfos()) {
  1065. testInfo->addFilenameTag();
  1066. }
  1067. }
  1068. } // anon namespace
  1069. Session::Session() {
  1070. static bool alreadyInstantiated = false;
  1071. if( alreadyInstantiated ) {
  1072. CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
  1073. CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
  1074. }
  1075. // There cannot be exceptions at startup in no-exception mode.
  1076. #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  1077. const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
  1078. if ( !exceptions.empty() ) {
  1079. config();
  1080. getCurrentMutableContext().setConfig(m_config.get());
  1081. m_startupExceptions = true;
  1082. auto errStream = makeStream( "%stderr" );
  1083. auto colourImpl = makeColourImpl(
  1084. ColourMode::PlatformDefault, errStream.get() );
  1085. auto guard = colourImpl->guardColour( Colour::Red );
  1086. errStream->stream() << "Errors occurred during startup!" << '\n';
  1087. // iterate over all exceptions and notify user
  1088. for ( const auto& ex_ptr : exceptions ) {
  1089. try {
  1090. std::rethrow_exception(ex_ptr);
  1091. } catch ( std::exception const& ex ) {
  1092. errStream->stream() << TextFlow::Column( ex.what() ).indent(2) << '\n';
  1093. }
  1094. }
  1095. }
  1096. #endif
  1097. alreadyInstantiated = true;
  1098. m_cli = makeCommandLineParser( m_configData );
  1099. }
  1100. Session::~Session() {
  1101. Catch::cleanUp();
  1102. }
  1103. void Session::showHelp() const {
  1104. Catch::cout()
  1105. << "\nCatch2 v" << libraryVersion() << '\n'
  1106. << m_cli << '\n'
  1107. << "For more detailed usage please see the project docs\n\n" << std::flush;
  1108. }
  1109. void Session::libIdentify() {
  1110. Catch::cout()
  1111. << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
  1112. << std::left << std::setw(16) << "category: " << "testframework\n"
  1113. << std::left << std::setw(16) << "framework: " << "Catch2\n"
  1114. << std::left << std::setw(16) << "version: " << libraryVersion() << '\n' << std::flush;
  1115. }
  1116. int Session::applyCommandLine( int argc, char const * const * argv ) {
  1117. if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; }
  1118. auto result = m_cli.parse( Clara::Args( argc, argv ) );
  1119. if( !result ) {
  1120. config();
  1121. getCurrentMutableContext().setConfig(m_config.get());
  1122. auto errStream = makeStream( "%stderr" );
  1123. auto colour = makeColourImpl( ColourMode::PlatformDefault, errStream.get() );
  1124. errStream->stream()
  1125. << colour->guardColour( Colour::Red )
  1126. << "\nError(s) in input:\n"
  1127. << TextFlow::Column( result.errorMessage() ).indent( 2 )
  1128. << "\n\n";
  1129. errStream->stream() << "Run with -? for usage\n\n" << std::flush;
  1130. return UnspecifiedErrorExitCode;
  1131. }
  1132. if( m_configData.showHelp )
  1133. showHelp();
  1134. if( m_configData.libIdentify )
  1135. libIdentify();
  1136. m_config.reset();
  1137. return 0;
  1138. }
  1139. #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
  1140. int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
  1141. char **utf8Argv = new char *[ argc ];
  1142. for ( int i = 0; i < argc; ++i ) {
  1143. int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
  1144. utf8Argv[ i ] = new char[ bufSize ];
  1145. WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
  1146. }
  1147. int returnCode = applyCommandLine( argc, utf8Argv );
  1148. for ( int i = 0; i < argc; ++i )
  1149. delete [] utf8Argv[ i ];
  1150. delete [] utf8Argv;
  1151. return returnCode;
  1152. }
  1153. #endif
  1154. void Session::useConfigData( ConfigData const& configData ) {
  1155. m_configData = configData;
  1156. m_config.reset();
  1157. }
  1158. int Session::run() {
  1159. if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
  1160. Catch::cout() << "...waiting for enter/ return before starting\n" << std::flush;
  1161. static_cast<void>(std::getchar());
  1162. }
  1163. int exitCode = runInternal();
  1164. if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
  1165. Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << '\n' << std::flush;
  1166. static_cast<void>(std::getchar());
  1167. }
  1168. return exitCode;
  1169. }
  1170. Clara::Parser const& Session::cli() const {
  1171. return m_cli;
  1172. }
  1173. void Session::cli( Clara::Parser const& newParser ) {
  1174. m_cli = newParser;
  1175. }
  1176. ConfigData& Session::configData() {
  1177. return m_configData;
  1178. }
  1179. Config& Session::config() {
  1180. if( !m_config )
  1181. m_config = Detail::make_unique<Config>( m_configData );
  1182. return *m_config;
  1183. }
  1184. int Session::runInternal() {
  1185. if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; }
  1186. if (m_configData.showHelp || m_configData.libIdentify) {
  1187. return 0;
  1188. }
  1189. if ( m_configData.shardIndex >= m_configData.shardCount ) {
  1190. Catch::cerr() << "The shard count (" << m_configData.shardCount
  1191. << ") must be greater than the shard index ("
  1192. << m_configData.shardIndex << ")\n"
  1193. << std::flush;
  1194. return UnspecifiedErrorExitCode;
  1195. }
  1196. CATCH_TRY {
  1197. config(); // Force config to be constructed
  1198. seedRng( *m_config );
  1199. if (m_configData.filenamesAsTags) {
  1200. applyFilenamesAsTags();
  1201. }
  1202. // Set up global config instance before we start calling into other functions
  1203. getCurrentMutableContext().setConfig(m_config.get());
  1204. // Create reporter(s) so we can route listings through them
  1205. auto reporter = prepareReporters(m_config.get());
  1206. auto const& invalidSpecs = m_config->testSpec().getInvalidSpecs();
  1207. if ( !invalidSpecs.empty() ) {
  1208. for ( auto const& spec : invalidSpecs ) {
  1209. reporter->reportInvalidTestSpec( spec );
  1210. }
  1211. return InvalidTestSpecExitCode;
  1212. }
  1213. // Handle list request
  1214. if (list(*reporter, *m_config)) {
  1215. return 0;
  1216. }
  1217. TestGroup tests { CATCH_MOVE(reporter), m_config.get() };
  1218. auto const totals = tests.execute();
  1219. if ( tests.hadUnmatchedTestSpecs()
  1220. && m_config->warnAboutUnmatchedTestSpecs() ) {
  1221. // UnmatchedTestSpecExitCode
  1222. return UnmatchedTestSpecExitCode;
  1223. }
  1224. if ( totals.testCases.total() == 0
  1225. && !m_config->zeroTestsCountAsSuccess() ) {
  1226. return NoTestsRunExitCode;
  1227. }
  1228. if ( totals.testCases.total() > 0 &&
  1229. totals.testCases.total() == totals.testCases.skipped
  1230. && !m_config->zeroTestsCountAsSuccess() ) {
  1231. return AllTestsSkippedExitCode;
  1232. }
  1233. if ( totals.assertions.failed ) { return TestFailureExitCode; }
  1234. return 0;
  1235. }
  1236. #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  1237. catch( std::exception& ex ) {
  1238. Catch::cerr() << ex.what() << '\n' << std::flush;
  1239. return UnspecifiedErrorExitCode;
  1240. }
  1241. #endif
  1242. }
  1243. } // end namespace Catch
  1244. namespace Catch {
  1245. RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
  1246. CATCH_TRY {
  1247. getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
  1248. } CATCH_CATCH_ALL {
  1249. // Do not throw when constructing global objects, instead register the exception to be processed later
  1250. getMutableRegistryHub().registerStartupException();
  1251. }
  1252. }
  1253. }
  1254. #include <cassert>
  1255. #include <cctype>
  1256. #include <algorithm>
  1257. namespace Catch {
  1258. namespace {
  1259. using TCP_underlying_type = uint8_t;
  1260. static_assert(sizeof(TestCaseProperties) == sizeof(TCP_underlying_type),
  1261. "The size of the TestCaseProperties is different from the assumed size");
  1262. constexpr TestCaseProperties operator|(TestCaseProperties lhs, TestCaseProperties rhs) {
  1263. return static_cast<TestCaseProperties>(
  1264. static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
  1265. );
  1266. }
  1267. constexpr TestCaseProperties& operator|=(TestCaseProperties& lhs, TestCaseProperties rhs) {
  1268. lhs = static_cast<TestCaseProperties>(
  1269. static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
  1270. );
  1271. return lhs;
  1272. }
  1273. constexpr TestCaseProperties operator&(TestCaseProperties lhs, TestCaseProperties rhs) {
  1274. return static_cast<TestCaseProperties>(
  1275. static_cast<TCP_underlying_type>(lhs) & static_cast<TCP_underlying_type>(rhs)
  1276. );
  1277. }
  1278. constexpr bool applies(TestCaseProperties tcp) {
  1279. static_assert(static_cast<TCP_underlying_type>(TestCaseProperties::None) == 0,
  1280. "TestCaseProperties::None must be equal to 0");
  1281. return tcp != TestCaseProperties::None;
  1282. }
  1283. TestCaseProperties parseSpecialTag( StringRef tag ) {
  1284. if( !tag.empty() && tag[0] == '.' )
  1285. return TestCaseProperties::IsHidden;
  1286. else if( tag == "!throws"_sr )
  1287. return TestCaseProperties::Throws;
  1288. else if( tag == "!shouldfail"_sr )
  1289. return TestCaseProperties::ShouldFail;
  1290. else if( tag == "!mayfail"_sr )
  1291. return TestCaseProperties::MayFail;
  1292. else if( tag == "!nonportable"_sr )
  1293. return TestCaseProperties::NonPortable;
  1294. else if( tag == "!benchmark"_sr )
  1295. return TestCaseProperties::Benchmark | TestCaseProperties::IsHidden;
  1296. else
  1297. return TestCaseProperties::None;
  1298. }
  1299. bool isReservedTag( StringRef tag ) {
  1300. return parseSpecialTag( tag ) == TestCaseProperties::None
  1301. && tag.size() > 0
  1302. && !std::isalnum( static_cast<unsigned char>(tag[0]) );
  1303. }
  1304. void enforceNotReservedTag( StringRef tag, SourceLineInfo const& _lineInfo ) {
  1305. CATCH_ENFORCE( !isReservedTag(tag),
  1306. "Tag name: [" << tag << "] is not allowed.\n"
  1307. << "Tag names starting with non alphanumeric characters are reserved\n"
  1308. << _lineInfo );
  1309. }
  1310. std::string makeDefaultName() {
  1311. static size_t counter = 0;
  1312. return "Anonymous test case " + std::to_string(++counter);
  1313. }
  1314. constexpr StringRef extractFilenamePart(StringRef filename) {
  1315. size_t lastDot = filename.size();
  1316. while (lastDot > 0 && filename[lastDot - 1] != '.') {
  1317. --lastDot;
  1318. }
  1319. // In theory we could have filename without any extension in it
  1320. if ( lastDot == 0 ) { return StringRef(); }
  1321. --lastDot;
  1322. size_t nameStart = lastDot;
  1323. while (nameStart > 0 && filename[nameStart - 1] != '/' && filename[nameStart - 1] != '\\') {
  1324. --nameStart;
  1325. }
  1326. return filename.substr(nameStart, lastDot - nameStart);
  1327. }
  1328. // Returns the upper bound on size of extra tags ([#file]+[.])
  1329. constexpr size_t sizeOfExtraTags(StringRef filepath) {
  1330. // [.] is 3, [#] is another 3
  1331. const size_t extras = 3 + 3;
  1332. return extractFilenamePart(filepath).size() + extras;
  1333. }
  1334. } // end unnamed namespace
  1335. bool operator<( Tag const& lhs, Tag const& rhs ) {
  1336. Detail::CaseInsensitiveLess cmp;
  1337. return cmp( lhs.original, rhs.original );
  1338. }
  1339. bool operator==( Tag const& lhs, Tag const& rhs ) {
  1340. Detail::CaseInsensitiveEqualTo cmp;
  1341. return cmp( lhs.original, rhs.original );
  1342. }
  1343. Detail::unique_ptr<TestCaseInfo>
  1344. makeTestCaseInfo(StringRef _className,
  1345. NameAndTags const& nameAndTags,
  1346. SourceLineInfo const& _lineInfo ) {
  1347. return Detail::make_unique<TestCaseInfo>(_className, nameAndTags, _lineInfo);
  1348. }
  1349. TestCaseInfo::TestCaseInfo(StringRef _className,
  1350. NameAndTags const& _nameAndTags,
  1351. SourceLineInfo const& _lineInfo):
  1352. name( _nameAndTags.name.empty() ? makeDefaultName() : _nameAndTags.name ),
  1353. className( _className ),
  1354. lineInfo( _lineInfo )
  1355. {
  1356. StringRef originalTags = _nameAndTags.tags;
  1357. // We need to reserve enough space to store all of the tags
  1358. // (including optional hidden tag and filename tag)
  1359. auto requiredSize = originalTags.size() + sizeOfExtraTags(_lineInfo.file);
  1360. backingTags.reserve(requiredSize);
  1361. // We cannot copy the tags directly, as we need to normalize
  1362. // some tags, so that [.foo] is copied as [.][foo].
  1363. size_t tagStart = 0;
  1364. size_t tagEnd = 0;
  1365. bool inTag = false;
  1366. for (size_t idx = 0; idx < originalTags.size(); ++idx) {
  1367. auto c = originalTags[idx];
  1368. if (c == '[') {
  1369. CATCH_ENFORCE(
  1370. !inTag,
  1371. "Found '[' inside a tag while registering test case '"
  1372. << _nameAndTags.name << "' at " << _lineInfo );
  1373. inTag = true;
  1374. tagStart = idx;
  1375. }
  1376. if (c == ']') {
  1377. CATCH_ENFORCE(
  1378. inTag,
  1379. "Found unmatched ']' while registering test case '"
  1380. << _nameAndTags.name << "' at " << _lineInfo );
  1381. inTag = false;
  1382. tagEnd = idx;
  1383. assert(tagStart < tagEnd);
  1384. // We need to check the tag for special meanings, copy
  1385. // it over to backing storage and actually reference the
  1386. // backing storage in the saved tags
  1387. StringRef tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1);
  1388. CATCH_ENFORCE( !tagStr.empty(),
  1389. "Found an empty tag while registering test case '"
  1390. << _nameAndTags.name << "' at "
  1391. << _lineInfo );
  1392. enforceNotReservedTag(tagStr, lineInfo);
  1393. properties |= parseSpecialTag(tagStr);
  1394. // When copying a tag to the backing storage, we need to
  1395. // check if it is a merged hide tag, such as [.foo], and
  1396. // if it is, we need to handle it as if it was [foo].
  1397. if (tagStr.size() > 1 && tagStr[0] == '.') {
  1398. tagStr = tagStr.substr(1, tagStr.size() - 1);
  1399. }
  1400. // We skip over dealing with the [.] tag, as we will add
  1401. // it later unconditionally and then sort and unique all
  1402. // the tags.
  1403. internalAppendTag(tagStr);
  1404. }
  1405. }
  1406. CATCH_ENFORCE( !inTag,
  1407. "Found an unclosed tag while registering test case '"
  1408. << _nameAndTags.name << "' at " << _lineInfo );
  1409. // Add [.] if relevant
  1410. if (isHidden()) {
  1411. internalAppendTag("."_sr);
  1412. }
  1413. // Sort and prepare tags
  1414. std::sort(begin(tags), end(tags));
  1415. tags.erase(std::unique(begin(tags), end(tags)),
  1416. end(tags));
  1417. }
  1418. bool TestCaseInfo::isHidden() const {
  1419. return applies( properties & TestCaseProperties::IsHidden );
  1420. }
  1421. bool TestCaseInfo::throws() const {
  1422. return applies( properties & TestCaseProperties::Throws );
  1423. }
  1424. bool TestCaseInfo::okToFail() const {
  1425. return applies( properties & (TestCaseProperties::ShouldFail | TestCaseProperties::MayFail ) );
  1426. }
  1427. bool TestCaseInfo::expectedToFail() const {
  1428. return applies( properties & (TestCaseProperties::ShouldFail) );
  1429. }
  1430. void TestCaseInfo::addFilenameTag() {
  1431. std::string combined("#");
  1432. combined += extractFilenamePart(lineInfo.file);
  1433. internalAppendTag(combined);
  1434. }
  1435. std::string TestCaseInfo::tagsAsString() const {
  1436. std::string ret;
  1437. // '[' and ']' per tag
  1438. std::size_t full_size = 2 * tags.size();
  1439. for (const auto& tag : tags) {
  1440. full_size += tag.original.size();
  1441. }
  1442. ret.reserve(full_size);
  1443. for (const auto& tag : tags) {
  1444. ret.push_back('[');
  1445. ret += tag.original;
  1446. ret.push_back(']');
  1447. }
  1448. return ret;
  1449. }
  1450. void TestCaseInfo::internalAppendTag(StringRef tagStr) {
  1451. backingTags += '[';
  1452. const auto backingStart = backingTags.size();
  1453. backingTags += tagStr;
  1454. const auto backingEnd = backingTags.size();
  1455. backingTags += ']';
  1456. tags.emplace_back(StringRef(backingTags.c_str() + backingStart, backingEnd - backingStart));
  1457. }
  1458. bool operator<( TestCaseInfo const& lhs, TestCaseInfo const& rhs ) {
  1459. // We want to avoid redoing the string comparisons multiple times,
  1460. // so we store the result of a three-way comparison before using
  1461. // it in the actual comparison logic.
  1462. const auto cmpName = lhs.name.compare( rhs.name );
  1463. if ( cmpName != 0 ) {
  1464. return cmpName < 0;
  1465. }
  1466. const auto cmpClassName = lhs.className.compare( rhs.className );
  1467. if ( cmpClassName != 0 ) {
  1468. return cmpClassName < 0;
  1469. }
  1470. return lhs.tags < rhs.tags;
  1471. }
  1472. } // end namespace Catch
  1473. #include <algorithm>
  1474. #include <string>
  1475. #include <vector>
  1476. #include <ostream>
  1477. namespace Catch {
  1478. TestSpec::Pattern::Pattern( std::string const& name )
  1479. : m_name( name )
  1480. {}
  1481. TestSpec::Pattern::~Pattern() = default;
  1482. std::string const& TestSpec::Pattern::name() const {
  1483. return m_name;
  1484. }
  1485. TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
  1486. : Pattern( filterString )
  1487. , m_wildcardPattern( toLower( name ), CaseSensitive::No )
  1488. {}
  1489. bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
  1490. return m_wildcardPattern.matches( testCase.name );
  1491. }
  1492. void TestSpec::NamePattern::serializeTo( std::ostream& out ) const {
  1493. out << '"' << name() << '"';
  1494. }
  1495. TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
  1496. : Pattern( filterString )
  1497. , m_tag( tag )
  1498. {}
  1499. bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
  1500. return std::find( begin( testCase.tags ),
  1501. end( testCase.tags ),
  1502. Tag( m_tag ) ) != end( testCase.tags );
  1503. }
  1504. void TestSpec::TagPattern::serializeTo( std::ostream& out ) const {
  1505. out << name();
  1506. }
  1507. bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
  1508. bool should_use = !testCase.isHidden();
  1509. for (auto const& pattern : m_required) {
  1510. should_use = true;
  1511. if (!pattern->matches(testCase)) {
  1512. return false;
  1513. }
  1514. }
  1515. for (auto const& pattern : m_forbidden) {
  1516. if (pattern->matches(testCase)) {
  1517. return false;
  1518. }
  1519. }
  1520. return should_use;
  1521. }
  1522. void TestSpec::Filter::serializeTo( std::ostream& out ) const {
  1523. bool first = true;
  1524. for ( auto const& pattern : m_required ) {
  1525. if ( !first ) {
  1526. out << ' ';
  1527. }
  1528. out << *pattern;
  1529. first = false;
  1530. }
  1531. for ( auto const& pattern : m_forbidden ) {
  1532. if ( !first ) {
  1533. out << ' ';
  1534. }
  1535. out << *pattern;
  1536. first = false;
  1537. }
  1538. }
  1539. std::string TestSpec::extractFilterName( Filter const& filter ) {
  1540. Catch::ReusableStringStream sstr;
  1541. sstr << filter;
  1542. return sstr.str();
  1543. }
  1544. bool TestSpec::hasFilters() const {
  1545. return !m_filters.empty();
  1546. }
  1547. bool TestSpec::matches( TestCaseInfo const& testCase ) const {
  1548. return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
  1549. }
  1550. TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const {
  1551. Matches matches;
  1552. matches.reserve( m_filters.size() );
  1553. for ( auto const& filter : m_filters ) {
  1554. std::vector<TestCaseHandle const*> currentMatches;
  1555. for ( auto const& test : testCases )
  1556. if ( isThrowSafe( test, config ) &&
  1557. filter.matches( test.getTestCaseInfo() ) )
  1558. currentMatches.emplace_back( &test );
  1559. matches.push_back(
  1560. FilterMatch{ extractFilterName( filter ), currentMatches } );
  1561. }
  1562. return matches;
  1563. }
  1564. const TestSpec::vectorStrings& TestSpec::getInvalidSpecs() const {
  1565. return m_invalidSpecs;
  1566. }
  1567. void TestSpec::serializeTo( std::ostream& out ) const {
  1568. bool first = true;
  1569. for ( auto const& filter : m_filters ) {
  1570. if ( !first ) {
  1571. out << ',';
  1572. }
  1573. out << filter;
  1574. first = false;
  1575. }
  1576. }
  1577. }
  1578. #include <chrono>
  1579. namespace Catch {
  1580. namespace {
  1581. static auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
  1582. return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
  1583. }
  1584. } // end unnamed namespace
  1585. void Timer::start() {
  1586. m_nanoseconds = getCurrentNanosecondsSinceEpoch();
  1587. }
  1588. auto Timer::getElapsedNanoseconds() const -> uint64_t {
  1589. return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
  1590. }
  1591. auto Timer::getElapsedMicroseconds() const -> uint64_t {
  1592. return getElapsedNanoseconds()/1000;
  1593. }
  1594. auto Timer::getElapsedMilliseconds() const -> unsigned int {
  1595. return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
  1596. }
  1597. auto Timer::getElapsedSeconds() const -> double {
  1598. return getElapsedMicroseconds()/1000000.0;
  1599. }
  1600. } // namespace Catch
  1601. #include <cmath>
  1602. #include <iomanip>
  1603. namespace Catch {
  1604. namespace Detail {
  1605. namespace {
  1606. const int hexThreshold = 255;
  1607. struct Endianness {
  1608. enum Arch { Big, Little };
  1609. static Arch which() {
  1610. int one = 1;
  1611. // If the lowest byte we read is non-zero, we can assume
  1612. // that little endian format is used.
  1613. auto value = *reinterpret_cast<char*>(&one);
  1614. return value ? Little : Big;
  1615. }
  1616. };
  1617. template<typename T>
  1618. std::string fpToString(T value, int precision) {
  1619. if (Catch::isnan(value)) {
  1620. return "nan";
  1621. }
  1622. ReusableStringStream rss;
  1623. rss << std::setprecision(precision)
  1624. << std::fixed
  1625. << value;
  1626. std::string d = rss.str();
  1627. std::size_t i = d.find_last_not_of('0');
  1628. if (i != std::string::npos && i != d.size() - 1) {
  1629. if (d[i] == '.')
  1630. i++;
  1631. d = d.substr(0, i + 1);
  1632. }
  1633. return d;
  1634. }
  1635. } // end unnamed namespace
  1636. std::string convertIntoString(StringRef string, bool escapeInvisibles) {
  1637. std::string ret;
  1638. // This is enough for the "don't escape invisibles" case, and a good
  1639. // lower bound on the "escape invisibles" case.
  1640. ret.reserve(string.size() + 2);
  1641. if (!escapeInvisibles) {
  1642. ret += '"';
  1643. ret += string;
  1644. ret += '"';
  1645. return ret;
  1646. }
  1647. ret += '"';
  1648. for (char c : string) {
  1649. switch (c) {
  1650. case '\r':
  1651. ret.append("\\r");
  1652. break;
  1653. case '\n':
  1654. ret.append("\\n");
  1655. break;
  1656. case '\t':
  1657. ret.append("\\t");
  1658. break;
  1659. case '\f':
  1660. ret.append("\\f");
  1661. break;
  1662. default:
  1663. ret.push_back(c);
  1664. break;
  1665. }
  1666. }
  1667. ret += '"';
  1668. return ret;
  1669. }
  1670. std::string convertIntoString(StringRef string) {
  1671. return convertIntoString(string, getCurrentContext().getConfig()->showInvisibles());
  1672. }
  1673. std::string rawMemoryToString( const void *object, std::size_t size ) {
  1674. // Reverse order for little endian architectures
  1675. int i = 0, end = static_cast<int>( size ), inc = 1;
  1676. if( Endianness::which() == Endianness::Little ) {
  1677. i = end-1;
  1678. end = inc = -1;
  1679. }
  1680. unsigned char const *bytes = static_cast<unsigned char const *>(object);
  1681. ReusableStringStream rss;
  1682. rss << "0x" << std::setfill('0') << std::hex;
  1683. for( ; i != end; i += inc )
  1684. rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
  1685. return rss.str();
  1686. }
  1687. } // end Detail namespace
  1688. //// ======================================================= ////
  1689. //
  1690. // Out-of-line defs for full specialization of StringMaker
  1691. //
  1692. //// ======================================================= ////
  1693. std::string StringMaker<std::string>::convert(const std::string& str) {
  1694. return Detail::convertIntoString( str );
  1695. }
  1696. #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
  1697. std::string StringMaker<std::string_view>::convert(std::string_view str) {
  1698. return Detail::convertIntoString( StringRef( str.data(), str.size() ) );
  1699. }
  1700. #endif
  1701. std::string StringMaker<char const*>::convert(char const* str) {
  1702. if (str) {
  1703. return Detail::convertIntoString( str );
  1704. } else {
  1705. return{ "{null string}" };
  1706. }
  1707. }
  1708. std::string StringMaker<char*>::convert(char* str) { // NOLINT(readability-non-const-parameter)
  1709. if (str) {
  1710. return Detail::convertIntoString( str );
  1711. } else {
  1712. return{ "{null string}" };
  1713. }
  1714. }
  1715. #ifdef CATCH_CONFIG_WCHAR
  1716. std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
  1717. std::string s;
  1718. s.reserve(wstr.size());
  1719. for (auto c : wstr) {
  1720. s += (c <= 0xff) ? static_cast<char>(c) : '?';
  1721. }
  1722. return ::Catch::Detail::stringify(s);
  1723. }
  1724. # ifdef CATCH_CONFIG_CPP17_STRING_VIEW
  1725. std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
  1726. return StringMaker<std::wstring>::convert(std::wstring(str));
  1727. }
  1728. # endif
  1729. std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
  1730. if (str) {
  1731. return ::Catch::Detail::stringify(std::wstring{ str });
  1732. } else {
  1733. return{ "{null string}" };
  1734. }
  1735. }
  1736. std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
  1737. if (str) {
  1738. return ::Catch::Detail::stringify(std::wstring{ str });
  1739. } else {
  1740. return{ "{null string}" };
  1741. }
  1742. }
  1743. #endif
  1744. #if defined(CATCH_CONFIG_CPP17_BYTE)
  1745. #include <cstddef>
  1746. std::string StringMaker<std::byte>::convert(std::byte value) {
  1747. return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
  1748. }
  1749. #endif // defined(CATCH_CONFIG_CPP17_BYTE)
  1750. std::string StringMaker<int>::convert(int value) {
  1751. return ::Catch::Detail::stringify(static_cast<long long>(value));
  1752. }
  1753. std::string StringMaker<long>::convert(long value) {
  1754. return ::Catch::Detail::stringify(static_cast<long long>(value));
  1755. }
  1756. std::string StringMaker<long long>::convert(long long value) {
  1757. ReusableStringStream rss;
  1758. rss << value;
  1759. if (value > Detail::hexThreshold) {
  1760. rss << " (0x" << std::hex << value << ')';
  1761. }
  1762. return rss.str();
  1763. }
  1764. std::string StringMaker<unsigned int>::convert(unsigned int value) {
  1765. return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
  1766. }
  1767. std::string StringMaker<unsigned long>::convert(unsigned long value) {
  1768. return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
  1769. }
  1770. std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
  1771. ReusableStringStream rss;
  1772. rss << value;
  1773. if (value > Detail::hexThreshold) {
  1774. rss << " (0x" << std::hex << value << ')';
  1775. }
  1776. return rss.str();
  1777. }
  1778. std::string StringMaker<signed char>::convert(signed char value) {
  1779. if (value == '\r') {
  1780. return "'\\r'";
  1781. } else if (value == '\f') {
  1782. return "'\\f'";
  1783. } else if (value == '\n') {
  1784. return "'\\n'";
  1785. } else if (value == '\t') {
  1786. return "'\\t'";
  1787. } else if ('\0' <= value && value < ' ') {
  1788. return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
  1789. } else {
  1790. char chstr[] = "' '";
  1791. chstr[1] = value;
  1792. return chstr;
  1793. }
  1794. }
  1795. std::string StringMaker<char>::convert(char c) {
  1796. return ::Catch::Detail::stringify(static_cast<signed char>(c));
  1797. }
  1798. std::string StringMaker<unsigned char>::convert(unsigned char value) {
  1799. return ::Catch::Detail::stringify(static_cast<char>(value));
  1800. }
  1801. int StringMaker<float>::precision = std::numeric_limits<float>::max_digits10;
  1802. std::string StringMaker<float>::convert(float value) {
  1803. return Detail::fpToString(value, precision) + 'f';
  1804. }
  1805. int StringMaker<double>::precision = std::numeric_limits<double>::max_digits10;
  1806. std::string StringMaker<double>::convert(double value) {
  1807. return Detail::fpToString(value, precision);
  1808. }
  1809. } // end namespace Catch
  1810. namespace Catch {
  1811. Counts Counts::operator - ( Counts const& other ) const {
  1812. Counts diff;
  1813. diff.passed = passed - other.passed;
  1814. diff.failed = failed - other.failed;
  1815. diff.failedButOk = failedButOk - other.failedButOk;
  1816. diff.skipped = skipped - other.skipped;
  1817. return diff;
  1818. }
  1819. Counts& Counts::operator += ( Counts const& other ) {
  1820. passed += other.passed;
  1821. failed += other.failed;
  1822. failedButOk += other.failedButOk;
  1823. skipped += other.skipped;
  1824. return *this;
  1825. }
  1826. std::uint64_t Counts::total() const {
  1827. return passed + failed + failedButOk + skipped;
  1828. }
  1829. bool Counts::allPassed() const {
  1830. return failed == 0 && failedButOk == 0 && skipped == 0;
  1831. }
  1832. bool Counts::allOk() const {
  1833. return failed == 0;
  1834. }
  1835. Totals Totals::operator - ( Totals const& other ) const {
  1836. Totals diff;
  1837. diff.assertions = assertions - other.assertions;
  1838. diff.testCases = testCases - other.testCases;
  1839. return diff;
  1840. }
  1841. Totals& Totals::operator += ( Totals const& other ) {
  1842. assertions += other.assertions;
  1843. testCases += other.testCases;
  1844. return *this;
  1845. }
  1846. Totals Totals::delta( Totals const& prevTotals ) const {
  1847. Totals diff = *this - prevTotals;
  1848. if( diff.assertions.failed > 0 )
  1849. ++diff.testCases.failed;
  1850. else if( diff.assertions.failedButOk > 0 )
  1851. ++diff.testCases.failedButOk;
  1852. else if ( diff.assertions.skipped > 0 )
  1853. ++ diff.testCases.skipped;
  1854. else
  1855. ++diff.testCases.passed;
  1856. return diff;
  1857. }
  1858. }
  1859. namespace Catch {
  1860. namespace Detail {
  1861. void registerTranslatorImpl(
  1862. Detail::unique_ptr<IExceptionTranslator>&& translator ) {
  1863. getMutableRegistryHub().registerTranslator(
  1864. CATCH_MOVE( translator ) );
  1865. }
  1866. } // namespace Detail
  1867. } // namespace Catch
  1868. #include <ostream>
  1869. namespace Catch {
  1870. Version::Version
  1871. ( unsigned int _majorVersion,
  1872. unsigned int _minorVersion,
  1873. unsigned int _patchNumber,
  1874. char const * const _branchName,
  1875. unsigned int _buildNumber )
  1876. : majorVersion( _majorVersion ),
  1877. minorVersion( _minorVersion ),
  1878. patchNumber( _patchNumber ),
  1879. branchName( _branchName ),
  1880. buildNumber( _buildNumber )
  1881. {}
  1882. std::ostream& operator << ( std::ostream& os, Version const& version ) {
  1883. os << version.majorVersion << '.'
  1884. << version.minorVersion << '.'
  1885. << version.patchNumber;
  1886. // branchName is never null -> 0th char is \0 if it is empty
  1887. if (version.branchName[0]) {
  1888. os << '-' << version.branchName
  1889. << '.' << version.buildNumber;
  1890. }
  1891. return os;
  1892. }
  1893. Version const& libraryVersion() {
  1894. static Version version( 3, 7, 1, "", 0 );
  1895. return version;
  1896. }
  1897. }
  1898. namespace Catch {
  1899. const char* GeneratorException::what() const noexcept {
  1900. return m_msg;
  1901. }
  1902. } // end namespace Catch
  1903. namespace Catch {
  1904. IGeneratorTracker::~IGeneratorTracker() = default;
  1905. namespace Generators {
  1906. namespace Detail {
  1907. [[noreturn]]
  1908. void throw_generator_exception(char const* msg) {
  1909. Catch::throw_exception(GeneratorException{ msg });
  1910. }
  1911. } // end namespace Detail
  1912. GeneratorUntypedBase::~GeneratorUntypedBase() = default;
  1913. IGeneratorTracker* acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) {
  1914. return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
  1915. }
  1916. IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
  1917. SourceLineInfo lineInfo,
  1918. GeneratorBasePtr&& generator ) {
  1919. return getResultCapture().createGeneratorTracker(
  1920. generatorName, lineInfo, CATCH_MOVE( generator ) );
  1921. }
  1922. } // namespace Generators
  1923. } // namespace Catch
  1924. #include <random>
  1925. namespace Catch {
  1926. namespace Generators {
  1927. namespace Detail {
  1928. std::uint32_t getSeed() { return sharedRng()(); }
  1929. } // namespace Detail
  1930. struct RandomFloatingGenerator<long double>::PImpl {
  1931. PImpl( long double a, long double b, uint32_t seed ):
  1932. rng( seed ), dist( a, b ) {}
  1933. Catch::SimplePcg32 rng;
  1934. std::uniform_real_distribution<long double> dist;
  1935. };
  1936. RandomFloatingGenerator<long double>::RandomFloatingGenerator(
  1937. long double a, long double b, std::uint32_t seed) :
  1938. m_pimpl(Catch::Detail::make_unique<PImpl>(a, b, seed)) {
  1939. static_cast<void>( next() );
  1940. }
  1941. RandomFloatingGenerator<long double>::~RandomFloatingGenerator() =
  1942. default;
  1943. bool RandomFloatingGenerator<long double>::next() {
  1944. m_current_number = m_pimpl->dist( m_pimpl->rng );
  1945. return true;
  1946. }
  1947. } // namespace Generators
  1948. } // namespace Catch
  1949. namespace Catch {
  1950. IResultCapture::~IResultCapture() = default;
  1951. }
  1952. namespace Catch {
  1953. IConfig::~IConfig() = default;
  1954. }
  1955. namespace Catch {
  1956. IExceptionTranslator::~IExceptionTranslator() = default;
  1957. IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
  1958. }
  1959. #include <string>
  1960. namespace Catch {
  1961. namespace Generators {
  1962. bool GeneratorUntypedBase::countedNext() {
  1963. auto ret = next();
  1964. if ( ret ) {
  1965. m_stringReprCache.clear();
  1966. ++m_currentElementIndex;
  1967. }
  1968. return ret;
  1969. }
  1970. StringRef GeneratorUntypedBase::currentElementAsString() const {
  1971. if ( m_stringReprCache.empty() ) {
  1972. m_stringReprCache = stringifyImpl();
  1973. }
  1974. return m_stringReprCache;
  1975. }
  1976. } // namespace Generators
  1977. } // namespace Catch
  1978. namespace Catch {
  1979. IRegistryHub::~IRegistryHub() = default;
  1980. IMutableRegistryHub::~IMutableRegistryHub() = default;
  1981. }
  1982. #include <cassert>
  1983. namespace Catch {
  1984. ReporterConfig::ReporterConfig(
  1985. IConfig const* _fullConfig,
  1986. Detail::unique_ptr<IStream> _stream,
  1987. ColourMode colourMode,
  1988. std::map<std::string, std::string> customOptions ):
  1989. m_stream( CATCH_MOVE(_stream) ),
  1990. m_fullConfig( _fullConfig ),
  1991. m_colourMode( colourMode ),
  1992. m_customOptions( CATCH_MOVE( customOptions ) ) {}
  1993. Detail::unique_ptr<IStream> ReporterConfig::takeStream() && {
  1994. assert( m_stream );
  1995. return CATCH_MOVE( m_stream );
  1996. }
  1997. IConfig const * ReporterConfig::fullConfig() const { return m_fullConfig; }
  1998. ColourMode ReporterConfig::colourMode() const { return m_colourMode; }
  1999. std::map<std::string, std::string> const&
  2000. ReporterConfig::customOptions() const {
  2001. return m_customOptions;
  2002. }
  2003. ReporterConfig::~ReporterConfig() = default;
  2004. AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
  2005. std::vector<MessageInfo> const& _infoMessages,
  2006. Totals const& _totals )
  2007. : assertionResult( _assertionResult ),
  2008. infoMessages( _infoMessages ),
  2009. totals( _totals )
  2010. {
  2011. if( assertionResult.hasMessage() ) {
  2012. // Copy message into messages list.
  2013. // !TBD This should have been done earlier, somewhere
  2014. MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
  2015. builder.m_info.message = static_cast<std::string>(assertionResult.getMessage());
  2016. infoMessages.push_back( CATCH_MOVE(builder.m_info) );
  2017. }
  2018. }
  2019. SectionStats::SectionStats( SectionInfo&& _sectionInfo,
  2020. Counts const& _assertions,
  2021. double _durationInSeconds,
  2022. bool _missingAssertions )
  2023. : sectionInfo( CATCH_MOVE(_sectionInfo) ),
  2024. assertions( _assertions ),
  2025. durationInSeconds( _durationInSeconds ),
  2026. missingAssertions( _missingAssertions )
  2027. {}
  2028. TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
  2029. Totals const& _totals,
  2030. std::string&& _stdOut,
  2031. std::string&& _stdErr,
  2032. bool _aborting )
  2033. : testInfo( &_testInfo ),
  2034. totals( _totals ),
  2035. stdOut( CATCH_MOVE(_stdOut) ),
  2036. stdErr( CATCH_MOVE(_stdErr) ),
  2037. aborting( _aborting )
  2038. {}
  2039. TestRunStats::TestRunStats( TestRunInfo const& _runInfo,
  2040. Totals const& _totals,
  2041. bool _aborting )
  2042. : runInfo( _runInfo ),
  2043. totals( _totals ),
  2044. aborting( _aborting )
  2045. {}
  2046. IEventListener::~IEventListener() = default;
  2047. } // end namespace Catch
  2048. namespace Catch {
  2049. IReporterFactory::~IReporterFactory() = default;
  2050. EventListenerFactory::~EventListenerFactory() = default;
  2051. }
  2052. namespace Catch {
  2053. ITestCaseRegistry::~ITestCaseRegistry() = default;
  2054. }
  2055. namespace Catch {
  2056. AssertionHandler::AssertionHandler
  2057. ( StringRef macroName,
  2058. SourceLineInfo const& lineInfo,
  2059. StringRef capturedExpression,
  2060. ResultDisposition::Flags resultDisposition )
  2061. : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
  2062. m_resultCapture( getResultCapture() )
  2063. {
  2064. m_resultCapture.notifyAssertionStarted( m_assertionInfo );
  2065. }
  2066. void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
  2067. m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
  2068. }
  2069. void AssertionHandler::handleMessage(ResultWas::OfType resultType, std::string&& message) {
  2070. m_resultCapture.handleMessage( m_assertionInfo, resultType, CATCH_MOVE(message), m_reaction );
  2071. }
  2072. auto AssertionHandler::allowThrows() const -> bool {
  2073. return getCurrentContext().getConfig()->allowThrows();
  2074. }
  2075. void AssertionHandler::complete() {
  2076. m_completed = true;
  2077. if( m_reaction.shouldDebugBreak ) {
  2078. // If you find your debugger stopping you here then go one level up on the
  2079. // call-stack for the code that caused it (typically a failed assertion)
  2080. // (To go back to the test and change execution, jump over the throw, next)
  2081. CATCH_BREAK_INTO_DEBUGGER();
  2082. }
  2083. if (m_reaction.shouldThrow) {
  2084. throw_test_failure_exception();
  2085. }
  2086. if ( m_reaction.shouldSkip ) {
  2087. throw_test_skip_exception();
  2088. }
  2089. }
  2090. void AssertionHandler::handleUnexpectedInflightException() {
  2091. m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
  2092. }
  2093. void AssertionHandler::handleExceptionThrownAsExpected() {
  2094. m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
  2095. }
  2096. void AssertionHandler::handleExceptionNotThrownAsExpected() {
  2097. m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
  2098. }
  2099. void AssertionHandler::handleUnexpectedExceptionNotThrown() {
  2100. m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
  2101. }
  2102. void AssertionHandler::handleThrowingCallSkipped() {
  2103. m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
  2104. }
  2105. // This is the overload that takes a string and infers the Equals matcher from it
  2106. // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
  2107. void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str ) {
  2108. handleExceptionMatchExpr( handler, Matchers::Equals( str ) );
  2109. }
  2110. } // namespace Catch
  2111. #include <algorithm>
  2112. namespace Catch {
  2113. namespace Detail {
  2114. bool CaseInsensitiveLess::operator()( StringRef lhs,
  2115. StringRef rhs ) const {
  2116. return std::lexicographical_compare(
  2117. lhs.begin(), lhs.end(),
  2118. rhs.begin(), rhs.end(),
  2119. []( char l, char r ) { return toLower( l ) < toLower( r ); } );
  2120. }
  2121. bool
  2122. CaseInsensitiveEqualTo::operator()( StringRef lhs,
  2123. StringRef rhs ) const {
  2124. return std::equal(
  2125. lhs.begin(), lhs.end(),
  2126. rhs.begin(), rhs.end(),
  2127. []( char l, char r ) { return toLower( l ) == toLower( r ); } );
  2128. }
  2129. } // namespace Detail
  2130. } // namespace Catch
  2131. #include <algorithm>
  2132. #include <ostream>
  2133. namespace {
  2134. bool isOptPrefix( char c ) {
  2135. return c == '-'
  2136. #ifdef CATCH_PLATFORM_WINDOWS
  2137. || c == '/'
  2138. #endif
  2139. ;
  2140. }
  2141. Catch::StringRef normaliseOpt( Catch::StringRef optName ) {
  2142. if ( optName[0] == '-'
  2143. #if defined(CATCH_PLATFORM_WINDOWS)
  2144. || optName[0] == '/'
  2145. #endif
  2146. ) {
  2147. return optName.substr( 1, optName.size() );
  2148. }
  2149. return optName;
  2150. }
  2151. static size_t find_first_separator(Catch::StringRef sr) {
  2152. auto is_separator = []( char c ) {
  2153. return c == ' ' || c == ':' || c == '=';
  2154. };
  2155. size_t pos = 0;
  2156. while (pos < sr.size()) {
  2157. if (is_separator(sr[pos])) { return pos; }
  2158. ++pos;
  2159. }
  2160. return Catch::StringRef::npos;
  2161. }
  2162. } // namespace
  2163. namespace Catch {
  2164. namespace Clara {
  2165. namespace Detail {
  2166. void TokenStream::loadBuffer() {
  2167. m_tokenBuffer.clear();
  2168. // Skip any empty strings
  2169. while ( it != itEnd && it->empty() ) {
  2170. ++it;
  2171. }
  2172. if ( it != itEnd ) {
  2173. StringRef next = *it;
  2174. if ( isOptPrefix( next[0] ) ) {
  2175. auto delimiterPos = find_first_separator(next);
  2176. if ( delimiterPos != StringRef::npos ) {
  2177. m_tokenBuffer.push_back(
  2178. { TokenType::Option,
  2179. next.substr( 0, delimiterPos ) } );
  2180. m_tokenBuffer.push_back(
  2181. { TokenType::Argument,
  2182. next.substr( delimiterPos + 1, next.size() ) } );
  2183. } else {
  2184. if ( next.size() > 1 && next[1] != '-' && next.size() > 2 ) {
  2185. // Combined short args, e.g. "-ab" for "-a -b"
  2186. for ( size_t i = 1; i < next.size(); ++i ) {
  2187. m_tokenBuffer.push_back(
  2188. { TokenType::Option,
  2189. next.substr( i, 1 ) } );
  2190. }
  2191. } else {
  2192. m_tokenBuffer.push_back(
  2193. { TokenType::Option, next } );
  2194. }
  2195. }
  2196. } else {
  2197. m_tokenBuffer.push_back(
  2198. { TokenType::Argument, next } );
  2199. }
  2200. }
  2201. }
  2202. TokenStream::TokenStream( Args const& args ):
  2203. TokenStream( args.m_args.begin(), args.m_args.end() ) {}
  2204. TokenStream::TokenStream( Iterator it_, Iterator itEnd_ ):
  2205. it( it_ ), itEnd( itEnd_ ) {
  2206. loadBuffer();
  2207. }
  2208. TokenStream& TokenStream::operator++() {
  2209. if ( m_tokenBuffer.size() >= 2 ) {
  2210. m_tokenBuffer.erase( m_tokenBuffer.begin() );
  2211. } else {
  2212. if ( it != itEnd )
  2213. ++it;
  2214. loadBuffer();
  2215. }
  2216. return *this;
  2217. }
  2218. ParserResult convertInto( std::string const& source,
  2219. std::string& target ) {
  2220. target = source;
  2221. return ParserResult::ok( ParseResultType::Matched );
  2222. }
  2223. ParserResult convertInto( std::string const& source,
  2224. bool& target ) {
  2225. std::string srcLC = toLower( source );
  2226. if ( srcLC == "y" || srcLC == "1" || srcLC == "true" ||
  2227. srcLC == "yes" || srcLC == "on" ) {
  2228. target = true;
  2229. } else if ( srcLC == "n" || srcLC == "0" || srcLC == "false" ||
  2230. srcLC == "no" || srcLC == "off" ) {
  2231. target = false;
  2232. } else {
  2233. return ParserResult::runtimeError(
  2234. "Expected a boolean value but did not recognise: '" +
  2235. source + '\'' );
  2236. }
  2237. return ParserResult::ok( ParseResultType::Matched );
  2238. }
  2239. size_t ParserBase::cardinality() const { return 1; }
  2240. InternalParseResult ParserBase::parse( Args const& args ) const {
  2241. return parse( static_cast<std::string>(args.exeName()), TokenStream( args ) );
  2242. }
  2243. ParseState::ParseState( ParseResultType type,
  2244. TokenStream remainingTokens ):
  2245. m_type( type ), m_remainingTokens( CATCH_MOVE(remainingTokens) ) {}
  2246. ParserResult BoundFlagRef::setFlag( bool flag ) {
  2247. m_ref = flag;
  2248. return ParserResult::ok( ParseResultType::Matched );
  2249. }
  2250. ResultBase::~ResultBase() = default;
  2251. bool BoundRef::isContainer() const { return false; }
  2252. bool BoundRef::isFlag() const { return false; }
  2253. bool BoundFlagRefBase::isFlag() const { return true; }
  2254. } // namespace Detail
  2255. Detail::InternalParseResult Arg::parse(std::string const&,
  2256. Detail::TokenStream tokens) const {
  2257. auto validationResult = validate();
  2258. if (!validationResult)
  2259. return Detail::InternalParseResult(validationResult);
  2260. auto token = *tokens;
  2261. if (token.type != Detail::TokenType::Argument)
  2262. return Detail::InternalParseResult::ok(Detail::ParseState(
  2263. ParseResultType::NoMatch, CATCH_MOVE(tokens)));
  2264. assert(!m_ref->isFlag());
  2265. auto valueRef =
  2266. static_cast<Detail::BoundValueRefBase*>(m_ref.get());
  2267. auto result = valueRef->setValue(static_cast<std::string>(token.token));
  2268. if ( !result )
  2269. return Detail::InternalParseResult( result );
  2270. else
  2271. return Detail::InternalParseResult::ok(
  2272. Detail::ParseState( ParseResultType::Matched,
  2273. CATCH_MOVE( ++tokens ) ) );
  2274. }
  2275. Opt::Opt(bool& ref) :
  2276. ParserRefImpl(std::make_shared<Detail::BoundFlagRef>(ref)) {}
  2277. Detail::HelpColumns Opt::getHelpColumns() const {
  2278. ReusableStringStream oss;
  2279. bool first = true;
  2280. for (auto const& opt : m_optNames) {
  2281. if (first)
  2282. first = false;
  2283. else
  2284. oss << ", ";
  2285. oss << opt;
  2286. }
  2287. if (!m_hint.empty())
  2288. oss << " <" << m_hint << '>';
  2289. return { oss.str(), m_description };
  2290. }
  2291. bool Opt::isMatch(StringRef optToken) const {
  2292. auto normalisedToken = normaliseOpt(optToken);
  2293. for (auto const& name : m_optNames) {
  2294. if (normaliseOpt(name) == normalisedToken)
  2295. return true;
  2296. }
  2297. return false;
  2298. }
  2299. Detail::InternalParseResult Opt::parse(std::string const&,
  2300. Detail::TokenStream tokens) const {
  2301. auto validationResult = validate();
  2302. if (!validationResult)
  2303. return Detail::InternalParseResult(validationResult);
  2304. if (tokens &&
  2305. tokens->type == Detail::TokenType::Option) {
  2306. auto const& token = *tokens;
  2307. if (isMatch(token.token)) {
  2308. if (m_ref->isFlag()) {
  2309. auto flagRef =
  2310. static_cast<Detail::BoundFlagRefBase*>(
  2311. m_ref.get());
  2312. auto result = flagRef->setFlag(true);
  2313. if (!result)
  2314. return Detail::InternalParseResult(result);
  2315. if (result.value() ==
  2316. ParseResultType::ShortCircuitAll)
  2317. return Detail::InternalParseResult::ok(Detail::ParseState(
  2318. result.value(), CATCH_MOVE(tokens)));
  2319. } else {
  2320. auto valueRef =
  2321. static_cast<Detail::BoundValueRefBase*>(
  2322. m_ref.get());
  2323. ++tokens;
  2324. if (!tokens)
  2325. return Detail::InternalParseResult::runtimeError(
  2326. "Expected argument following " +
  2327. token.token);
  2328. auto const& argToken = *tokens;
  2329. if (argToken.type != Detail::TokenType::Argument)
  2330. return Detail::InternalParseResult::runtimeError(
  2331. "Expected argument following " +
  2332. token.token);
  2333. const auto result = valueRef->setValue(static_cast<std::string>(argToken.token));
  2334. if (!result)
  2335. return Detail::InternalParseResult(result);
  2336. if (result.value() ==
  2337. ParseResultType::ShortCircuitAll)
  2338. return Detail::InternalParseResult::ok(Detail::ParseState(
  2339. result.value(), CATCH_MOVE(tokens)));
  2340. }
  2341. return Detail::InternalParseResult::ok(Detail::ParseState(
  2342. ParseResultType::Matched, CATCH_MOVE(++tokens)));
  2343. }
  2344. }
  2345. return Detail::InternalParseResult::ok(
  2346. Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
  2347. }
  2348. Detail::Result Opt::validate() const {
  2349. if (m_optNames.empty())
  2350. return Detail::Result::logicError("No options supplied to Opt");
  2351. for (auto const& name : m_optNames) {
  2352. if (name.empty())
  2353. return Detail::Result::logicError(
  2354. "Option name cannot be empty");
  2355. #ifdef CATCH_PLATFORM_WINDOWS
  2356. if (name[0] != '-' && name[0] != '/')
  2357. return Detail::Result::logicError(
  2358. "Option name must begin with '-' or '/'");
  2359. #else
  2360. if (name[0] != '-')
  2361. return Detail::Result::logicError(
  2362. "Option name must begin with '-'");
  2363. #endif
  2364. }
  2365. return ParserRefImpl::validate();
  2366. }
  2367. ExeName::ExeName() :
  2368. m_name(std::make_shared<std::string>("<executable>")) {}
  2369. ExeName::ExeName(std::string& ref) : ExeName() {
  2370. m_ref = std::make_shared<Detail::BoundValueRef<std::string>>(ref);
  2371. }
  2372. Detail::InternalParseResult
  2373. ExeName::parse(std::string const&,
  2374. Detail::TokenStream tokens) const {
  2375. return Detail::InternalParseResult::ok(
  2376. Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
  2377. }
  2378. ParserResult ExeName::set(std::string const& newName) {
  2379. auto lastSlash = newName.find_last_of("\\/");
  2380. auto filename = (lastSlash == std::string::npos)
  2381. ? newName
  2382. : newName.substr(lastSlash + 1);
  2383. *m_name = filename;
  2384. if (m_ref)
  2385. return m_ref->setValue(filename);
  2386. else
  2387. return ParserResult::ok(ParseResultType::Matched);
  2388. }
  2389. Parser& Parser::operator|=( Parser const& other ) {
  2390. m_options.insert( m_options.end(),
  2391. other.m_options.begin(),
  2392. other.m_options.end() );
  2393. m_args.insert(
  2394. m_args.end(), other.m_args.begin(), other.m_args.end() );
  2395. return *this;
  2396. }
  2397. std::vector<Detail::HelpColumns> Parser::getHelpColumns() const {
  2398. std::vector<Detail::HelpColumns> cols;
  2399. cols.reserve( m_options.size() );
  2400. for ( auto const& o : m_options ) {
  2401. cols.push_back(o.getHelpColumns());
  2402. }
  2403. return cols;
  2404. }
  2405. void Parser::writeToStream( std::ostream& os ) const {
  2406. if ( !m_exeName.name().empty() ) {
  2407. os << "usage:\n"
  2408. << " " << m_exeName.name() << ' ';
  2409. bool required = true, first = true;
  2410. for ( auto const& arg : m_args ) {
  2411. if ( first )
  2412. first = false;
  2413. else
  2414. os << ' ';
  2415. if ( arg.isOptional() && required ) {
  2416. os << '[';
  2417. required = false;
  2418. }
  2419. os << '<' << arg.hint() << '>';
  2420. if ( arg.cardinality() == 0 )
  2421. os << " ... ";
  2422. }
  2423. if ( !required )
  2424. os << ']';
  2425. if ( !m_options.empty() )
  2426. os << " options";
  2427. os << "\n\nwhere options are:\n";
  2428. }
  2429. auto rows = getHelpColumns();
  2430. size_t consoleWidth = CATCH_CONFIG_CONSOLE_WIDTH;
  2431. size_t optWidth = 0;
  2432. for ( auto const& cols : rows )
  2433. optWidth = ( std::max )( optWidth, cols.left.size() + 2 );
  2434. optWidth = ( std::min )( optWidth, consoleWidth / 2 );
  2435. for ( auto& cols : rows ) {
  2436. auto row = TextFlow::Column( CATCH_MOVE(cols.left) )
  2437. .width( optWidth )
  2438. .indent( 2 ) +
  2439. TextFlow::Spacer( 4 ) +
  2440. TextFlow::Column( static_cast<std::string>(cols.descriptions) )
  2441. .width( consoleWidth - 7 - optWidth );
  2442. os << row << '\n';
  2443. }
  2444. }
  2445. Detail::Result Parser::validate() const {
  2446. for ( auto const& opt : m_options ) {
  2447. auto result = opt.validate();
  2448. if ( !result )
  2449. return result;
  2450. }
  2451. for ( auto const& arg : m_args ) {
  2452. auto result = arg.validate();
  2453. if ( !result )
  2454. return result;
  2455. }
  2456. return Detail::Result::ok();
  2457. }
  2458. Detail::InternalParseResult
  2459. Parser::parse( std::string const& exeName,
  2460. Detail::TokenStream tokens ) const {
  2461. struct ParserInfo {
  2462. ParserBase const* parser = nullptr;
  2463. size_t count = 0;
  2464. };
  2465. std::vector<ParserInfo> parseInfos;
  2466. parseInfos.reserve( m_options.size() + m_args.size() );
  2467. for ( auto const& opt : m_options ) {
  2468. parseInfos.push_back( { &opt, 0 } );
  2469. }
  2470. for ( auto const& arg : m_args ) {
  2471. parseInfos.push_back( { &arg, 0 } );
  2472. }
  2473. m_exeName.set( exeName );
  2474. auto result = Detail::InternalParseResult::ok(
  2475. Detail::ParseState( ParseResultType::NoMatch, CATCH_MOVE(tokens) ) );
  2476. while ( result.value().remainingTokens() ) {
  2477. bool tokenParsed = false;
  2478. for ( auto& parseInfo : parseInfos ) {
  2479. if ( parseInfo.parser->cardinality() == 0 ||
  2480. parseInfo.count < parseInfo.parser->cardinality() ) {
  2481. result = parseInfo.parser->parse(
  2482. exeName, CATCH_MOVE(result).value().remainingTokens() );
  2483. if ( !result )
  2484. return result;
  2485. if ( result.value().type() !=
  2486. ParseResultType::NoMatch ) {
  2487. tokenParsed = true;
  2488. ++parseInfo.count;
  2489. break;
  2490. }
  2491. }
  2492. }
  2493. if ( result.value().type() == ParseResultType::ShortCircuitAll )
  2494. return result;
  2495. if ( !tokenParsed )
  2496. return Detail::InternalParseResult::runtimeError(
  2497. "Unrecognised token: " +
  2498. result.value().remainingTokens()->token );
  2499. }
  2500. // !TBD Check missing required options
  2501. return result;
  2502. }
  2503. Args::Args(int argc, char const* const* argv) :
  2504. m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
  2505. Args::Args(std::initializer_list<StringRef> args) :
  2506. m_exeName(*args.begin()),
  2507. m_args(args.begin() + 1, args.end()) {}
  2508. Help::Help( bool& showHelpFlag ):
  2509. Opt( [&]( bool flag ) {
  2510. showHelpFlag = flag;
  2511. return ParserResult::ok( ParseResultType::ShortCircuitAll );
  2512. } ) {
  2513. static_cast<Opt&> ( *this )(
  2514. "display usage information" )["-?"]["-h"]["--help"]
  2515. .optional();
  2516. }
  2517. } // namespace Clara
  2518. } // namespace Catch
  2519. #include <fstream>
  2520. #include <string>
  2521. namespace Catch {
  2522. Clara::Parser makeCommandLineParser( ConfigData& config ) {
  2523. using namespace Clara;
  2524. auto const setWarning = [&]( std::string const& warning ) {
  2525. if ( warning == "NoAssertions" ) {
  2526. config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::NoAssertions);
  2527. return ParserResult::ok( ParseResultType::Matched );
  2528. } else if ( warning == "UnmatchedTestSpec" ) {
  2529. config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::UnmatchedTestSpec);
  2530. return ParserResult::ok( ParseResultType::Matched );
  2531. }
  2532. return ParserResult ::runtimeError(
  2533. "Unrecognised warning option: '" + warning + '\'' );
  2534. };
  2535. auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
  2536. std::ifstream f( filename.c_str() );
  2537. if( !f.is_open() )
  2538. return ParserResult::runtimeError( "Unable to load input file: '" + filename + '\'' );
  2539. std::string line;
  2540. while( std::getline( f, line ) ) {
  2541. line = trim(line);
  2542. if( !line.empty() && !startsWith( line, '#' ) ) {
  2543. if( !startsWith( line, '"' ) )
  2544. line = '"' + CATCH_MOVE(line) + '"';
  2545. config.testsOrTags.push_back( line );
  2546. config.testsOrTags.emplace_back( "," );
  2547. }
  2548. }
  2549. //Remove comma in the end
  2550. if(!config.testsOrTags.empty())
  2551. config.testsOrTags.erase( config.testsOrTags.end()-1 );
  2552. return ParserResult::ok( ParseResultType::Matched );
  2553. };
  2554. auto const setTestOrder = [&]( std::string const& order ) {
  2555. if( startsWith( "declared", order ) )
  2556. config.runOrder = TestRunOrder::Declared;
  2557. else if( startsWith( "lexical", order ) )
  2558. config.runOrder = TestRunOrder::LexicographicallySorted;
  2559. else if( startsWith( "random", order ) )
  2560. config.runOrder = TestRunOrder::Randomized;
  2561. else
  2562. return ParserResult::runtimeError( "Unrecognised ordering: '" + order + '\'' );
  2563. return ParserResult::ok( ParseResultType::Matched );
  2564. };
  2565. auto const setRngSeed = [&]( std::string const& seed ) {
  2566. if( seed == "time" ) {
  2567. config.rngSeed = generateRandomSeed(GenerateFrom::Time);
  2568. return ParserResult::ok(ParseResultType::Matched);
  2569. } else if (seed == "random-device") {
  2570. config.rngSeed = generateRandomSeed(GenerateFrom::RandomDevice);
  2571. return ParserResult::ok(ParseResultType::Matched);
  2572. }
  2573. // TODO: ideally we should be parsing uint32_t directly
  2574. // fix this later when we add new parse overload
  2575. auto parsedSeed = parseUInt( seed, 0 );
  2576. if ( !parsedSeed ) {
  2577. return ParserResult::runtimeError( "Could not parse '" + seed + "' as seed" );
  2578. }
  2579. config.rngSeed = *parsedSeed;
  2580. return ParserResult::ok( ParseResultType::Matched );
  2581. };
  2582. auto const setDefaultColourMode = [&]( std::string const& colourMode ) {
  2583. Optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
  2584. if ( !maybeMode ) {
  2585. return ParserResult::runtimeError(
  2586. "colour mode must be one of: default, ansi, win32, "
  2587. "or none. '" +
  2588. colourMode + "' is not recognised" );
  2589. }
  2590. auto mode = *maybeMode;
  2591. if ( !isColourImplAvailable( mode ) ) {
  2592. return ParserResult::runtimeError(
  2593. "colour mode '" + colourMode +
  2594. "' is not supported in this binary" );
  2595. }
  2596. config.defaultColourMode = mode;
  2597. return ParserResult::ok( ParseResultType::Matched );
  2598. };
  2599. auto const setWaitForKeypress = [&]( std::string const& keypress ) {
  2600. auto keypressLc = toLower( keypress );
  2601. if (keypressLc == "never")
  2602. config.waitForKeypress = WaitForKeypress::Never;
  2603. else if( keypressLc == "start" )
  2604. config.waitForKeypress = WaitForKeypress::BeforeStart;
  2605. else if( keypressLc == "exit" )
  2606. config.waitForKeypress = WaitForKeypress::BeforeExit;
  2607. else if( keypressLc == "both" )
  2608. config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
  2609. else
  2610. return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );
  2611. return ParserResult::ok( ParseResultType::Matched );
  2612. };
  2613. auto const setVerbosity = [&]( std::string const& verbosity ) {
  2614. auto lcVerbosity = toLower( verbosity );
  2615. if( lcVerbosity == "quiet" )
  2616. config.verbosity = Verbosity::Quiet;
  2617. else if( lcVerbosity == "normal" )
  2618. config.verbosity = Verbosity::Normal;
  2619. else if( lcVerbosity == "high" )
  2620. config.verbosity = Verbosity::High;
  2621. else
  2622. return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + '\'' );
  2623. return ParserResult::ok( ParseResultType::Matched );
  2624. };
  2625. auto const setReporter = [&]( std::string const& userReporterSpec ) {
  2626. if ( userReporterSpec.empty() ) {
  2627. return ParserResult::runtimeError( "Received empty reporter spec." );
  2628. }
  2629. Optional<ReporterSpec> parsed =
  2630. parseReporterSpec( userReporterSpec );
  2631. if ( !parsed ) {
  2632. return ParserResult::runtimeError(
  2633. "Could not parse reporter spec '" + userReporterSpec +
  2634. "'" );
  2635. }
  2636. auto const& reporterSpec = *parsed;
  2637. auto const& factories =
  2638. getRegistryHub().getReporterRegistry().getFactories();
  2639. auto result = factories.find( reporterSpec.name() );
  2640. if ( result == factories.end() ) {
  2641. return ParserResult::runtimeError(
  2642. "Unrecognized reporter, '" + reporterSpec.name() +
  2643. "'. Check available with --list-reporters" );
  2644. }
  2645. const bool hadOutputFile = reporterSpec.outputFile().some();
  2646. config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) );
  2647. // It would be enough to check this only once at the very end, but
  2648. // there is not a place where we could call this check, so do it
  2649. // every time it could fail. For valid inputs, this is still called
  2650. // at most once.
  2651. if (!hadOutputFile) {
  2652. int n_reporters_without_file = 0;
  2653. for (auto const& spec : config.reporterSpecifications) {
  2654. if (spec.outputFile().none()) {
  2655. n_reporters_without_file++;
  2656. }
  2657. }
  2658. if (n_reporters_without_file > 1) {
  2659. return ParserResult::runtimeError( "Only one reporter may have unspecified output file." );
  2660. }
  2661. }
  2662. return ParserResult::ok( ParseResultType::Matched );
  2663. };
  2664. auto const setShardCount = [&]( std::string const& shardCount ) {
  2665. auto parsedCount = parseUInt( shardCount );
  2666. if ( !parsedCount ) {
  2667. return ParserResult::runtimeError(
  2668. "Could not parse '" + shardCount + "' as shard count" );
  2669. }
  2670. if ( *parsedCount == 0 ) {
  2671. return ParserResult::runtimeError(
  2672. "Shard count must be positive" );
  2673. }
  2674. config.shardCount = *parsedCount;
  2675. return ParserResult::ok( ParseResultType::Matched );
  2676. };
  2677. auto const setShardIndex = [&](std::string const& shardIndex) {
  2678. auto parsedIndex = parseUInt( shardIndex );
  2679. if ( !parsedIndex ) {
  2680. return ParserResult::runtimeError(
  2681. "Could not parse '" + shardIndex + "' as shard index" );
  2682. }
  2683. config.shardIndex = *parsedIndex;
  2684. return ParserResult::ok( ParseResultType::Matched );
  2685. };
  2686. auto cli
  2687. = ExeName( config.processName )
  2688. | Help( config.showHelp )
  2689. | Opt( config.showSuccessfulTests )
  2690. ["-s"]["--success"]
  2691. ( "include successful tests in output" )
  2692. | Opt( config.shouldDebugBreak )
  2693. ["-b"]["--break"]
  2694. ( "break into debugger on failure" )
  2695. | Opt( config.noThrow )
  2696. ["-e"]["--nothrow"]
  2697. ( "skip exception tests" )
  2698. | Opt( config.showInvisibles )
  2699. ["-i"]["--invisibles"]
  2700. ( "show invisibles (tabs, newlines)" )
  2701. | Opt( config.defaultOutputFilename, "filename" )
  2702. ["-o"]["--out"]
  2703. ( "default output filename" )
  2704. | Opt( accept_many, setReporter, "name[::key=value]*" )
  2705. ["-r"]["--reporter"]
  2706. ( "reporter to use (defaults to console)" )
  2707. | Opt( config.name, "name" )
  2708. ["-n"]["--name"]
  2709. ( "suite name" )
  2710. | Opt( [&]( bool ){ config.abortAfter = 1; } )
  2711. ["-a"]["--abort"]
  2712. ( "abort at first failure" )
  2713. | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
  2714. ["-x"]["--abortx"]
  2715. ( "abort after x failures" )
  2716. | Opt( accept_many, setWarning, "warning name" )
  2717. ["-w"]["--warn"]
  2718. ( "enable warnings" )
  2719. | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
  2720. ["-d"]["--durations"]
  2721. ( "show test durations" )
  2722. | Opt( config.minDuration, "seconds" )
  2723. ["-D"]["--min-duration"]
  2724. ( "show test durations for tests taking at least the given number of seconds" )
  2725. | Opt( loadTestNamesFromFile, "filename" )
  2726. ["-f"]["--input-file"]
  2727. ( "load test names to run from a file" )
  2728. | Opt( config.filenamesAsTags )
  2729. ["-#"]["--filenames-as-tags"]
  2730. ( "adds a tag for the filename" )
  2731. | Opt( config.sectionsToRun, "section name" )
  2732. ["-c"]["--section"]
  2733. ( "specify section to run" )
  2734. | Opt( setVerbosity, "quiet|normal|high" )
  2735. ["-v"]["--verbosity"]
  2736. ( "set output verbosity" )
  2737. | Opt( config.listTests )
  2738. ["--list-tests"]
  2739. ( "list all/matching test cases" )
  2740. | Opt( config.listTags )
  2741. ["--list-tags"]
  2742. ( "list all/matching tags" )
  2743. | Opt( config.listReporters )
  2744. ["--list-reporters"]
  2745. ( "list all available reporters" )
  2746. | Opt( config.listListeners )
  2747. ["--list-listeners"]
  2748. ( "list all listeners" )
  2749. | Opt( setTestOrder, "decl|lex|rand" )
  2750. ["--order"]
  2751. ( "test case order (defaults to decl)" )
  2752. | Opt( setRngSeed, "'time'|'random-device'|number" )
  2753. ["--rng-seed"]
  2754. ( "set a specific seed for random numbers" )
  2755. | Opt( setDefaultColourMode, "ansi|win32|none|default" )
  2756. ["--colour-mode"]
  2757. ( "what color mode should be used as default" )
  2758. | Opt( config.libIdentify )
  2759. ["--libidentify"]
  2760. ( "report name and version according to libidentify standard" )
  2761. | Opt( setWaitForKeypress, "never|start|exit|both" )
  2762. ["--wait-for-keypress"]
  2763. ( "waits for a keypress before exiting" )
  2764. | Opt( config.skipBenchmarks)
  2765. ["--skip-benchmarks"]
  2766. ( "disable running benchmarks")
  2767. | Opt( config.benchmarkSamples, "samples" )
  2768. ["--benchmark-samples"]
  2769. ( "number of samples to collect (default: 100)" )
  2770. | Opt( config.benchmarkResamples, "resamples" )
  2771. ["--benchmark-resamples"]
  2772. ( "number of resamples for the bootstrap (default: 100000)" )
  2773. | Opt( config.benchmarkConfidenceInterval, "confidence interval" )
  2774. ["--benchmark-confidence-interval"]
  2775. ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )
  2776. | Opt( config.benchmarkNoAnalysis )
  2777. ["--benchmark-no-analysis"]
  2778. ( "perform only measurements; do not perform any analysis" )
  2779. | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )
  2780. ["--benchmark-warmup-time"]
  2781. ( "amount of time in milliseconds spent on warming up each test (default: 100)" )
  2782. | Opt( setShardCount, "shard count" )
  2783. ["--shard-count"]
  2784. ( "split the tests to execute into this many groups" )
  2785. | Opt( setShardIndex, "shard index" )
  2786. ["--shard-index"]
  2787. ( "index of the group of tests to execute (see --shard-count)" )
  2788. | Opt( config.allowZeroTests )
  2789. ["--allow-running-no-tests"]
  2790. ( "Treat 'No tests run' as a success" )
  2791. | Arg( config.testsOrTags, "test name|pattern|tags" )
  2792. ( "which test or tests to use" );
  2793. return cli;
  2794. }
  2795. } // end namespace Catch
  2796. #if defined(__clang__)
  2797. # pragma clang diagnostic push
  2798. # pragma clang diagnostic ignored "-Wexit-time-destructors"
  2799. #endif
  2800. #include <cassert>
  2801. #include <ostream>
  2802. #include <utility>
  2803. namespace Catch {
  2804. ColourImpl::~ColourImpl() = default;
  2805. ColourImpl::ColourGuard ColourImpl::guardColour( Colour::Code colourCode ) {
  2806. return ColourGuard(colourCode, this );
  2807. }
  2808. void ColourImpl::ColourGuard::engageImpl( std::ostream& stream ) {
  2809. assert( &stream == &m_colourImpl->m_stream->stream() &&
  2810. "Engaging colour guard for different stream than used by the "
  2811. "parent colour implementation" );
  2812. static_cast<void>( stream );
  2813. m_engaged = true;
  2814. m_colourImpl->use( m_code );
  2815. }
  2816. ColourImpl::ColourGuard::ColourGuard( Colour::Code code,
  2817. ColourImpl const* colour ):
  2818. m_colourImpl( colour ), m_code( code ) {
  2819. }
  2820. ColourImpl::ColourGuard::ColourGuard( ColourGuard&& rhs ) noexcept:
  2821. m_colourImpl( rhs.m_colourImpl ),
  2822. m_code( rhs.m_code ),
  2823. m_engaged( rhs.m_engaged ) {
  2824. rhs.m_engaged = false;
  2825. }
  2826. ColourImpl::ColourGuard&
  2827. ColourImpl::ColourGuard::operator=( ColourGuard&& rhs ) noexcept {
  2828. using std::swap;
  2829. swap( m_colourImpl, rhs.m_colourImpl );
  2830. swap( m_code, rhs.m_code );
  2831. swap( m_engaged, rhs.m_engaged );
  2832. return *this;
  2833. }
  2834. ColourImpl::ColourGuard::~ColourGuard() {
  2835. if ( m_engaged ) {
  2836. m_colourImpl->use( Colour::None );
  2837. }
  2838. }
  2839. ColourImpl::ColourGuard&
  2840. ColourImpl::ColourGuard::engage( std::ostream& stream ) & {
  2841. engageImpl( stream );
  2842. return *this;
  2843. }
  2844. ColourImpl::ColourGuard&&
  2845. ColourImpl::ColourGuard::engage( std::ostream& stream ) && {
  2846. engageImpl( stream );
  2847. return CATCH_MOVE(*this);
  2848. }
  2849. namespace {
  2850. //! A do-nothing implementation of colour, used as fallback for unknown
  2851. //! platforms, and when the user asks to deactivate all colours.
  2852. class NoColourImpl final : public ColourImpl {
  2853. public:
  2854. NoColourImpl( IStream* stream ): ColourImpl( stream ) {}
  2855. private:
  2856. void use( Colour::Code ) const override {}
  2857. };
  2858. } // namespace
  2859. } // namespace Catch
  2860. #if defined ( CATCH_CONFIG_COLOUR_WIN32 ) /////////////////////////////////////////
  2861. namespace Catch {
  2862. namespace {
  2863. class Win32ColourImpl final : public ColourImpl {
  2864. public:
  2865. Win32ColourImpl(IStream* stream):
  2866. ColourImpl(stream) {
  2867. CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
  2868. GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ),
  2869. &csbiInfo );
  2870. originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
  2871. originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
  2872. }
  2873. static bool useImplementationForStream(IStream const& stream) {
  2874. // Win32 text colour APIs can only be used on console streams
  2875. // We cannot check that the output hasn't been redirected,
  2876. // so we just check that the original stream is console stream.
  2877. return stream.isConsole();
  2878. }
  2879. private:
  2880. void use( Colour::Code _colourCode ) const override {
  2881. switch( _colourCode ) {
  2882. case Colour::None: return setTextAttribute( originalForegroundAttributes );
  2883. case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
  2884. case Colour::Red: return setTextAttribute( FOREGROUND_RED );
  2885. case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
  2886. case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
  2887. case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
  2888. case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
  2889. case Colour::Grey: return setTextAttribute( 0 );
  2890. case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
  2891. case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
  2892. case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
  2893. case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
  2894. case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
  2895. case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
  2896. default:
  2897. CATCH_ERROR( "Unknown colour requested" );
  2898. }
  2899. }
  2900. void setTextAttribute( WORD _textAttribute ) const {
  2901. SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ),
  2902. _textAttribute |
  2903. originalBackgroundAttributes );
  2904. }
  2905. WORD originalForegroundAttributes;
  2906. WORD originalBackgroundAttributes;
  2907. };
  2908. } // end anon namespace
  2909. } // end namespace Catch
  2910. #endif // Windows/ ANSI/ None
  2911. #if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC )
  2912. # define CATCH_INTERNAL_HAS_ISATTY
  2913. # include <unistd.h>
  2914. #endif
  2915. namespace Catch {
  2916. namespace {
  2917. class ANSIColourImpl final : public ColourImpl {
  2918. public:
  2919. ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {}
  2920. static bool useImplementationForStream(IStream const& stream) {
  2921. // This is kinda messy due to trying to support a bunch of
  2922. // different platforms at once.
  2923. // The basic idea is that if we are asked to do autodetection (as
  2924. // opposed to being told to use posixy colours outright), then we
  2925. // only want to use the colours if we are writing to console.
  2926. // However, console might be redirected, so we make an attempt at
  2927. // checking for that on platforms where we know how to do that.
  2928. bool useColour = stream.isConsole();
  2929. #if defined( CATCH_INTERNAL_HAS_ISATTY ) && \
  2930. !( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) )
  2931. ErrnoGuard _; // for isatty
  2932. useColour = useColour && isatty( STDOUT_FILENO );
  2933. # endif
  2934. # if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE )
  2935. useColour = useColour && !isDebuggerActive();
  2936. # endif
  2937. return useColour;
  2938. }
  2939. private:
  2940. void use( Colour::Code _colourCode ) const override {
  2941. auto setColour = [&out =
  2942. m_stream->stream()]( char const* escapeCode ) {
  2943. // The escape sequence must be flushed to console, otherwise
  2944. // if stdin and stderr are intermixed, we'd get accidentally
  2945. // coloured output.
  2946. out << '\033' << escapeCode << std::flush;
  2947. };
  2948. switch( _colourCode ) {
  2949. case Colour::None:
  2950. case Colour::White: return setColour( "[0m" );
  2951. case Colour::Red: return setColour( "[0;31m" );
  2952. case Colour::Green: return setColour( "[0;32m" );
  2953. case Colour::Blue: return setColour( "[0;34m" );
  2954. case Colour::Cyan: return setColour( "[0;36m" );
  2955. case Colour::Yellow: return setColour( "[0;33m" );
  2956. case Colour::Grey: return setColour( "[1;30m" );
  2957. case Colour::LightGrey: return setColour( "[0;37m" );
  2958. case Colour::BrightRed: return setColour( "[1;31m" );
  2959. case Colour::BrightGreen: return setColour( "[1;32m" );
  2960. case Colour::BrightWhite: return setColour( "[1;37m" );
  2961. case Colour::BrightYellow: return setColour( "[1;33m" );
  2962. case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
  2963. default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
  2964. }
  2965. }
  2966. };
  2967. } // end anon namespace
  2968. } // end namespace Catch
  2969. namespace Catch {
  2970. Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
  2971. IStream* stream ) {
  2972. #if defined( CATCH_CONFIG_COLOUR_WIN32 )
  2973. if ( colourSelection == ColourMode::Win32 ) {
  2974. return Detail::make_unique<Win32ColourImpl>( stream );
  2975. }
  2976. #endif
  2977. if ( colourSelection == ColourMode::ANSI ) {
  2978. return Detail::make_unique<ANSIColourImpl>( stream );
  2979. }
  2980. if ( colourSelection == ColourMode::None ) {
  2981. return Detail::make_unique<NoColourImpl>( stream );
  2982. }
  2983. if ( colourSelection == ColourMode::PlatformDefault) {
  2984. #if defined( CATCH_CONFIG_COLOUR_WIN32 )
  2985. if ( Win32ColourImpl::useImplementationForStream( *stream ) ) {
  2986. return Detail::make_unique<Win32ColourImpl>( stream );
  2987. }
  2988. #endif
  2989. if ( ANSIColourImpl::useImplementationForStream( *stream ) ) {
  2990. return Detail::make_unique<ANSIColourImpl>( stream );
  2991. }
  2992. return Detail::make_unique<NoColourImpl>( stream );
  2993. }
  2994. CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(colourSelection) );
  2995. }
  2996. bool isColourImplAvailable( ColourMode colourSelection ) {
  2997. switch ( colourSelection ) {
  2998. #if defined( CATCH_CONFIG_COLOUR_WIN32 )
  2999. case ColourMode::Win32:
  3000. #endif
  3001. case ColourMode::ANSI:
  3002. case ColourMode::None:
  3003. case ColourMode::PlatformDefault:
  3004. return true;
  3005. default:
  3006. return false;
  3007. }
  3008. }
  3009. } // end namespace Catch
  3010. #if defined(__clang__)
  3011. # pragma clang diagnostic pop
  3012. #endif
  3013. namespace Catch {
  3014. Context* Context::currentContext = nullptr;
  3015. void cleanUpContext() {
  3016. delete Context::currentContext;
  3017. Context::currentContext = nullptr;
  3018. }
  3019. void Context::createContext() {
  3020. currentContext = new Context();
  3021. }
  3022. Context& getCurrentMutableContext() {
  3023. if ( !Context::currentContext ) { Context::createContext(); }
  3024. // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
  3025. return *Context::currentContext;
  3026. }
  3027. SimplePcg32& sharedRng() {
  3028. static SimplePcg32 s_rng;
  3029. return s_rng;
  3030. }
  3031. }
  3032. #include <ostream>
  3033. #if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
  3034. #include <android/log.h>
  3035. namespace Catch {
  3036. void writeToDebugConsole( std::string const& text ) {
  3037. __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
  3038. }
  3039. }
  3040. #elif defined(CATCH_PLATFORM_WINDOWS)
  3041. namespace Catch {
  3042. void writeToDebugConsole( std::string const& text ) {
  3043. ::OutputDebugStringA( text.c_str() );
  3044. }
  3045. }
  3046. #else
  3047. namespace Catch {
  3048. void writeToDebugConsole( std::string const& text ) {
  3049. // !TBD: Need a version for Mac/ XCode and other IDEs
  3050. Catch::cout() << text;
  3051. }
  3052. }
  3053. #endif // Platform
  3054. #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
  3055. # include <cassert>
  3056. # include <sys/types.h>
  3057. # include <unistd.h>
  3058. # include <cstddef>
  3059. # include <ostream>
  3060. #ifdef __apple_build_version__
  3061. // These headers will only compile with AppleClang (XCode)
  3062. // For other compilers (Clang, GCC, ... ) we need to exclude them
  3063. # include <sys/sysctl.h>
  3064. #endif
  3065. namespace Catch {
  3066. #ifdef __apple_build_version__
  3067. // The following function is taken directly from the following technical note:
  3068. // https://developer.apple.com/library/archive/qa/qa1361/_index.html
  3069. // Returns true if the current process is being debugged (either
  3070. // running under the debugger or has a debugger attached post facto).
  3071. bool isDebuggerActive(){
  3072. int mib[4];
  3073. struct kinfo_proc info;
  3074. std::size_t size;
  3075. // Initialize the flags so that, if sysctl fails for some bizarre
  3076. // reason, we get a predictable result.
  3077. info.kp_proc.p_flag = 0;
  3078. // Initialize mib, which tells sysctl the info we want, in this case
  3079. // we're looking for information about a specific process ID.
  3080. mib[0] = CTL_KERN;
  3081. mib[1] = KERN_PROC;
  3082. mib[2] = KERN_PROC_PID;
  3083. mib[3] = getpid();
  3084. // Call sysctl.
  3085. size = sizeof(info);
  3086. if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
  3087. Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n\n" << std::flush;
  3088. return false;
  3089. }
  3090. // We're being debugged if the P_TRACED flag is set.
  3091. return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
  3092. }
  3093. #else
  3094. bool isDebuggerActive() {
  3095. // We need to find another way to determine this for non-appleclang compilers on macOS
  3096. return false;
  3097. }
  3098. #endif
  3099. } // namespace Catch
  3100. #elif defined(CATCH_PLATFORM_LINUX)
  3101. #include <fstream>
  3102. #include <string>
  3103. namespace Catch{
  3104. // The standard POSIX way of detecting a debugger is to attempt to
  3105. // ptrace() the process, but this needs to be done from a child and not
  3106. // this process itself to still allow attaching to this process later
  3107. // if wanted, so is rather heavy. Under Linux we have the PID of the
  3108. // "debugger" (which doesn't need to be gdb, of course, it could also
  3109. // be strace, for example) in /proc/$PID/status, so just get it from
  3110. // there instead.
  3111. bool isDebuggerActive(){
  3112. // Libstdc++ has a bug, where std::ifstream sets errno to 0
  3113. // This way our users can properly assert over errno values
  3114. ErrnoGuard guard;
  3115. std::ifstream in("/proc/self/status");
  3116. for( std::string line; std::getline(in, line); ) {
  3117. static const int PREFIX_LEN = 11;
  3118. if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
  3119. // We're traced if the PID is not 0 and no other PID starts
  3120. // with 0 digit, so it's enough to check for just a single
  3121. // character.
  3122. return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
  3123. }
  3124. }
  3125. return false;
  3126. }
  3127. } // namespace Catch
  3128. #elif defined(_MSC_VER)
  3129. extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
  3130. namespace Catch {
  3131. bool isDebuggerActive() {
  3132. return IsDebuggerPresent() != 0;
  3133. }
  3134. }
  3135. #elif defined(__MINGW32__)
  3136. extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
  3137. namespace Catch {
  3138. bool isDebuggerActive() {
  3139. return IsDebuggerPresent() != 0;
  3140. }
  3141. }
  3142. #else
  3143. namespace Catch {
  3144. bool isDebuggerActive() { return false; }
  3145. }
  3146. #endif // Platform
  3147. namespace Catch {
  3148. void ITransientExpression::streamReconstructedExpression(
  3149. std::ostream& os ) const {
  3150. // We can't make this function pure virtual to keep ITransientExpression
  3151. // constexpr, so we write error message instead
  3152. os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression";
  3153. }
  3154. void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
  3155. if( lhs.size() + rhs.size() < 40 &&
  3156. lhs.find('\n') == std::string::npos &&
  3157. rhs.find('\n') == std::string::npos )
  3158. os << lhs << ' ' << op << ' ' << rhs;
  3159. else
  3160. os << lhs << '\n' << op << '\n' << rhs;
  3161. }
  3162. }
  3163. #include <stdexcept>
  3164. namespace Catch {
  3165. #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
  3166. [[noreturn]]
  3167. void throw_exception(std::exception const& e) {
  3168. Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
  3169. << "The message was: " << e.what() << '\n';
  3170. std::terminate();
  3171. }
  3172. #endif
  3173. [[noreturn]]
  3174. void throw_logic_error(std::string const& msg) {
  3175. throw_exception(std::logic_error(msg));
  3176. }
  3177. [[noreturn]]
  3178. void throw_domain_error(std::string const& msg) {
  3179. throw_exception(std::domain_error(msg));
  3180. }
  3181. [[noreturn]]
  3182. void throw_runtime_error(std::string const& msg) {
  3183. throw_exception(std::runtime_error(msg));
  3184. }
  3185. } // namespace Catch;
  3186. #include <cassert>
  3187. namespace Catch {
  3188. IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() = default;
  3189. namespace Detail {
  3190. namespace {
  3191. // Extracts the actual name part of an enum instance
  3192. // In other words, it returns the Blue part of Bikeshed::Colour::Blue
  3193. StringRef extractInstanceName(StringRef enumInstance) {
  3194. // Find last occurrence of ":"
  3195. size_t name_start = enumInstance.size();
  3196. while (name_start > 0 && enumInstance[name_start - 1] != ':') {
  3197. --name_start;
  3198. }
  3199. return enumInstance.substr(name_start, enumInstance.size() - name_start);
  3200. }
  3201. }
  3202. std::vector<StringRef> parseEnums( StringRef enums ) {
  3203. auto enumValues = splitStringRef( enums, ',' );
  3204. std::vector<StringRef> parsed;
  3205. parsed.reserve( enumValues.size() );
  3206. for( auto const& enumValue : enumValues ) {
  3207. parsed.push_back(trim(extractInstanceName(enumValue)));
  3208. }
  3209. return parsed;
  3210. }
  3211. EnumInfo::~EnumInfo() = default;
  3212. StringRef EnumInfo::lookup( int value ) const {
  3213. for( auto const& valueToName : m_values ) {
  3214. if( valueToName.first == value )
  3215. return valueToName.second;
  3216. }
  3217. return "{** unexpected enum value **}"_sr;
  3218. }
  3219. Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
  3220. auto enumInfo = Catch::Detail::make_unique<EnumInfo>();
  3221. enumInfo->m_name = enumName;
  3222. enumInfo->m_values.reserve( values.size() );
  3223. const auto valueNames = Catch::Detail::parseEnums( allValueNames );
  3224. assert( valueNames.size() == values.size() );
  3225. std::size_t i = 0;
  3226. for( auto value : values )
  3227. enumInfo->m_values.emplace_back(value, valueNames[i++]);
  3228. return enumInfo;
  3229. }
  3230. EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
  3231. m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
  3232. return *m_enumInfos.back();
  3233. }
  3234. } // Detail
  3235. } // Catch
  3236. #include <cerrno>
  3237. namespace Catch {
  3238. ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
  3239. ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
  3240. }
  3241. #include <exception>
  3242. namespace Catch {
  3243. #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  3244. namespace {
  3245. static std::string tryTranslators(
  3246. std::vector<
  3247. Detail::unique_ptr<IExceptionTranslator const>> const& translators ) {
  3248. if ( translators.empty() ) {
  3249. std::rethrow_exception( std::current_exception() );
  3250. } else {
  3251. return translators[0]->translate( translators.begin() + 1,
  3252. translators.end() );
  3253. }
  3254. }
  3255. }
  3256. #endif //!defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  3257. ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() = default;
  3258. void ExceptionTranslatorRegistry::registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) {
  3259. m_translators.push_back( CATCH_MOVE( translator ) );
  3260. }
  3261. #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  3262. std::string ExceptionTranslatorRegistry::translateActiveException() const {
  3263. // Compiling a mixed mode project with MSVC means that CLR
  3264. // exceptions will be caught in (...) as well. However, these do
  3265. // do not fill-in std::current_exception and thus lead to crash
  3266. // when attempting rethrow.
  3267. // /EHa switch also causes structured exceptions to be caught
  3268. // here, but they fill-in current_exception properly, so
  3269. // at worst the output should be a little weird, instead of
  3270. // causing a crash.
  3271. if ( std::current_exception() == nullptr ) {
  3272. return "Non C++ exception. Possibly a CLR exception.";
  3273. }
  3274. // First we try user-registered translators. If none of them can
  3275. // handle the exception, it will be rethrown handled by our defaults.
  3276. try {
  3277. return tryTranslators(m_translators);
  3278. }
  3279. // To avoid having to handle TFE explicitly everywhere, we just
  3280. // rethrow it so that it goes back up the caller.
  3281. catch( TestFailureException& ) {
  3282. std::rethrow_exception(std::current_exception());
  3283. }
  3284. catch( TestSkipException& ) {
  3285. std::rethrow_exception(std::current_exception());
  3286. }
  3287. catch( std::exception const& ex ) {
  3288. return ex.what();
  3289. }
  3290. catch( std::string const& msg ) {
  3291. return msg;
  3292. }
  3293. catch( const char* msg ) {
  3294. return msg;
  3295. }
  3296. catch(...) {
  3297. return "Unknown exception";
  3298. }
  3299. }
  3300. #else // ^^ Exceptions are enabled // Exceptions are disabled vv
  3301. std::string ExceptionTranslatorRegistry::translateActiveException() const {
  3302. CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
  3303. }
  3304. #endif
  3305. }
  3306. /** \file
  3307. * This file provides platform specific implementations of FatalConditionHandler
  3308. *
  3309. * This means that there is a lot of conditional compilation, and platform
  3310. * specific code. Currently, Catch2 supports a dummy handler (if no
  3311. * handler is desired), and 2 platform specific handlers:
  3312. * * Windows' SEH
  3313. * * POSIX signals
  3314. *
  3315. * Consequently, various pieces of code below are compiled if either of
  3316. * the platform specific handlers is enabled, or if none of them are
  3317. * enabled. It is assumed that both cannot be enabled at the same time,
  3318. * and doing so should cause a compilation error.
  3319. *
  3320. * If another platform specific handler is added, the compile guards
  3321. * below will need to be updated taking these assumptions into account.
  3322. */
  3323. #include <algorithm>
  3324. #if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
  3325. namespace Catch {
  3326. // If neither SEH nor signal handling is required, the handler impls
  3327. // do not have to do anything, and can be empty.
  3328. void FatalConditionHandler::engage_platform() {}
  3329. void FatalConditionHandler::disengage_platform() noexcept {}
  3330. FatalConditionHandler::FatalConditionHandler() = default;
  3331. FatalConditionHandler::~FatalConditionHandler() = default;
  3332. } // end namespace Catch
  3333. #endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
  3334. #if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
  3335. #error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
  3336. #endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
  3337. #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
  3338. namespace {
  3339. //! Signals fatal error message to the run context
  3340. void reportFatal( char const * const message ) {
  3341. Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
  3342. }
  3343. //! Minimal size Catch2 needs for its own fatal error handling.
  3344. //! Picked empirically, so it might not be sufficient on all
  3345. //! platforms, and for all configurations.
  3346. constexpr std::size_t minStackSizeForErrors = 32 * 1024;
  3347. } // end unnamed namespace
  3348. #endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
  3349. #if defined( CATCH_CONFIG_WINDOWS_SEH )
  3350. namespace Catch {
  3351. struct SignalDefs { DWORD id; const char* name; };
  3352. // There is no 1-1 mapping between signals and windows exceptions.
  3353. // Windows can easily distinguish between SO and SigSegV,
  3354. // but SigInt, SigTerm, etc are handled differently.
  3355. static SignalDefs signalDefs[] = {
  3356. { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
  3357. { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
  3358. { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
  3359. { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
  3360. };
  3361. static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
  3362. for (auto const& def : signalDefs) {
  3363. if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
  3364. reportFatal(def.name);
  3365. }
  3366. }
  3367. // If its not an exception we care about, pass it along.
  3368. // This stops us from eating debugger breaks etc.
  3369. return EXCEPTION_CONTINUE_SEARCH;
  3370. }
  3371. // Since we do not support multiple instantiations, we put these
  3372. // into global variables and rely on cleaning them up in outlined
  3373. // constructors/destructors
  3374. static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr;
  3375. // For MSVC, we reserve part of the stack memory for handling
  3376. // memory overflow structured exception.
  3377. FatalConditionHandler::FatalConditionHandler() {
  3378. ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
  3379. if (!SetThreadStackGuarantee(&guaranteeSize)) {
  3380. // We do not want to fully error out, because needing
  3381. // the stack reserve should be rare enough anyway.
  3382. Catch::cerr()
  3383. << "Failed to reserve piece of stack."
  3384. << " Stack overflows will not be reported successfully.";
  3385. }
  3386. }
  3387. // We do not attempt to unset the stack guarantee, because
  3388. // Windows does not support lowering the stack size guarantee.
  3389. FatalConditionHandler::~FatalConditionHandler() = default;
  3390. void FatalConditionHandler::engage_platform() {
  3391. // Register as a the top level exception filter.
  3392. previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
  3393. }
  3394. void FatalConditionHandler::disengage_platform() noexcept {
  3395. if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) {
  3396. Catch::cerr()
  3397. << "Unexpected SEH unhandled exception filter on disengage."
  3398. << " The filter was restored, but might be rolled back unexpectedly.";
  3399. }
  3400. previousTopLevelExceptionFilter = nullptr;
  3401. }
  3402. } // end namespace Catch
  3403. #endif // CATCH_CONFIG_WINDOWS_SEH
  3404. #if defined( CATCH_CONFIG_POSIX_SIGNALS )
  3405. #include <signal.h>
  3406. namespace Catch {
  3407. struct SignalDefs {
  3408. int id;
  3409. const char* name;
  3410. };
  3411. static SignalDefs signalDefs[] = {
  3412. { SIGINT, "SIGINT - Terminal interrupt signal" },
  3413. { SIGILL, "SIGILL - Illegal instruction signal" },
  3414. { SIGFPE, "SIGFPE - Floating point error signal" },
  3415. { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
  3416. { SIGTERM, "SIGTERM - Termination request signal" },
  3417. { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
  3418. };
  3419. // Older GCCs trigger -Wmissing-field-initializers for T foo = {}
  3420. // which is zero initialization, but not explicit. We want to avoid
  3421. // that.
  3422. #if defined(__GNUC__)
  3423. # pragma GCC diagnostic push
  3424. # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
  3425. #endif
  3426. static char* altStackMem = nullptr;
  3427. static std::size_t altStackSize = 0;
  3428. static stack_t oldSigStack{};
  3429. static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
  3430. static void restorePreviousSignalHandlers() noexcept {
  3431. // We set signal handlers back to the previous ones. Hopefully
  3432. // nobody overwrote them in the meantime, and doesn't expect
  3433. // their signal handlers to live past ours given that they
  3434. // installed them after ours..
  3435. for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
  3436. sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
  3437. }
  3438. // Return the old stack
  3439. sigaltstack(&oldSigStack, nullptr);
  3440. }
  3441. static void handleSignal( int sig ) {
  3442. char const * name = "<unknown signal>";
  3443. for (auto const& def : signalDefs) {
  3444. if (sig == def.id) {
  3445. name = def.name;
  3446. break;
  3447. }
  3448. }
  3449. // We need to restore previous signal handlers and let them do
  3450. // their thing, so that the users can have the debugger break
  3451. // when a signal is raised, and so on.
  3452. restorePreviousSignalHandlers();
  3453. reportFatal( name );
  3454. raise( sig );
  3455. }
  3456. FatalConditionHandler::FatalConditionHandler() {
  3457. assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
  3458. if (altStackSize == 0) {
  3459. altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
  3460. }
  3461. altStackMem = new char[altStackSize]();
  3462. }
  3463. FatalConditionHandler::~FatalConditionHandler() {
  3464. delete[] altStackMem;
  3465. // We signal that another instance can be constructed by zeroing
  3466. // out the pointer.
  3467. altStackMem = nullptr;
  3468. }
  3469. void FatalConditionHandler::engage_platform() {
  3470. stack_t sigStack;
  3471. sigStack.ss_sp = altStackMem;
  3472. sigStack.ss_size = altStackSize;
  3473. sigStack.ss_flags = 0;
  3474. sigaltstack(&sigStack, &oldSigStack);
  3475. struct sigaction sa = { };
  3476. sa.sa_handler = handleSignal;
  3477. sa.sa_flags = SA_ONSTACK;
  3478. for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
  3479. sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
  3480. }
  3481. }
  3482. #if defined(__GNUC__)
  3483. # pragma GCC diagnostic pop
  3484. #endif
  3485. void FatalConditionHandler::disengage_platform() noexcept {
  3486. restorePreviousSignalHandlers();
  3487. }
  3488. } // end namespace Catch
  3489. #endif // CATCH_CONFIG_POSIX_SIGNALS
  3490. #include <cstring>
  3491. namespace Catch {
  3492. namespace Detail {
  3493. uint32_t convertToBits(float f) {
  3494. static_assert(sizeof(float) == sizeof(uint32_t), "Important ULP matcher assumption violated");
  3495. uint32_t i;
  3496. std::memcpy(&i, &f, sizeof(f));
  3497. return i;
  3498. }
  3499. uint64_t convertToBits(double d) {
  3500. static_assert(sizeof(double) == sizeof(uint64_t), "Important ULP matcher assumption violated");
  3501. uint64_t i;
  3502. std::memcpy(&i, &d, sizeof(d));
  3503. return i;
  3504. }
  3505. #if defined( __GNUC__ ) || defined( __clang__ )
  3506. # pragma GCC diagnostic push
  3507. # pragma GCC diagnostic ignored "-Wfloat-equal"
  3508. #endif
  3509. bool directCompare( float lhs, float rhs ) { return lhs == rhs; }
  3510. bool directCompare( double lhs, double rhs ) { return lhs == rhs; }
  3511. #if defined( __GNUC__ ) || defined( __clang__ )
  3512. # pragma GCC diagnostic pop
  3513. #endif
  3514. } // end namespace Detail
  3515. } // end namespace Catch
  3516. #include <cstdlib>
  3517. namespace Catch {
  3518. namespace Detail {
  3519. #if !defined (CATCH_CONFIG_GETENV)
  3520. char const* getEnv( char const* ) { return nullptr; }
  3521. #else
  3522. char const* getEnv( char const* varName ) {
  3523. # if defined( _MSC_VER )
  3524. # pragma warning( push )
  3525. # pragma warning( disable : 4996 ) // use getenv_s instead of getenv
  3526. # endif
  3527. return std::getenv( varName );
  3528. # if defined( _MSC_VER )
  3529. # pragma warning( pop )
  3530. # endif
  3531. }
  3532. #endif
  3533. } // namespace Detail
  3534. } // namespace Catch
  3535. #include <cstdio>
  3536. #include <fstream>
  3537. #include <sstream>
  3538. #include <vector>
  3539. namespace Catch {
  3540. Catch::IStream::~IStream() = default;
  3541. namespace Detail {
  3542. namespace {
  3543. template<typename WriterF, std::size_t bufferSize=256>
  3544. class StreamBufImpl final : public std::streambuf {
  3545. char data[bufferSize];
  3546. WriterF m_writer;
  3547. public:
  3548. StreamBufImpl() {
  3549. setp( data, data + sizeof(data) );
  3550. }
  3551. ~StreamBufImpl() noexcept override {
  3552. StreamBufImpl::sync();
  3553. }
  3554. private:
  3555. int overflow( int c ) override {
  3556. sync();
  3557. if( c != EOF ) {
  3558. if( pbase() == epptr() )
  3559. m_writer( std::string( 1, static_cast<char>( c ) ) );
  3560. else
  3561. sputc( static_cast<char>( c ) );
  3562. }
  3563. return 0;
  3564. }
  3565. int sync() override {
  3566. if( pbase() != pptr() ) {
  3567. m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
  3568. setp( pbase(), epptr() );
  3569. }
  3570. return 0;
  3571. }
  3572. };
  3573. ///////////////////////////////////////////////////////////////////////////
  3574. struct OutputDebugWriter {
  3575. void operator()( std::string const& str ) {
  3576. if ( !str.empty() ) {
  3577. writeToDebugConsole( str );
  3578. }
  3579. }
  3580. };
  3581. ///////////////////////////////////////////////////////////////////////////
  3582. class FileStream final : public IStream {
  3583. std::ofstream m_ofs;
  3584. public:
  3585. FileStream( std::string const& filename ) {
  3586. m_ofs.open( filename.c_str() );
  3587. CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' );
  3588. m_ofs << std::unitbuf;
  3589. }
  3590. public: // IStream
  3591. std::ostream& stream() override {
  3592. return m_ofs;
  3593. }
  3594. };
  3595. ///////////////////////////////////////////////////////////////////////////
  3596. class CoutStream final : public IStream {
  3597. std::ostream m_os;
  3598. public:
  3599. // Store the streambuf from cout up-front because
  3600. // cout may get redirected when running tests
  3601. CoutStream() : m_os( Catch::cout().rdbuf() ) {}
  3602. public: // IStream
  3603. std::ostream& stream() override { return m_os; }
  3604. bool isConsole() const override { return true; }
  3605. };
  3606. class CerrStream : public IStream {
  3607. std::ostream m_os;
  3608. public:
  3609. // Store the streambuf from cerr up-front because
  3610. // cout may get redirected when running tests
  3611. CerrStream(): m_os( Catch::cerr().rdbuf() ) {}
  3612. public: // IStream
  3613. std::ostream& stream() override { return m_os; }
  3614. bool isConsole() const override { return true; }
  3615. };
  3616. ///////////////////////////////////////////////////////////////////////////
  3617. class DebugOutStream final : public IStream {
  3618. Detail::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
  3619. std::ostream m_os;
  3620. public:
  3621. DebugOutStream()
  3622. : m_streamBuf( Detail::make_unique<StreamBufImpl<OutputDebugWriter>>() ),
  3623. m_os( m_streamBuf.get() )
  3624. {}
  3625. public: // IStream
  3626. std::ostream& stream() override { return m_os; }
  3627. };
  3628. } // unnamed namespace
  3629. } // namespace Detail
  3630. ///////////////////////////////////////////////////////////////////////////
  3631. auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream> {
  3632. if ( filename.empty() || filename == "-" ) {
  3633. return Detail::make_unique<Detail::CoutStream>();
  3634. }
  3635. if( filename[0] == '%' ) {
  3636. if ( filename == "%debug" ) {
  3637. return Detail::make_unique<Detail::DebugOutStream>();
  3638. } else if ( filename == "%stderr" ) {
  3639. return Detail::make_unique<Detail::CerrStream>();
  3640. } else if ( filename == "%stdout" ) {
  3641. return Detail::make_unique<Detail::CoutStream>();
  3642. } else {
  3643. CATCH_ERROR( "Unrecognised stream: '" << filename << '\'' );
  3644. }
  3645. }
  3646. return Detail::make_unique<Detail::FileStream>( filename );
  3647. }
  3648. }
  3649. namespace Catch {
  3650. void JsonUtils::indent( std::ostream& os, std::uint64_t level ) {
  3651. for ( std::uint64_t i = 0; i < level; ++i ) {
  3652. os << " ";
  3653. }
  3654. }
  3655. void JsonUtils::appendCommaNewline( std::ostream& os,
  3656. bool& should_comma,
  3657. std::uint64_t level ) {
  3658. if ( should_comma ) { os << ','; }
  3659. should_comma = true;
  3660. os << '\n';
  3661. indent( os, level );
  3662. }
  3663. JsonObjectWriter::JsonObjectWriter( std::ostream& os ):
  3664. JsonObjectWriter{ os, 0 } {}
  3665. JsonObjectWriter::JsonObjectWriter( std::ostream& os,
  3666. std::uint64_t indent_level ):
  3667. m_os{ os }, m_indent_level{ indent_level } {
  3668. m_os << '{';
  3669. }
  3670. JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ) noexcept:
  3671. m_os{ source.m_os },
  3672. m_indent_level{ source.m_indent_level },
  3673. m_should_comma{ source.m_should_comma },
  3674. m_active{ source.m_active } {
  3675. source.m_active = false;
  3676. }
  3677. JsonObjectWriter::~JsonObjectWriter() {
  3678. if ( !m_active ) { return; }
  3679. m_os << '\n';
  3680. JsonUtils::indent( m_os, m_indent_level );
  3681. m_os << '}';
  3682. }
  3683. JsonValueWriter JsonObjectWriter::write( StringRef key ) {
  3684. JsonUtils::appendCommaNewline(
  3685. m_os, m_should_comma, m_indent_level + 1 );
  3686. m_os << '"' << key << "\": ";
  3687. return JsonValueWriter{ m_os, m_indent_level + 1 };
  3688. }
  3689. JsonArrayWriter::JsonArrayWriter( std::ostream& os ):
  3690. JsonArrayWriter{ os, 0 } {}
  3691. JsonArrayWriter::JsonArrayWriter( std::ostream& os,
  3692. std::uint64_t indent_level ):
  3693. m_os{ os }, m_indent_level{ indent_level } {
  3694. m_os << '[';
  3695. }
  3696. JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ) noexcept:
  3697. m_os{ source.m_os },
  3698. m_indent_level{ source.m_indent_level },
  3699. m_should_comma{ source.m_should_comma },
  3700. m_active{ source.m_active } {
  3701. source.m_active = false;
  3702. }
  3703. JsonArrayWriter::~JsonArrayWriter() {
  3704. if ( !m_active ) { return; }
  3705. m_os << '\n';
  3706. JsonUtils::indent( m_os, m_indent_level );
  3707. m_os << ']';
  3708. }
  3709. JsonObjectWriter JsonArrayWriter::writeObject() {
  3710. JsonUtils::appendCommaNewline(
  3711. m_os, m_should_comma, m_indent_level + 1 );
  3712. return JsonObjectWriter{ m_os, m_indent_level + 1 };
  3713. }
  3714. JsonArrayWriter JsonArrayWriter::writeArray() {
  3715. JsonUtils::appendCommaNewline(
  3716. m_os, m_should_comma, m_indent_level + 1 );
  3717. return JsonArrayWriter{ m_os, m_indent_level + 1 };
  3718. }
  3719. JsonArrayWriter& JsonArrayWriter::write( bool value ) {
  3720. return writeImpl( value );
  3721. }
  3722. JsonValueWriter::JsonValueWriter( std::ostream& os ):
  3723. JsonValueWriter{ os, 0 } {}
  3724. JsonValueWriter::JsonValueWriter( std::ostream& os,
  3725. std::uint64_t indent_level ):
  3726. m_os{ os }, m_indent_level{ indent_level } {}
  3727. JsonObjectWriter JsonValueWriter::writeObject() && {
  3728. return JsonObjectWriter{ m_os, m_indent_level };
  3729. }
  3730. JsonArrayWriter JsonValueWriter::writeArray() && {
  3731. return JsonArrayWriter{ m_os, m_indent_level };
  3732. }
  3733. void JsonValueWriter::write( Catch::StringRef value ) && {
  3734. writeImpl( value, true );
  3735. }
  3736. void JsonValueWriter::write( bool value ) && {
  3737. writeImpl( value ? "true"_sr : "false"_sr, false );
  3738. }
  3739. void JsonValueWriter::writeImpl( Catch::StringRef value, bool quote ) {
  3740. if ( quote ) { m_os << '"'; }
  3741. for (char c : value) {
  3742. // Escape list taken from https://www.json.org/json-en.html,
  3743. // string definition.
  3744. // Note that while forward slash _can_ be escaped, it does
  3745. // not have to be, if JSON is not further embedded somewhere
  3746. // where forward slash is meaningful.
  3747. if ( c == '"' ) {
  3748. m_os << "\\\"";
  3749. } else if ( c == '\\' ) {
  3750. m_os << "\\\\";
  3751. } else if ( c == '\b' ) {
  3752. m_os << "\\b";
  3753. } else if ( c == '\f' ) {
  3754. m_os << "\\f";
  3755. } else if ( c == '\n' ) {
  3756. m_os << "\\n";
  3757. } else if ( c == '\r' ) {
  3758. m_os << "\\r";
  3759. } else if ( c == '\t' ) {
  3760. m_os << "\\t";
  3761. } else {
  3762. m_os << c;
  3763. }
  3764. }
  3765. if ( quote ) { m_os << '"'; }
  3766. }
  3767. } // namespace Catch
  3768. namespace Catch {
  3769. auto operator << (std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream& {
  3770. if (lazyExpr.m_isNegated)
  3771. os << '!';
  3772. if (lazyExpr) {
  3773. if (lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression())
  3774. os << '(' << *lazyExpr.m_transientExpression << ')';
  3775. else
  3776. os << *lazyExpr.m_transientExpression;
  3777. } else {
  3778. os << "{** error - unchecked empty expression requested **}";
  3779. }
  3780. return os;
  3781. }
  3782. } // namespace Catch
  3783. #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
  3784. #include <crtdbg.h>
  3785. namespace Catch {
  3786. LeakDetector::LeakDetector() {
  3787. int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  3788. flag |= _CRTDBG_LEAK_CHECK_DF;
  3789. flag |= _CRTDBG_ALLOC_MEM_DF;
  3790. _CrtSetDbgFlag(flag);
  3791. _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
  3792. _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  3793. // Change this to leaking allocation's number to break there
  3794. _CrtSetBreakAlloc(-1);
  3795. }
  3796. }
  3797. #else // ^^ Windows crt debug heap enabled // Windows crt debug heap disabled vv
  3798. Catch::LeakDetector::LeakDetector() = default;
  3799. #endif // CATCH_CONFIG_WINDOWS_CRTDBG
  3800. Catch::LeakDetector::~LeakDetector() {
  3801. Catch::cleanUp();
  3802. }
  3803. namespace Catch {
  3804. namespace {
  3805. void listTests(IEventListener& reporter, IConfig const& config) {
  3806. auto const& testSpec = config.testSpec();
  3807. auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
  3808. reporter.listTests(matchedTestCases);
  3809. }
  3810. void listTags(IEventListener& reporter, IConfig const& config) {
  3811. auto const& testSpec = config.testSpec();
  3812. std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
  3813. std::map<StringRef, TagInfo, Detail::CaseInsensitiveLess> tagCounts;
  3814. for (auto const& testCase : matchedTestCases) {
  3815. for (auto const& tagName : testCase.getTestCaseInfo().tags) {
  3816. auto it = tagCounts.find(tagName.original);
  3817. if (it == tagCounts.end())
  3818. it = tagCounts.insert(std::make_pair(tagName.original, TagInfo())).first;
  3819. it->second.add(tagName.original);
  3820. }
  3821. }
  3822. std::vector<TagInfo> infos; infos.reserve(tagCounts.size());
  3823. for (auto& tagc : tagCounts) {
  3824. infos.push_back(CATCH_MOVE(tagc.second));
  3825. }
  3826. reporter.listTags(infos);
  3827. }
  3828. void listReporters(IEventListener& reporter) {
  3829. std::vector<ReporterDescription> descriptions;
  3830. auto const& factories = getRegistryHub().getReporterRegistry().getFactories();
  3831. descriptions.reserve(factories.size());
  3832. for (auto const& fac : factories) {
  3833. descriptions.push_back({ fac.first, fac.second->getDescription() });
  3834. }
  3835. reporter.listReporters(descriptions);
  3836. }
  3837. void listListeners(IEventListener& reporter) {
  3838. std::vector<ListenerDescription> descriptions;
  3839. auto const& factories =
  3840. getRegistryHub().getReporterRegistry().getListeners();
  3841. descriptions.reserve( factories.size() );
  3842. for ( auto const& fac : factories ) {
  3843. descriptions.push_back( { fac->getName(), fac->getDescription() } );
  3844. }
  3845. reporter.listListeners( descriptions );
  3846. }
  3847. } // end anonymous namespace
  3848. void TagInfo::add( StringRef spelling ) {
  3849. ++count;
  3850. spellings.insert( spelling );
  3851. }
  3852. std::string TagInfo::all() const {
  3853. // 2 per tag for brackets '[' and ']'
  3854. size_t size = spellings.size() * 2;
  3855. for (auto const& spelling : spellings) {
  3856. size += spelling.size();
  3857. }
  3858. std::string out; out.reserve(size);
  3859. for (auto const& spelling : spellings) {
  3860. out += '[';
  3861. out += spelling;
  3862. out += ']';
  3863. }
  3864. return out;
  3865. }
  3866. bool list( IEventListener& reporter, Config const& config ) {
  3867. bool listed = false;
  3868. if (config.listTests()) {
  3869. listed = true;
  3870. listTests(reporter, config);
  3871. }
  3872. if (config.listTags()) {
  3873. listed = true;
  3874. listTags(reporter, config);
  3875. }
  3876. if (config.listReporters()) {
  3877. listed = true;
  3878. listReporters(reporter);
  3879. }
  3880. if ( config.listListeners() ) {
  3881. listed = true;
  3882. listListeners( reporter );
  3883. }
  3884. return listed;
  3885. }
  3886. } // end namespace Catch
  3887. namespace Catch {
  3888. CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
  3889. CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
  3890. static LeakDetector leakDetector;
  3891. CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
  3892. }
  3893. // Allow users of amalgamated .cpp file to remove our main and provide their own.
  3894. #if !defined(CATCH_AMALGAMATED_CUSTOM_MAIN)
  3895. #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
  3896. // Standard C/C++ Win32 Unicode wmain entry point
  3897. extern "C" int __cdecl wmain (int argc, wchar_t * argv[], wchar_t * []) {
  3898. #else
  3899. // Standard C/C++ main entry point
  3900. int main (int argc, char * argv[]) {
  3901. #endif
  3902. // We want to force the linker not to discard the global variable
  3903. // and its constructor, as it (optionally) registers leak detector
  3904. (void)&Catch::leakDetector;
  3905. return Catch::Session().run( argc, argv );
  3906. }
  3907. #endif // !defined(CATCH_AMALGAMATED_CUSTOM_MAIN
  3908. namespace Catch {
  3909. MessageInfo::MessageInfo( StringRef _macroName,
  3910. SourceLineInfo const& _lineInfo,
  3911. ResultWas::OfType _type )
  3912. : macroName( _macroName ),
  3913. lineInfo( _lineInfo ),
  3914. type( _type ),
  3915. sequence( ++globalCount )
  3916. {}
  3917. // This may need protecting if threading support is added
  3918. unsigned int MessageInfo::globalCount = 0;
  3919. } // end namespace Catch
  3920. #include <cstdio>
  3921. #include <cstring>
  3922. #include <iosfwd>
  3923. #include <sstream>
  3924. #if defined( CATCH_CONFIG_NEW_CAPTURE )
  3925. # if defined( _MSC_VER )
  3926. # include <io.h> //_dup and _dup2
  3927. # define dup _dup
  3928. # define dup2 _dup2
  3929. # define fileno _fileno
  3930. # else
  3931. # include <unistd.h> // dup and dup2
  3932. # endif
  3933. #endif
  3934. namespace Catch {
  3935. namespace {
  3936. //! A no-op implementation, used if no reporter wants output
  3937. //! redirection.
  3938. class NoopRedirect : public OutputRedirect {
  3939. void activateImpl() override {}
  3940. void deactivateImpl() override {}
  3941. std::string getStdout() override { return {}; }
  3942. std::string getStderr() override { return {}; }
  3943. void clearBuffers() override {}
  3944. };
  3945. /**
  3946. * Redirects specific stream's rdbuf with another's.
  3947. *
  3948. * Redirection can be stopped and started on-demand, assumes
  3949. * that the underlying stream's rdbuf aren't changed by other
  3950. * users.
  3951. */
  3952. class RedirectedStreamNew {
  3953. std::ostream& m_originalStream;
  3954. std::ostream& m_redirectionStream;
  3955. std::streambuf* m_prevBuf;
  3956. public:
  3957. RedirectedStreamNew( std::ostream& originalStream,
  3958. std::ostream& redirectionStream ):
  3959. m_originalStream( originalStream ),
  3960. m_redirectionStream( redirectionStream ),
  3961. m_prevBuf( m_originalStream.rdbuf() ) {}
  3962. void startRedirect() {
  3963. m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
  3964. }
  3965. void stopRedirect() { m_originalStream.rdbuf( m_prevBuf ); }
  3966. };
  3967. /**
  3968. * Redirects the `std::cout`, `std::cerr`, `std::clog` streams,
  3969. * but does not touch the actual `stdout`/`stderr` file descriptors.
  3970. */
  3971. class StreamRedirect : public OutputRedirect {
  3972. ReusableStringStream m_redirectedOut, m_redirectedErr;
  3973. RedirectedStreamNew m_cout, m_cerr, m_clog;
  3974. public:
  3975. StreamRedirect():
  3976. m_cout( Catch::cout(), m_redirectedOut.get() ),
  3977. m_cerr( Catch::cerr(), m_redirectedErr.get() ),
  3978. m_clog( Catch::clog(), m_redirectedErr.get() ) {}
  3979. void activateImpl() override {
  3980. m_cout.startRedirect();
  3981. m_cerr.startRedirect();
  3982. m_clog.startRedirect();
  3983. }
  3984. void deactivateImpl() override {
  3985. m_cout.stopRedirect();
  3986. m_cerr.stopRedirect();
  3987. m_clog.stopRedirect();
  3988. }
  3989. std::string getStdout() override { return m_redirectedOut.str(); }
  3990. std::string getStderr() override { return m_redirectedErr.str(); }
  3991. void clearBuffers() override {
  3992. m_redirectedOut.str( "" );
  3993. m_redirectedErr.str( "" );
  3994. }
  3995. };
  3996. #if defined( CATCH_CONFIG_NEW_CAPTURE )
  3997. // Windows's implementation of std::tmpfile is terrible (it tries
  3998. // to create a file inside system folder, thus requiring elevated
  3999. // privileges for the binary), so we have to use tmpnam(_s) and
  4000. // create the file ourselves there.
  4001. class TempFile {
  4002. public:
  4003. TempFile( TempFile const& ) = delete;
  4004. TempFile& operator=( TempFile const& ) = delete;
  4005. TempFile( TempFile&& ) = delete;
  4006. TempFile& operator=( TempFile&& ) = delete;
  4007. # if defined( _MSC_VER )
  4008. TempFile() {
  4009. if ( tmpnam_s( m_buffer ) ) {
  4010. CATCH_RUNTIME_ERROR( "Could not get a temp filename" );
  4011. }
  4012. if ( fopen_s( &m_file, m_buffer, "wb+" ) ) {
  4013. char buffer[100];
  4014. if ( strerror_s( buffer, errno ) ) {
  4015. CATCH_RUNTIME_ERROR(
  4016. "Could not translate errno to a string" );
  4017. }
  4018. CATCH_RUNTIME_ERROR( "Could not open the temp file: '"
  4019. << m_buffer
  4020. << "' because: " << buffer );
  4021. }
  4022. }
  4023. # else
  4024. TempFile() {
  4025. m_file = std::tmpfile();
  4026. if ( !m_file ) {
  4027. CATCH_RUNTIME_ERROR( "Could not create a temp file." );
  4028. }
  4029. }
  4030. # endif
  4031. ~TempFile() {
  4032. // TBD: What to do about errors here?
  4033. std::fclose( m_file );
  4034. // We manually create the file on Windows only, on Linux
  4035. // it will be autodeleted
  4036. # if defined( _MSC_VER )
  4037. std::remove( m_buffer );
  4038. # endif
  4039. }
  4040. std::FILE* getFile() { return m_file; }
  4041. std::string getContents() {
  4042. ReusableStringStream sstr;
  4043. constexpr long buffer_size = 100;
  4044. char buffer[buffer_size + 1] = {};
  4045. long current_pos = ftell( m_file );
  4046. CATCH_ENFORCE( current_pos >= 0,
  4047. "ftell failed, errno: " << errno );
  4048. std::rewind( m_file );
  4049. while ( current_pos > 0 ) {
  4050. auto read_characters =
  4051. std::fread( buffer,
  4052. 1,
  4053. std::min( buffer_size, current_pos ),
  4054. m_file );
  4055. buffer[read_characters] = '\0';
  4056. sstr << buffer;
  4057. current_pos -= static_cast<long>( read_characters );
  4058. }
  4059. return sstr.str();
  4060. }
  4061. void clear() { std::rewind( m_file ); }
  4062. private:
  4063. std::FILE* m_file = nullptr;
  4064. char m_buffer[L_tmpnam] = { 0 };
  4065. };
  4066. /**
  4067. * Redirects the actual `stdout`/`stderr` file descriptors.
  4068. *
  4069. * Works by replacing the file descriptors numbered 1 and 2
  4070. * with an open temporary file.
  4071. */
  4072. class FileRedirect : public OutputRedirect {
  4073. TempFile m_outFile, m_errFile;
  4074. int m_originalOut = -1;
  4075. int m_originalErr = -1;
  4076. // Flushes cout/cerr/clog streams and stdout/stderr FDs
  4077. void flushEverything() {
  4078. Catch::cout() << std::flush;
  4079. fflush( stdout );
  4080. // Since we support overriding these streams, we flush cerr
  4081. // even though std::cerr is unbuffered
  4082. Catch::cerr() << std::flush;
  4083. Catch::clog() << std::flush;
  4084. fflush( stderr );
  4085. }
  4086. public:
  4087. FileRedirect():
  4088. m_originalOut( dup( fileno( stdout ) ) ),
  4089. m_originalErr( dup( fileno( stderr ) ) ) {
  4090. CATCH_ENFORCE( m_originalOut >= 0, "Could not dup stdout" );
  4091. CATCH_ENFORCE( m_originalErr >= 0, "Could not dup stderr" );
  4092. }
  4093. std::string getStdout() override { return m_outFile.getContents(); }
  4094. std::string getStderr() override { return m_errFile.getContents(); }
  4095. void clearBuffers() override {
  4096. m_outFile.clear();
  4097. m_errFile.clear();
  4098. }
  4099. void activateImpl() override {
  4100. // We flush before starting redirect, to ensure that we do
  4101. // not capture the end of message sent before activation.
  4102. flushEverything();
  4103. int ret;
  4104. ret = dup2( fileno( m_outFile.getFile() ), fileno( stdout ) );
  4105. CATCH_ENFORCE( ret >= 0,
  4106. "dup2 to stdout has failed, errno: " << errno );
  4107. ret = dup2( fileno( m_errFile.getFile() ), fileno( stderr ) );
  4108. CATCH_ENFORCE( ret >= 0,
  4109. "dup2 to stderr has failed, errno: " << errno );
  4110. }
  4111. void deactivateImpl() override {
  4112. // We flush before ending redirect, to ensure that we
  4113. // capture all messages sent while the redirect was active.
  4114. flushEverything();
  4115. int ret;
  4116. ret = dup2( m_originalOut, fileno( stdout ) );
  4117. CATCH_ENFORCE(
  4118. ret >= 0,
  4119. "dup2 of original stdout has failed, errno: " << errno );
  4120. ret = dup2( m_originalErr, fileno( stderr ) );
  4121. CATCH_ENFORCE(
  4122. ret >= 0,
  4123. "dup2 of original stderr has failed, errno: " << errno );
  4124. }
  4125. };
  4126. #endif // CATCH_CONFIG_NEW_CAPTURE
  4127. } // end namespace
  4128. bool isRedirectAvailable( OutputRedirect::Kind kind ) {
  4129. switch ( kind ) {
  4130. // These two are always available
  4131. case OutputRedirect::None:
  4132. case OutputRedirect::Streams:
  4133. return true;
  4134. #if defined( CATCH_CONFIG_NEW_CAPTURE )
  4135. case OutputRedirect::FileDescriptors:
  4136. return true;
  4137. #endif
  4138. default:
  4139. return false;
  4140. }
  4141. }
  4142. Detail::unique_ptr<OutputRedirect> makeOutputRedirect( bool actual ) {
  4143. if ( actual ) {
  4144. // TODO: Clean this up later
  4145. #if defined( CATCH_CONFIG_NEW_CAPTURE )
  4146. return Detail::make_unique<FileRedirect>();
  4147. #else
  4148. return Detail::make_unique<StreamRedirect>();
  4149. #endif
  4150. } else {
  4151. return Detail::make_unique<NoopRedirect>();
  4152. }
  4153. }
  4154. RedirectGuard scopedActivate( OutputRedirect& redirectImpl ) {
  4155. return RedirectGuard( true, redirectImpl );
  4156. }
  4157. RedirectGuard scopedDeactivate( OutputRedirect& redirectImpl ) {
  4158. return RedirectGuard( false, redirectImpl );
  4159. }
  4160. OutputRedirect::~OutputRedirect() = default;
  4161. RedirectGuard::RedirectGuard( bool activate, OutputRedirect& redirectImpl ):
  4162. m_redirect( &redirectImpl ),
  4163. m_activate( activate ),
  4164. m_previouslyActive( redirectImpl.isActive() ) {
  4165. // Skip cases where there is no actual state change.
  4166. if ( m_activate == m_previouslyActive ) { return; }
  4167. if ( m_activate ) {
  4168. m_redirect->activate();
  4169. } else {
  4170. m_redirect->deactivate();
  4171. }
  4172. }
  4173. RedirectGuard::~RedirectGuard() noexcept( false ) {
  4174. if ( m_moved ) { return; }
  4175. // Skip cases where there is no actual state change.
  4176. if ( m_activate == m_previouslyActive ) { return; }
  4177. if ( m_activate ) {
  4178. m_redirect->deactivate();
  4179. } else {
  4180. m_redirect->activate();
  4181. }
  4182. }
  4183. RedirectGuard::RedirectGuard( RedirectGuard&& rhs ) noexcept:
  4184. m_redirect( rhs.m_redirect ),
  4185. m_activate( rhs.m_activate ),
  4186. m_previouslyActive( rhs.m_previouslyActive ),
  4187. m_moved( false ) {
  4188. rhs.m_moved = true;
  4189. }
  4190. RedirectGuard& RedirectGuard::operator=( RedirectGuard&& rhs ) noexcept {
  4191. m_redirect = rhs.m_redirect;
  4192. m_activate = rhs.m_activate;
  4193. m_previouslyActive = rhs.m_previouslyActive;
  4194. m_moved = false;
  4195. rhs.m_moved = true;
  4196. return *this;
  4197. }
  4198. } // namespace Catch
  4199. #if defined( CATCH_CONFIG_NEW_CAPTURE )
  4200. # if defined( _MSC_VER )
  4201. # undef dup
  4202. # undef dup2
  4203. # undef fileno
  4204. # endif
  4205. #endif
  4206. #include <limits>
  4207. #include <stdexcept>
  4208. namespace Catch {
  4209. Optional<unsigned int> parseUInt(std::string const& input, int base) {
  4210. auto trimmed = trim( input );
  4211. // std::stoull is annoying and accepts numbers starting with '-',
  4212. // it just negates them into unsigned int
  4213. if ( trimmed.empty() || trimmed[0] == '-' ) {
  4214. return {};
  4215. }
  4216. CATCH_TRY {
  4217. size_t pos = 0;
  4218. const auto ret = std::stoull( trimmed, &pos, base );
  4219. // We did not consume the whole input, so there is an issue
  4220. // This can be bunch of different stuff, like multiple numbers
  4221. // in the input, or invalid digits/characters and so on. Either
  4222. // way, we do not want to return the partially parsed result.
  4223. if ( pos != trimmed.size() ) {
  4224. return {};
  4225. }
  4226. // Too large
  4227. if ( ret > std::numeric_limits<unsigned int>::max() ) {
  4228. return {};
  4229. }
  4230. return static_cast<unsigned int>(ret);
  4231. }
  4232. CATCH_CATCH_ANON( std::invalid_argument const& ) {
  4233. // no conversion could be performed
  4234. }
  4235. CATCH_CATCH_ANON( std::out_of_range const& ) {
  4236. // the input does not fit into an unsigned long long
  4237. }
  4238. return {};
  4239. }
  4240. } // namespace Catch
  4241. #include <cmath>
  4242. namespace Catch {
  4243. #if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
  4244. bool isnan(float f) {
  4245. return std::isnan(f);
  4246. }
  4247. bool isnan(double d) {
  4248. return std::isnan(d);
  4249. }
  4250. #else
  4251. // For now we only use this for embarcadero
  4252. bool isnan(float f) {
  4253. return std::_isnan(f);
  4254. }
  4255. bool isnan(double d) {
  4256. return std::_isnan(d);
  4257. }
  4258. #endif
  4259. #if !defined( CATCH_CONFIG_GLOBAL_NEXTAFTER )
  4260. float nextafter( float x, float y ) { return std::nextafter( x, y ); }
  4261. double nextafter( double x, double y ) { return std::nextafter( x, y ); }
  4262. #else
  4263. float nextafter( float x, float y ) { return ::nextafterf( x, y ); }
  4264. double nextafter( double x, double y ) { return ::nextafter( x, y ); }
  4265. #endif
  4266. } // end namespace Catch
  4267. namespace Catch {
  4268. namespace {
  4269. #if defined(_MSC_VER)
  4270. #pragma warning(push)
  4271. #pragma warning(disable:4146) // we negate uint32 during the rotate
  4272. #endif
  4273. // Safe rotr implementation thanks to John Regehr
  4274. uint32_t rotate_right(uint32_t val, uint32_t count) {
  4275. const uint32_t mask = 31;
  4276. count &= mask;
  4277. return (val >> count) | (val << (-count & mask));
  4278. }
  4279. #if defined(_MSC_VER)
  4280. #pragma warning(pop)
  4281. #endif
  4282. }
  4283. SimplePcg32::SimplePcg32(result_type seed_) {
  4284. seed(seed_);
  4285. }
  4286. void SimplePcg32::seed(result_type seed_) {
  4287. m_state = 0;
  4288. (*this)();
  4289. m_state += seed_;
  4290. (*this)();
  4291. }
  4292. void SimplePcg32::discard(uint64_t skip) {
  4293. // We could implement this to run in O(log n) steps, but this
  4294. // should suffice for our use case.
  4295. for (uint64_t s = 0; s < skip; ++s) {
  4296. static_cast<void>((*this)());
  4297. }
  4298. }
  4299. SimplePcg32::result_type SimplePcg32::operator()() {
  4300. // prepare the output value
  4301. const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
  4302. const auto output = rotate_right(xorshifted, m_state >> 59u);
  4303. // advance state
  4304. m_state = m_state * 6364136223846793005ULL + s_inc;
  4305. return output;
  4306. }
  4307. bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
  4308. return lhs.m_state == rhs.m_state;
  4309. }
  4310. bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
  4311. return lhs.m_state != rhs.m_state;
  4312. }
  4313. }
  4314. #include <ctime>
  4315. #include <random>
  4316. namespace Catch {
  4317. std::uint32_t generateRandomSeed( GenerateFrom from ) {
  4318. switch ( from ) {
  4319. case GenerateFrom::Time:
  4320. return static_cast<std::uint32_t>( std::time( nullptr ) );
  4321. case GenerateFrom::Default:
  4322. case GenerateFrom::RandomDevice: {
  4323. std::random_device rd;
  4324. return Detail::fillBitsFrom<std::uint32_t>( rd );
  4325. }
  4326. default:
  4327. CATCH_ERROR("Unknown generation method");
  4328. }
  4329. }
  4330. } // end namespace Catch
  4331. namespace Catch {
  4332. struct ReporterRegistry::ReporterRegistryImpl {
  4333. std::vector<Detail::unique_ptr<EventListenerFactory>> listeners;
  4334. std::map<std::string, IReporterFactoryPtr, Detail::CaseInsensitiveLess>
  4335. factories;
  4336. };
  4337. ReporterRegistry::ReporterRegistry():
  4338. m_impl( Detail::make_unique<ReporterRegistryImpl>() ) {
  4339. // Because it is impossible to move out of initializer list,
  4340. // we have to add the elements manually
  4341. m_impl->factories["Automake"] =
  4342. Detail::make_unique<ReporterFactory<AutomakeReporter>>();
  4343. m_impl->factories["compact"] =
  4344. Detail::make_unique<ReporterFactory<CompactReporter>>();
  4345. m_impl->factories["console"] =
  4346. Detail::make_unique<ReporterFactory<ConsoleReporter>>();
  4347. m_impl->factories["JUnit"] =
  4348. Detail::make_unique<ReporterFactory<JunitReporter>>();
  4349. m_impl->factories["SonarQube"] =
  4350. Detail::make_unique<ReporterFactory<SonarQubeReporter>>();
  4351. m_impl->factories["TAP"] =
  4352. Detail::make_unique<ReporterFactory<TAPReporter>>();
  4353. m_impl->factories["TeamCity"] =
  4354. Detail::make_unique<ReporterFactory<TeamCityReporter>>();
  4355. m_impl->factories["XML"] =
  4356. Detail::make_unique<ReporterFactory<XmlReporter>>();
  4357. m_impl->factories["JSON"] =
  4358. Detail::make_unique<ReporterFactory<JsonReporter>>();
  4359. }
  4360. ReporterRegistry::~ReporterRegistry() = default;
  4361. IEventListenerPtr
  4362. ReporterRegistry::create( std::string const& name,
  4363. ReporterConfig&& config ) const {
  4364. auto it = m_impl->factories.find( name );
  4365. if ( it == m_impl->factories.end() ) return nullptr;
  4366. return it->second->create( CATCH_MOVE( config ) );
  4367. }
  4368. void ReporterRegistry::registerReporter( std::string const& name,
  4369. IReporterFactoryPtr factory ) {
  4370. CATCH_ENFORCE( name.find( "::" ) == name.npos,
  4371. "'::' is not allowed in reporter name: '" + name +
  4372. '\'' );
  4373. auto ret = m_impl->factories.emplace( name, CATCH_MOVE( factory ) );
  4374. CATCH_ENFORCE( ret.second,
  4375. "reporter using '" + name +
  4376. "' as name was already registered" );
  4377. }
  4378. void ReporterRegistry::registerListener(
  4379. Detail::unique_ptr<EventListenerFactory> factory ) {
  4380. m_impl->listeners.push_back( CATCH_MOVE( factory ) );
  4381. }
  4382. std::map<std::string,
  4383. IReporterFactoryPtr,
  4384. Detail::CaseInsensitiveLess> const&
  4385. ReporterRegistry::getFactories() const {
  4386. return m_impl->factories;
  4387. }
  4388. std::vector<Detail::unique_ptr<EventListenerFactory>> const&
  4389. ReporterRegistry::getListeners() const {
  4390. return m_impl->listeners;
  4391. }
  4392. } // namespace Catch
  4393. #include <algorithm>
  4394. namespace Catch {
  4395. namespace {
  4396. struct kvPair {
  4397. StringRef key, value;
  4398. };
  4399. kvPair splitKVPair(StringRef kvString) {
  4400. auto splitPos = static_cast<size_t>(
  4401. std::find( kvString.begin(), kvString.end(), '=' ) -
  4402. kvString.begin() );
  4403. return { kvString.substr( 0, splitPos ),
  4404. kvString.substr( splitPos + 1, kvString.size() ) };
  4405. }
  4406. }
  4407. namespace Detail {
  4408. std::vector<std::string> splitReporterSpec( StringRef reporterSpec ) {
  4409. static constexpr auto separator = "::";
  4410. static constexpr size_t separatorSize = 2;
  4411. size_t separatorPos = 0;
  4412. auto findNextSeparator = [&reporterSpec]( size_t startPos ) {
  4413. static_assert(
  4414. separatorSize == 2,
  4415. "The code below currently assumes 2 char separator" );
  4416. auto currentPos = startPos;
  4417. do {
  4418. while ( currentPos < reporterSpec.size() &&
  4419. reporterSpec[currentPos] != separator[0] ) {
  4420. ++currentPos;
  4421. }
  4422. if ( currentPos + 1 < reporterSpec.size() &&
  4423. reporterSpec[currentPos + 1] == separator[1] ) {
  4424. return currentPos;
  4425. }
  4426. ++currentPos;
  4427. } while ( currentPos < reporterSpec.size() );
  4428. return static_cast<size_t>( -1 );
  4429. };
  4430. std::vector<std::string> parts;
  4431. while ( separatorPos < reporterSpec.size() ) {
  4432. const auto nextSeparator = findNextSeparator( separatorPos );
  4433. parts.push_back( static_cast<std::string>( reporterSpec.substr(
  4434. separatorPos, nextSeparator - separatorPos ) ) );
  4435. if ( nextSeparator == static_cast<size_t>( -1 ) ) {
  4436. break;
  4437. }
  4438. separatorPos = nextSeparator + separatorSize;
  4439. }
  4440. // Handle a separator at the end.
  4441. // This is not a valid spec, but we want to do validation in a
  4442. // centralized place
  4443. if ( separatorPos == reporterSpec.size() ) {
  4444. parts.emplace_back();
  4445. }
  4446. return parts;
  4447. }
  4448. Optional<ColourMode> stringToColourMode( StringRef colourMode ) {
  4449. if ( colourMode == "default" ) {
  4450. return ColourMode::PlatformDefault;
  4451. } else if ( colourMode == "ansi" ) {
  4452. return ColourMode::ANSI;
  4453. } else if ( colourMode == "win32" ) {
  4454. return ColourMode::Win32;
  4455. } else if ( colourMode == "none" ) {
  4456. return ColourMode::None;
  4457. } else {
  4458. return {};
  4459. }
  4460. }
  4461. } // namespace Detail
  4462. bool operator==( ReporterSpec const& lhs, ReporterSpec const& rhs ) {
  4463. return lhs.m_name == rhs.m_name &&
  4464. lhs.m_outputFileName == rhs.m_outputFileName &&
  4465. lhs.m_colourMode == rhs.m_colourMode &&
  4466. lhs.m_customOptions == rhs.m_customOptions;
  4467. }
  4468. Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ) {
  4469. auto parts = Detail::splitReporterSpec( reporterSpec );
  4470. assert( parts.size() > 0 && "Split should never return empty vector" );
  4471. std::map<std::string, std::string> kvPairs;
  4472. Optional<std::string> outputFileName;
  4473. Optional<ColourMode> colourMode;
  4474. // First part is always reporter name, so we skip it
  4475. for ( size_t i = 1; i < parts.size(); ++i ) {
  4476. auto kv = splitKVPair( parts[i] );
  4477. auto key = kv.key, value = kv.value;
  4478. if ( key.empty() || value.empty() ) { // NOLINT(bugprone-branch-clone)
  4479. return {};
  4480. } else if ( key[0] == 'X' ) {
  4481. // This is a reporter-specific option, we don't check these
  4482. // apart from basic sanity checks
  4483. if ( key.size() == 1 ) {
  4484. return {};
  4485. }
  4486. auto ret = kvPairs.emplace( std::string(kv.key), std::string(kv.value) );
  4487. if ( !ret.second ) {
  4488. // Duplicated key. We might want to handle this differently,
  4489. // e.g. by overwriting the existing value?
  4490. return {};
  4491. }
  4492. } else if ( key == "out" ) {
  4493. // Duplicated key
  4494. if ( outputFileName ) {
  4495. return {};
  4496. }
  4497. outputFileName = static_cast<std::string>( value );
  4498. } else if ( key == "colour-mode" ) {
  4499. // Duplicated key
  4500. if ( colourMode ) {
  4501. return {};
  4502. }
  4503. colourMode = Detail::stringToColourMode( value );
  4504. // Parsing failed
  4505. if ( !colourMode ) {
  4506. return {};
  4507. }
  4508. } else {
  4509. // Unrecognized option
  4510. return {};
  4511. }
  4512. }
  4513. return ReporterSpec{ CATCH_MOVE( parts[0] ),
  4514. CATCH_MOVE( outputFileName ),
  4515. CATCH_MOVE( colourMode ),
  4516. CATCH_MOVE( kvPairs ) };
  4517. }
  4518. ReporterSpec::ReporterSpec(
  4519. std::string name,
  4520. Optional<std::string> outputFileName,
  4521. Optional<ColourMode> colourMode,
  4522. std::map<std::string, std::string> customOptions ):
  4523. m_name( CATCH_MOVE( name ) ),
  4524. m_outputFileName( CATCH_MOVE( outputFileName ) ),
  4525. m_colourMode( CATCH_MOVE( colourMode ) ),
  4526. m_customOptions( CATCH_MOVE( customOptions ) ) {}
  4527. } // namespace Catch
  4528. #include <cstdio>
  4529. #include <sstream>
  4530. #include <vector>
  4531. namespace Catch {
  4532. // This class encapsulates the idea of a pool of ostringstreams that can be reused.
  4533. struct StringStreams {
  4534. std::vector<Detail::unique_ptr<std::ostringstream>> m_streams;
  4535. std::vector<std::size_t> m_unused;
  4536. std::ostringstream m_referenceStream; // Used for copy state/ flags from
  4537. auto add() -> std::size_t {
  4538. if( m_unused.empty() ) {
  4539. m_streams.push_back( Detail::make_unique<std::ostringstream>() );
  4540. return m_streams.size()-1;
  4541. }
  4542. else {
  4543. auto index = m_unused.back();
  4544. m_unused.pop_back();
  4545. return index;
  4546. }
  4547. }
  4548. void release( std::size_t index ) {
  4549. m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
  4550. m_unused.push_back(index);
  4551. }
  4552. };
  4553. ReusableStringStream::ReusableStringStream()
  4554. : m_index( Singleton<StringStreams>::getMutable().add() ),
  4555. m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
  4556. {}
  4557. ReusableStringStream::~ReusableStringStream() {
  4558. static_cast<std::ostringstream*>( m_oss )->str("");
  4559. m_oss->clear();
  4560. Singleton<StringStreams>::getMutable().release( m_index );
  4561. }
  4562. std::string ReusableStringStream::str() const {
  4563. return static_cast<std::ostringstream*>( m_oss )->str();
  4564. }
  4565. void ReusableStringStream::str( std::string const& str ) {
  4566. static_cast<std::ostringstream*>( m_oss )->str( str );
  4567. }
  4568. }
  4569. #include <cassert>
  4570. #include <algorithm>
  4571. namespace Catch {
  4572. namespace Generators {
  4573. namespace {
  4574. struct GeneratorTracker final : TestCaseTracking::TrackerBase,
  4575. IGeneratorTracker {
  4576. GeneratorBasePtr m_generator;
  4577. GeneratorTracker(
  4578. TestCaseTracking::NameAndLocation&& nameAndLocation,
  4579. TrackerContext& ctx,
  4580. ITracker* parent ):
  4581. TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {}
  4582. static GeneratorTracker*
  4583. acquire( TrackerContext& ctx,
  4584. TestCaseTracking::NameAndLocationRef const&
  4585. nameAndLocation ) {
  4586. GeneratorTracker* tracker;
  4587. ITracker& currentTracker = ctx.currentTracker();
  4588. // Under specific circumstances, the generator we want
  4589. // to acquire is also the current tracker. If this is
  4590. // the case, we have to avoid looking through current
  4591. // tracker's children, and instead return the current
  4592. // tracker.
  4593. // A case where this check is important is e.g.
  4594. // for (int i = 0; i < 5; ++i) {
  4595. // int n = GENERATE(1, 2);
  4596. // }
  4597. //
  4598. // without it, the code above creates 5 nested generators.
  4599. if ( currentTracker.nameAndLocation() == nameAndLocation ) {
  4600. auto thisTracker = currentTracker.parent()->findChild(
  4601. nameAndLocation );
  4602. assert( thisTracker );
  4603. assert( thisTracker->isGeneratorTracker() );
  4604. tracker = static_cast<GeneratorTracker*>( thisTracker );
  4605. } else if ( ITracker* childTracker =
  4606. currentTracker.findChild(
  4607. nameAndLocation ) ) {
  4608. assert( childTracker );
  4609. assert( childTracker->isGeneratorTracker() );
  4610. tracker =
  4611. static_cast<GeneratorTracker*>( childTracker );
  4612. } else {
  4613. return nullptr;
  4614. }
  4615. if ( !tracker->isComplete() ) { tracker->open(); }
  4616. return tracker;
  4617. }
  4618. // TrackerBase interface
  4619. bool isGeneratorTracker() const override { return true; }
  4620. auto hasGenerator() const -> bool override {
  4621. return !!m_generator;
  4622. }
  4623. void close() override {
  4624. TrackerBase::close();
  4625. // If a generator has a child (it is followed by a section)
  4626. // and none of its children have started, then we must wait
  4627. // until later to start consuming its values.
  4628. // This catches cases where `GENERATE` is placed between two
  4629. // `SECTION`s.
  4630. // **The check for m_children.empty cannot be removed**.
  4631. // doing so would break `GENERATE` _not_ followed by
  4632. // `SECTION`s.
  4633. const bool should_wait_for_child = [&]() {
  4634. // No children -> nobody to wait for
  4635. if ( m_children.empty() ) { return false; }
  4636. // If at least one child started executing, don't wait
  4637. if ( std::find_if(
  4638. m_children.begin(),
  4639. m_children.end(),
  4640. []( TestCaseTracking::ITrackerPtr const&
  4641. tracker ) {
  4642. return tracker->hasStarted();
  4643. } ) != m_children.end() ) {
  4644. return false;
  4645. }
  4646. // No children have started. We need to check if they
  4647. // _can_ start, and thus we should wait for them, or
  4648. // they cannot start (due to filters), and we shouldn't
  4649. // wait for them
  4650. ITracker* parent = m_parent;
  4651. // This is safe: there is always at least one section
  4652. // tracker in a test case tracking tree
  4653. while ( !parent->isSectionTracker() ) {
  4654. parent = parent->parent();
  4655. }
  4656. assert( parent &&
  4657. "Missing root (test case) level section" );
  4658. auto const& parentSection =
  4659. static_cast<SectionTracker const&>( *parent );
  4660. auto const& filters = parentSection.getFilters();
  4661. // No filters -> no restrictions on running sections
  4662. if ( filters.empty() ) { return true; }
  4663. for ( auto const& child : m_children ) {
  4664. if ( child->isSectionTracker() &&
  4665. std::find( filters.begin(),
  4666. filters.end(),
  4667. static_cast<SectionTracker const&>(
  4668. *child )
  4669. .trimmedName() ) !=
  4670. filters.end() ) {
  4671. return true;
  4672. }
  4673. }
  4674. return false;
  4675. }();
  4676. // This check is a bit tricky, because m_generator->next()
  4677. // has a side-effect, where it consumes generator's current
  4678. // value, but we do not want to invoke the side-effect if
  4679. // this generator is still waiting for any child to start.
  4680. assert( m_generator && "Tracker without generator" );
  4681. if ( should_wait_for_child ||
  4682. ( m_runState == CompletedSuccessfully &&
  4683. m_generator->countedNext() ) ) {
  4684. m_children.clear();
  4685. m_runState = Executing;
  4686. }
  4687. }
  4688. // IGeneratorTracker interface
  4689. auto getGenerator() const -> GeneratorBasePtr const& override {
  4690. return m_generator;
  4691. }
  4692. void setGenerator( GeneratorBasePtr&& generator ) override {
  4693. m_generator = CATCH_MOVE( generator );
  4694. }
  4695. };
  4696. } // namespace
  4697. }
  4698. RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter)
  4699. : m_runInfo(_config->name()),
  4700. m_config(_config),
  4701. m_reporter(CATCH_MOVE(reporter)),
  4702. m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
  4703. m_outputRedirect( makeOutputRedirect( m_reporter->getPreferences().shouldRedirectStdOut ) ),
  4704. m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
  4705. {
  4706. getCurrentMutableContext().setResultCapture( this );
  4707. m_reporter->testRunStarting(m_runInfo);
  4708. }
  4709. RunContext::~RunContext() {
  4710. m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
  4711. }
  4712. Totals RunContext::runTest(TestCaseHandle const& testCase) {
  4713. const Totals prevTotals = m_totals;
  4714. auto const& testInfo = testCase.getTestCaseInfo();
  4715. m_reporter->testCaseStarting(testInfo);
  4716. testCase.prepareTestCase();
  4717. m_activeTestCase = &testCase;
  4718. ITracker& rootTracker = m_trackerContext.startRun();
  4719. assert(rootTracker.isSectionTracker());
  4720. static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
  4721. // We intentionally only seed the internal RNG once per test case,
  4722. // before it is first invoked. The reason for that is a complex
  4723. // interplay of generator/section implementation details and the
  4724. // Random*Generator types.
  4725. //
  4726. // The issue boils down to us needing to seed the Random*Generators
  4727. // with different seed each, so that they return different sequences
  4728. // of random numbers. We do this by giving them a number from the
  4729. // shared RNG instance as their seed.
  4730. //
  4731. // However, this runs into an issue if the reseeding happens each
  4732. // time the test case is entered (as opposed to first time only),
  4733. // because multiple generators could get the same seed, e.g. in
  4734. // ```cpp
  4735. // TEST_CASE() {
  4736. // auto i = GENERATE(take(10, random(0, 100));
  4737. // SECTION("A") {
  4738. // auto j = GENERATE(take(10, random(0, 100));
  4739. // }
  4740. // SECTION("B") {
  4741. // auto k = GENERATE(take(10, random(0, 100));
  4742. // }
  4743. // }
  4744. // ```
  4745. // `i` and `j` would properly return values from different sequences,
  4746. // but `i` and `k` would return the same sequence, because their seed
  4747. // would be the same.
  4748. // (The reason their seeds would be the same is that the generator
  4749. // for k would be initialized when the test case is entered the second
  4750. // time, after the shared RNG instance was reset to the same value
  4751. // it had when the generator for i was initialized.)
  4752. seedRng( *m_config );
  4753. uint64_t testRuns = 0;
  4754. std::string redirectedCout;
  4755. std::string redirectedCerr;
  4756. do {
  4757. m_trackerContext.startCycle();
  4758. m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo));
  4759. m_reporter->testCasePartialStarting(testInfo, testRuns);
  4760. const auto beforeRunTotals = m_totals;
  4761. runCurrentTest();
  4762. std::string oneRunCout = m_outputRedirect->getStdout();
  4763. std::string oneRunCerr = m_outputRedirect->getStderr();
  4764. m_outputRedirect->clearBuffers();
  4765. redirectedCout += oneRunCout;
  4766. redirectedCerr += oneRunCerr;
  4767. const auto singleRunTotals = m_totals.delta(beforeRunTotals);
  4768. auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
  4769. m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
  4770. ++testRuns;
  4771. } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
  4772. Totals deltaTotals = m_totals.delta(prevTotals);
  4773. if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
  4774. deltaTotals.assertions.failed++;
  4775. deltaTotals.testCases.passed--;
  4776. deltaTotals.testCases.failed++;
  4777. }
  4778. m_totals.testCases += deltaTotals.testCases;
  4779. testCase.tearDownTestCase();
  4780. m_reporter->testCaseEnded(TestCaseStats(testInfo,
  4781. deltaTotals,
  4782. CATCH_MOVE(redirectedCout),
  4783. CATCH_MOVE(redirectedCerr),
  4784. aborting()));
  4785. m_activeTestCase = nullptr;
  4786. m_testCaseTracker = nullptr;
  4787. return deltaTotals;
  4788. }
  4789. void RunContext::assertionEnded(AssertionResult&& result) {
  4790. if (result.getResultType() == ResultWas::Ok) {
  4791. m_totals.assertions.passed++;
  4792. m_lastAssertionPassed = true;
  4793. } else if (result.getResultType() == ResultWas::ExplicitSkip) {
  4794. m_totals.assertions.skipped++;
  4795. m_lastAssertionPassed = true;
  4796. } else if (!result.succeeded()) {
  4797. m_lastAssertionPassed = false;
  4798. if (result.isOk()) {
  4799. }
  4800. else if( m_activeTestCase->getTestCaseInfo().okToFail() )
  4801. m_totals.assertions.failedButOk++;
  4802. else
  4803. m_totals.assertions.failed++;
  4804. }
  4805. else {
  4806. m_lastAssertionPassed = true;
  4807. }
  4808. {
  4809. auto _ = scopedDeactivate( *m_outputRedirect );
  4810. m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) );
  4811. }
  4812. if ( result.getResultType() != ResultWas::Warning ) {
  4813. m_messageScopes.clear();
  4814. }
  4815. // Reset working state. assertion info will be reset after
  4816. // populateReaction is run if it is needed
  4817. m_lastResult = CATCH_MOVE( result );
  4818. }
  4819. void RunContext::resetAssertionInfo() {
  4820. m_lastAssertionInfo.macroName = StringRef();
  4821. m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
  4822. m_lastAssertionInfo.resultDisposition = ResultDisposition::Normal;
  4823. }
  4824. void RunContext::notifyAssertionStarted( AssertionInfo const& info ) {
  4825. auto _ = scopedDeactivate( *m_outputRedirect );
  4826. m_reporter->assertionStarting( info );
  4827. }
  4828. bool RunContext::sectionStarted( StringRef sectionName,
  4829. SourceLineInfo const& sectionLineInfo,
  4830. Counts& assertions ) {
  4831. ITracker& sectionTracker =
  4832. SectionTracker::acquire( m_trackerContext,
  4833. TestCaseTracking::NameAndLocationRef(
  4834. sectionName, sectionLineInfo ) );
  4835. if (!sectionTracker.isOpen())
  4836. return false;
  4837. m_activeSections.push_back(&sectionTracker);
  4838. SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
  4839. m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
  4840. {
  4841. auto _ = scopedDeactivate( *m_outputRedirect );
  4842. m_reporter->sectionStarting( sectionInfo );
  4843. }
  4844. assertions = m_totals.assertions;
  4845. return true;
  4846. }
  4847. IGeneratorTracker*
  4848. RunContext::acquireGeneratorTracker( StringRef generatorName,
  4849. SourceLineInfo const& lineInfo ) {
  4850. using namespace Generators;
  4851. GeneratorTracker* tracker = GeneratorTracker::acquire(
  4852. m_trackerContext,
  4853. TestCaseTracking::NameAndLocationRef(
  4854. generatorName, lineInfo ) );
  4855. m_lastAssertionInfo.lineInfo = lineInfo;
  4856. return tracker;
  4857. }
  4858. IGeneratorTracker* RunContext::createGeneratorTracker(
  4859. StringRef generatorName,
  4860. SourceLineInfo lineInfo,
  4861. Generators::GeneratorBasePtr&& generator ) {
  4862. auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast<std::string>( generatorName ), lineInfo );
  4863. auto& currentTracker = m_trackerContext.currentTracker();
  4864. assert(
  4865. currentTracker.nameAndLocation() != nameAndLoc &&
  4866. "Trying to create tracker for a genreator that already has one" );
  4867. auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
  4868. CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker );
  4869. auto ret = newTracker.get();
  4870. currentTracker.addChild( CATCH_MOVE( newTracker ) );
  4871. ret->setGenerator( CATCH_MOVE( generator ) );
  4872. ret->open();
  4873. return ret;
  4874. }
  4875. bool RunContext::testForMissingAssertions(Counts& assertions) {
  4876. if (assertions.total() != 0)
  4877. return false;
  4878. if (!m_config->warnAboutMissingAssertions())
  4879. return false;
  4880. if (m_trackerContext.currentTracker().hasChildren())
  4881. return false;
  4882. m_totals.assertions.failed++;
  4883. assertions.failed++;
  4884. return true;
  4885. }
  4886. void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
  4887. Counts assertions = m_totals.assertions - endInfo.prevAssertions;
  4888. bool missingAssertions = testForMissingAssertions(assertions);
  4889. if (!m_activeSections.empty()) {
  4890. m_activeSections.back()->close();
  4891. m_activeSections.pop_back();
  4892. }
  4893. {
  4894. auto _ = scopedDeactivate( *m_outputRedirect );
  4895. m_reporter->sectionEnded(
  4896. SectionStats( CATCH_MOVE( endInfo.sectionInfo ),
  4897. assertions,
  4898. endInfo.durationInSeconds,
  4899. missingAssertions ) );
  4900. }
  4901. m_messages.clear();
  4902. m_messageScopes.clear();
  4903. }
  4904. void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
  4905. if ( m_unfinishedSections.empty() ) {
  4906. m_activeSections.back()->fail();
  4907. } else {
  4908. m_activeSections.back()->close();
  4909. }
  4910. m_activeSections.pop_back();
  4911. m_unfinishedSections.push_back(CATCH_MOVE(endInfo));
  4912. }
  4913. void RunContext::benchmarkPreparing( StringRef name ) {
  4914. auto _ = scopedDeactivate( *m_outputRedirect );
  4915. m_reporter->benchmarkPreparing( name );
  4916. }
  4917. void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
  4918. auto _ = scopedDeactivate( *m_outputRedirect );
  4919. m_reporter->benchmarkStarting( info );
  4920. }
  4921. void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
  4922. auto _ = scopedDeactivate( *m_outputRedirect );
  4923. m_reporter->benchmarkEnded( stats );
  4924. }
  4925. void RunContext::benchmarkFailed( StringRef error ) {
  4926. auto _ = scopedDeactivate( *m_outputRedirect );
  4927. m_reporter->benchmarkFailed( error );
  4928. }
  4929. void RunContext::pushScopedMessage(MessageInfo const & message) {
  4930. m_messages.push_back(message);
  4931. }
  4932. void RunContext::popScopedMessage(MessageInfo const & message) {
  4933. m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
  4934. }
  4935. void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) {
  4936. m_messageScopes.emplace_back( CATCH_MOVE(builder) );
  4937. }
  4938. std::string RunContext::getCurrentTestName() const {
  4939. return m_activeTestCase
  4940. ? m_activeTestCase->getTestCaseInfo().name
  4941. : std::string();
  4942. }
  4943. const AssertionResult * RunContext::getLastResult() const {
  4944. return &(*m_lastResult);
  4945. }
  4946. void RunContext::exceptionEarlyReported() {
  4947. m_shouldReportUnexpected = false;
  4948. }
  4949. void RunContext::handleFatalErrorCondition( StringRef message ) {
  4950. // TODO: scoped deactivate here? Just give up and do best effort?
  4951. // the deactivation can break things further, OTOH so can the
  4952. // capture
  4953. auto _ = scopedDeactivate( *m_outputRedirect );
  4954. // First notify reporter that bad things happened
  4955. m_reporter->fatalErrorEncountered( message );
  4956. // Don't rebuild the result -- the stringification itself can cause more fatal errors
  4957. // Instead, fake a result data.
  4958. AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
  4959. tempResult.message = static_cast<std::string>(message);
  4960. AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult));
  4961. assertionEnded(CATCH_MOVE(result) );
  4962. resetAssertionInfo();
  4963. // Best effort cleanup for sections that have not been destructed yet
  4964. // Since this is a fatal error, we have not had and won't have the opportunity to destruct them properly
  4965. while (!m_activeSections.empty()) {
  4966. auto nl = m_activeSections.back()->nameAndLocation();
  4967. SectionEndInfo endInfo{ SectionInfo(CATCH_MOVE(nl.location), CATCH_MOVE(nl.name)), {}, 0.0 };
  4968. sectionEndedEarly(CATCH_MOVE(endInfo));
  4969. }
  4970. handleUnfinishedSections();
  4971. // Recreate section for test case (as we will lose the one that was in scope)
  4972. auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
  4973. SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
  4974. Counts assertions;
  4975. assertions.failed = 1;
  4976. SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false);
  4977. m_reporter->sectionEnded( testCaseSectionStats );
  4978. auto const& testInfo = m_activeTestCase->getTestCaseInfo();
  4979. Totals deltaTotals;
  4980. deltaTotals.testCases.failed = 1;
  4981. deltaTotals.assertions.failed = 1;
  4982. m_reporter->testCaseEnded(TestCaseStats(testInfo,
  4983. deltaTotals,
  4984. std::string(),
  4985. std::string(),
  4986. false));
  4987. m_totals.testCases.failed++;
  4988. m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
  4989. }
  4990. bool RunContext::lastAssertionPassed() {
  4991. return m_lastAssertionPassed;
  4992. }
  4993. void RunContext::assertionPassed() {
  4994. m_lastAssertionPassed = true;
  4995. ++m_totals.assertions.passed;
  4996. resetAssertionInfo();
  4997. m_messageScopes.clear();
  4998. }
  4999. bool RunContext::aborting() const {
  5000. return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
  5001. }
  5002. void RunContext::runCurrentTest() {
  5003. auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
  5004. SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
  5005. m_reporter->sectionStarting(testCaseSection);
  5006. Counts prevAssertions = m_totals.assertions;
  5007. double duration = 0;
  5008. m_shouldReportUnexpected = true;
  5009. m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
  5010. Timer timer;
  5011. CATCH_TRY {
  5012. {
  5013. auto _ = scopedActivate( *m_outputRedirect );
  5014. timer.start();
  5015. invokeActiveTestCase();
  5016. }
  5017. duration = timer.getElapsedSeconds();
  5018. } CATCH_CATCH_ANON (TestFailureException&) {
  5019. // This just means the test was aborted due to failure
  5020. } CATCH_CATCH_ANON (TestSkipException&) {
  5021. // This just means the test was explicitly skipped
  5022. } CATCH_CATCH_ALL {
  5023. // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
  5024. // are reported without translation at the point of origin.
  5025. if( m_shouldReportUnexpected ) {
  5026. AssertionReaction dummyReaction;
  5027. handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
  5028. }
  5029. }
  5030. Counts assertions = m_totals.assertions - prevAssertions;
  5031. bool missingAssertions = testForMissingAssertions(assertions);
  5032. m_testCaseTracker->close();
  5033. handleUnfinishedSections();
  5034. m_messages.clear();
  5035. m_messageScopes.clear();
  5036. SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions);
  5037. m_reporter->sectionEnded(testCaseSectionStats);
  5038. }
  5039. void RunContext::invokeActiveTestCase() {
  5040. // We need to engage a handler for signals/structured exceptions
  5041. // before running the tests themselves, or the binary can crash
  5042. // without failed test being reported.
  5043. FatalConditionHandlerGuard _(&m_fatalConditionhandler);
  5044. // We keep having issue where some compilers warn about an unused
  5045. // variable, even though the type has non-trivial constructor and
  5046. // destructor. This is annoying and ugly, but it makes them stfu.
  5047. (void)_;
  5048. m_activeTestCase->invoke();
  5049. }
  5050. void RunContext::handleUnfinishedSections() {
  5051. // If sections ended prematurely due to an exception we stored their
  5052. // infos here so we can tear them down outside the unwind process.
  5053. for ( auto it = m_unfinishedSections.rbegin(),
  5054. itEnd = m_unfinishedSections.rend();
  5055. it != itEnd;
  5056. ++it ) {
  5057. sectionEnded( CATCH_MOVE( *it ) );
  5058. }
  5059. m_unfinishedSections.clear();
  5060. }
  5061. void RunContext::handleExpr(
  5062. AssertionInfo const& info,
  5063. ITransientExpression const& expr,
  5064. AssertionReaction& reaction
  5065. ) {
  5066. bool negated = isFalseTest( info.resultDisposition );
  5067. bool result = expr.getResult() != negated;
  5068. if( result ) {
  5069. if (!m_includeSuccessfulResults) {
  5070. assertionPassed();
  5071. }
  5072. else {
  5073. reportExpr(info, ResultWas::Ok, &expr, negated);
  5074. }
  5075. }
  5076. else {
  5077. reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
  5078. populateReaction( reaction );
  5079. }
  5080. resetAssertionInfo();
  5081. }
  5082. void RunContext::reportExpr(
  5083. AssertionInfo const &info,
  5084. ResultWas::OfType resultType,
  5085. ITransientExpression const *expr,
  5086. bool negated ) {
  5087. m_lastAssertionInfo = info;
  5088. AssertionResultData data( resultType, LazyExpression( negated ) );
  5089. AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
  5090. assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
  5091. assertionEnded( CATCH_MOVE(assertionResult) );
  5092. }
  5093. void RunContext::handleMessage(
  5094. AssertionInfo const& info,
  5095. ResultWas::OfType resultType,
  5096. std::string&& message,
  5097. AssertionReaction& reaction
  5098. ) {
  5099. m_lastAssertionInfo = info;
  5100. AssertionResultData data( resultType, LazyExpression( false ) );
  5101. data.message = CATCH_MOVE( message );
  5102. AssertionResult assertionResult{ m_lastAssertionInfo,
  5103. CATCH_MOVE( data ) };
  5104. const auto isOk = assertionResult.isOk();
  5105. assertionEnded( CATCH_MOVE(assertionResult) );
  5106. if ( !isOk ) {
  5107. populateReaction( reaction );
  5108. } else if ( resultType == ResultWas::ExplicitSkip ) {
  5109. // TODO: Need to handle this explicitly, as ExplicitSkip is
  5110. // considered "OK"
  5111. reaction.shouldSkip = true;
  5112. }
  5113. resetAssertionInfo();
  5114. }
  5115. void RunContext::handleUnexpectedExceptionNotThrown(
  5116. AssertionInfo const& info,
  5117. AssertionReaction& reaction
  5118. ) {
  5119. handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
  5120. }
  5121. void RunContext::handleUnexpectedInflightException(
  5122. AssertionInfo const& info,
  5123. std::string&& message,
  5124. AssertionReaction& reaction
  5125. ) {
  5126. m_lastAssertionInfo = info;
  5127. AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
  5128. data.message = CATCH_MOVE(message);
  5129. AssertionResult assertionResult{ info, CATCH_MOVE(data) };
  5130. assertionEnded( CATCH_MOVE(assertionResult) );
  5131. populateReaction( reaction );
  5132. resetAssertionInfo();
  5133. }
  5134. void RunContext::populateReaction( AssertionReaction& reaction ) {
  5135. reaction.shouldDebugBreak = m_config->shouldDebugBreak();
  5136. reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
  5137. }
  5138. void RunContext::handleIncomplete(
  5139. AssertionInfo const& info
  5140. ) {
  5141. using namespace std::string_literals;
  5142. m_lastAssertionInfo = info;
  5143. AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
  5144. data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
  5145. AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
  5146. assertionEnded( CATCH_MOVE(assertionResult) );
  5147. resetAssertionInfo();
  5148. }
  5149. void RunContext::handleNonExpr(
  5150. AssertionInfo const &info,
  5151. ResultWas::OfType resultType,
  5152. AssertionReaction &reaction
  5153. ) {
  5154. m_lastAssertionInfo = info;
  5155. AssertionResultData data( resultType, LazyExpression( false ) );
  5156. AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
  5157. const auto isOk = assertionResult.isOk();
  5158. assertionEnded( CATCH_MOVE(assertionResult) );
  5159. if ( !isOk ) { populateReaction( reaction ); }
  5160. resetAssertionInfo();
  5161. }
  5162. IResultCapture& getResultCapture() {
  5163. if (auto* capture = getCurrentContext().getResultCapture())
  5164. return *capture;
  5165. else
  5166. CATCH_INTERNAL_ERROR("No result capture instance");
  5167. }
  5168. void seedRng(IConfig const& config) {
  5169. sharedRng().seed(config.rngSeed());
  5170. }
  5171. unsigned int rngSeed() {
  5172. return getCurrentContext().getConfig()->rngSeed();
  5173. }
  5174. }
  5175. namespace Catch {
  5176. Section::Section( SectionInfo&& info ):
  5177. m_info( CATCH_MOVE( info ) ),
  5178. m_sectionIncluded(
  5179. getResultCapture().sectionStarted( m_info.name, m_info.lineInfo, m_assertions ) ) {
  5180. // Non-"included" sections will not use the timing information
  5181. // anyway, so don't bother with the potential syscall.
  5182. if (m_sectionIncluded) {
  5183. m_timer.start();
  5184. }
  5185. }
  5186. Section::Section( SourceLineInfo const& _lineInfo,
  5187. StringRef _name,
  5188. const char* const ):
  5189. m_info( { "invalid", static_cast<std::size_t>( -1 ) }, std::string{} ),
  5190. m_sectionIncluded(
  5191. getResultCapture().sectionStarted( _name, _lineInfo, m_assertions ) ) {
  5192. // We delay initialization the SectionInfo member until we know
  5193. // this section needs it, so we avoid allocating std::string for name.
  5194. // We also delay timer start to avoid the potential syscall unless we
  5195. // will actually use the result.
  5196. if ( m_sectionIncluded ) {
  5197. m_info.name = static_cast<std::string>( _name );
  5198. m_info.lineInfo = _lineInfo;
  5199. m_timer.start();
  5200. }
  5201. }
  5202. Section::~Section() {
  5203. if( m_sectionIncluded ) {
  5204. SectionEndInfo endInfo{ CATCH_MOVE(m_info), m_assertions, m_timer.getElapsedSeconds() };
  5205. if ( uncaught_exceptions() ) {
  5206. getResultCapture().sectionEndedEarly( CATCH_MOVE(endInfo) );
  5207. } else {
  5208. getResultCapture().sectionEnded( CATCH_MOVE( endInfo ) );
  5209. }
  5210. }
  5211. }
  5212. // This indicates whether the section should be executed or not
  5213. Section::operator bool() const {
  5214. return m_sectionIncluded;
  5215. }
  5216. } // end namespace Catch
  5217. #include <vector>
  5218. namespace Catch {
  5219. namespace {
  5220. static auto getSingletons() -> std::vector<ISingleton*>*& {
  5221. static std::vector<ISingleton*>* g_singletons = nullptr;
  5222. if( !g_singletons )
  5223. g_singletons = new std::vector<ISingleton*>();
  5224. return g_singletons;
  5225. }
  5226. }
  5227. ISingleton::~ISingleton() = default;
  5228. void addSingleton(ISingleton* singleton ) {
  5229. getSingletons()->push_back( singleton );
  5230. }
  5231. void cleanupSingletons() {
  5232. auto& singletons = getSingletons();
  5233. for( auto singleton : *singletons )
  5234. delete singleton;
  5235. delete singletons;
  5236. singletons = nullptr;
  5237. }
  5238. } // namespace Catch
  5239. #include <cstring>
  5240. #include <ostream>
  5241. namespace Catch {
  5242. bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
  5243. return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
  5244. }
  5245. bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
  5246. // We can assume that the same file will usually have the same pointer.
  5247. // Thus, if the pointers are the same, there is no point in calling the strcmp
  5248. return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
  5249. }
  5250. std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
  5251. #ifndef __GNUG__
  5252. os << info.file << '(' << info.line << ')';
  5253. #else
  5254. os << info.file << ':' << info.line;
  5255. #endif
  5256. return os;
  5257. }
  5258. } // end namespace Catch
  5259. namespace Catch {
  5260. #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  5261. void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
  5262. CATCH_TRY {
  5263. m_exceptions.push_back(exception);
  5264. } CATCH_CATCH_ALL {
  5265. // If we run out of memory during start-up there's really not a lot more we can do about it
  5266. std::terminate();
  5267. }
  5268. }
  5269. std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {
  5270. return m_exceptions;
  5271. }
  5272. #endif
  5273. } // end namespace Catch
  5274. #include <iostream>
  5275. namespace Catch {
  5276. // If you #define this you must implement these functions
  5277. #if !defined( CATCH_CONFIG_NOSTDOUT )
  5278. std::ostream& cout() { return std::cout; }
  5279. std::ostream& cerr() { return std::cerr; }
  5280. std::ostream& clog() { return std::clog; }
  5281. #endif
  5282. } // namespace Catch
  5283. #include <ostream>
  5284. #include <cstring>
  5285. #include <cctype>
  5286. #include <vector>
  5287. namespace Catch {
  5288. bool startsWith( std::string const& s, std::string const& prefix ) {
  5289. return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
  5290. }
  5291. bool startsWith( StringRef s, char prefix ) {
  5292. return !s.empty() && s[0] == prefix;
  5293. }
  5294. bool endsWith( std::string const& s, std::string const& suffix ) {
  5295. return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
  5296. }
  5297. bool endsWith( std::string const& s, char suffix ) {
  5298. return !s.empty() && s[s.size()-1] == suffix;
  5299. }
  5300. bool contains( std::string const& s, std::string const& infix ) {
  5301. return s.find( infix ) != std::string::npos;
  5302. }
  5303. void toLowerInPlace( std::string& s ) {
  5304. for ( char& c : s ) {
  5305. c = toLower( c );
  5306. }
  5307. }
  5308. std::string toLower( std::string const& s ) {
  5309. std::string lc = s;
  5310. toLowerInPlace( lc );
  5311. return lc;
  5312. }
  5313. char toLower(char c) {
  5314. return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
  5315. }
  5316. std::string trim( std::string const& str ) {
  5317. static char const* whitespaceChars = "\n\r\t ";
  5318. std::string::size_type start = str.find_first_not_of( whitespaceChars );
  5319. std::string::size_type end = str.find_last_not_of( whitespaceChars );
  5320. return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
  5321. }
  5322. StringRef trim(StringRef ref) {
  5323. const auto is_ws = [](char c) {
  5324. return c == ' ' || c == '\t' || c == '\n' || c == '\r';
  5325. };
  5326. size_t real_begin = 0;
  5327. while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; }
  5328. size_t real_end = ref.size();
  5329. while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; }
  5330. return ref.substr(real_begin, real_end - real_begin);
  5331. }
  5332. bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
  5333. std::size_t i = str.find( replaceThis );
  5334. if (i == std::string::npos) {
  5335. return false;
  5336. }
  5337. std::size_t copyBegin = 0;
  5338. std::string origStr = CATCH_MOVE(str);
  5339. str.clear();
  5340. // There is at least one replacement, so reserve with the best guess
  5341. // we can make without actually counting the number of occurences.
  5342. str.reserve(origStr.size() - replaceThis.size() + withThis.size());
  5343. do {
  5344. str.append(origStr, copyBegin, i-copyBegin );
  5345. str += withThis;
  5346. copyBegin = i + replaceThis.size();
  5347. if( copyBegin < origStr.size() )
  5348. i = origStr.find( replaceThis, copyBegin );
  5349. else
  5350. i = std::string::npos;
  5351. } while( i != std::string::npos );
  5352. if ( copyBegin < origStr.size() ) {
  5353. str.append(origStr, copyBegin, origStr.size() );
  5354. }
  5355. return true;
  5356. }
  5357. std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {
  5358. std::vector<StringRef> subStrings;
  5359. std::size_t start = 0;
  5360. for(std::size_t pos = 0; pos < str.size(); ++pos ) {
  5361. if( str[pos] == delimiter ) {
  5362. if( pos - start > 1 )
  5363. subStrings.push_back( str.substr( start, pos-start ) );
  5364. start = pos+1;
  5365. }
  5366. }
  5367. if( start < str.size() )
  5368. subStrings.push_back( str.substr( start, str.size()-start ) );
  5369. return subStrings;
  5370. }
  5371. std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
  5372. os << pluraliser.m_count << ' ' << pluraliser.m_label;
  5373. if( pluraliser.m_count != 1 )
  5374. os << 's';
  5375. return os;
  5376. }
  5377. }
  5378. #include <algorithm>
  5379. #include <ostream>
  5380. #include <cstring>
  5381. #include <cstdint>
  5382. namespace Catch {
  5383. StringRef::StringRef( char const* rawChars ) noexcept
  5384. : StringRef( rawChars, std::strlen(rawChars) )
  5385. {}
  5386. bool StringRef::operator<(StringRef rhs) const noexcept {
  5387. if (m_size < rhs.m_size) {
  5388. return strncmp(m_start, rhs.m_start, m_size) <= 0;
  5389. }
  5390. return strncmp(m_start, rhs.m_start, rhs.m_size) < 0;
  5391. }
  5392. int StringRef::compare( StringRef rhs ) const {
  5393. auto cmpResult =
  5394. strncmp( m_start, rhs.m_start, std::min( m_size, rhs.m_size ) );
  5395. // This means that strncmp found a difference before the strings
  5396. // ended, and we can return it directly
  5397. if ( cmpResult != 0 ) {
  5398. return cmpResult;
  5399. }
  5400. // If strings are equal up to length, then their comparison results on
  5401. // their size
  5402. if ( m_size < rhs.m_size ) {
  5403. return -1;
  5404. } else if ( m_size > rhs.m_size ) {
  5405. return 1;
  5406. } else {
  5407. return 0;
  5408. }
  5409. }
  5410. auto operator << ( std::ostream& os, StringRef str ) -> std::ostream& {
  5411. return os.write(str.data(), static_cast<std::streamsize>(str.size()));
  5412. }
  5413. std::string operator+(StringRef lhs, StringRef rhs) {
  5414. std::string ret;
  5415. ret.reserve(lhs.size() + rhs.size());
  5416. ret += lhs;
  5417. ret += rhs;
  5418. return ret;
  5419. }
  5420. auto operator+=( std::string& lhs, StringRef rhs ) -> std::string& {
  5421. lhs.append(rhs.data(), rhs.size());
  5422. return lhs;
  5423. }
  5424. } // namespace Catch
  5425. namespace Catch {
  5426. TagAliasRegistry::~TagAliasRegistry() = default;
  5427. TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
  5428. auto it = m_registry.find( alias );
  5429. if( it != m_registry.end() )
  5430. return &(it->second);
  5431. else
  5432. return nullptr;
  5433. }
  5434. std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
  5435. std::string expandedTestSpec = unexpandedTestSpec;
  5436. for( auto const& registryKvp : m_registry ) {
  5437. std::size_t pos = expandedTestSpec.find( registryKvp.first );
  5438. if( pos != std::string::npos ) {
  5439. expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
  5440. registryKvp.second.tag +
  5441. expandedTestSpec.substr( pos + registryKvp.first.size() );
  5442. }
  5443. }
  5444. return expandedTestSpec;
  5445. }
  5446. void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
  5447. CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
  5448. "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
  5449. CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
  5450. "error: tag alias, '" << alias << "' already registered.\n"
  5451. << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
  5452. << "\tRedefined at: " << lineInfo );
  5453. }
  5454. ITagAliasRegistry::~ITagAliasRegistry() = default;
  5455. ITagAliasRegistry const& ITagAliasRegistry::get() {
  5456. return getRegistryHub().getTagAliasRegistry();
  5457. }
  5458. } // end namespace Catch
  5459. namespace Catch {
  5460. TestCaseInfoHasher::TestCaseInfoHasher( hash_t seed ): m_seed( seed ) {}
  5461. uint32_t TestCaseInfoHasher::operator()( TestCaseInfo const& t ) const {
  5462. // FNV-1a hash algorithm that is designed for uniqueness:
  5463. const hash_t prime = 1099511628211u;
  5464. hash_t hash = 14695981039346656037u;
  5465. for ( const char c : t.name ) {
  5466. hash ^= c;
  5467. hash *= prime;
  5468. }
  5469. for ( const char c : t.className ) {
  5470. hash ^= c;
  5471. hash *= prime;
  5472. }
  5473. for ( const Tag& tag : t.tags ) {
  5474. for ( const char c : tag.original ) {
  5475. hash ^= c;
  5476. hash *= prime;
  5477. }
  5478. }
  5479. hash ^= m_seed;
  5480. hash *= prime;
  5481. const uint32_t low{ static_cast<uint32_t>( hash ) };
  5482. const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
  5483. return low * high;
  5484. }
  5485. } // namespace Catch
  5486. #include <algorithm>
  5487. #include <set>
  5488. namespace Catch {
  5489. namespace {
  5490. static void enforceNoDuplicateTestCases(
  5491. std::vector<TestCaseHandle> const& tests ) {
  5492. auto testInfoCmp = []( TestCaseInfo const* lhs,
  5493. TestCaseInfo const* rhs ) {
  5494. return *lhs < *rhs;
  5495. };
  5496. std::set<TestCaseInfo const*, decltype( testInfoCmp )&> seenTests(
  5497. testInfoCmp );
  5498. for ( auto const& test : tests ) {
  5499. const auto infoPtr = &test.getTestCaseInfo();
  5500. const auto prev = seenTests.insert( infoPtr );
  5501. CATCH_ENFORCE( prev.second,
  5502. "error: test case \""
  5503. << infoPtr->name << "\", with tags \""
  5504. << infoPtr->tagsAsString()
  5505. << "\" already defined.\n"
  5506. << "\tFirst seen at "
  5507. << ( *prev.first )->lineInfo << "\n"
  5508. << "\tRedefined at " << infoPtr->lineInfo );
  5509. }
  5510. }
  5511. static bool matchTest( TestCaseHandle const& testCase,
  5512. TestSpec const& testSpec,
  5513. IConfig const& config ) {
  5514. return testSpec.matches( testCase.getTestCaseInfo() ) &&
  5515. isThrowSafe( testCase, config );
  5516. }
  5517. } // end unnamed namespace
  5518. std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ) {
  5519. switch (config.runOrder()) {
  5520. case TestRunOrder::Declared:
  5521. return unsortedTestCases;
  5522. case TestRunOrder::LexicographicallySorted: {
  5523. std::vector<TestCaseHandle> sorted = unsortedTestCases;
  5524. std::sort(
  5525. sorted.begin(),
  5526. sorted.end(),
  5527. []( TestCaseHandle const& lhs, TestCaseHandle const& rhs ) {
  5528. return lhs.getTestCaseInfo() < rhs.getTestCaseInfo();
  5529. }
  5530. );
  5531. return sorted;
  5532. }
  5533. case TestRunOrder::Randomized: {
  5534. using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>;
  5535. TestCaseInfoHasher h{ config.rngSeed() };
  5536. std::vector<TestWithHash> indexed_tests;
  5537. indexed_tests.reserve(unsortedTestCases.size());
  5538. for (auto const& handle : unsortedTestCases) {
  5539. indexed_tests.emplace_back(h(handle.getTestCaseInfo()), handle);
  5540. }
  5541. std::sort( indexed_tests.begin(),
  5542. indexed_tests.end(),
  5543. []( TestWithHash const& lhs, TestWithHash const& rhs ) {
  5544. if ( lhs.first == rhs.first ) {
  5545. return lhs.second.getTestCaseInfo() <
  5546. rhs.second.getTestCaseInfo();
  5547. }
  5548. return lhs.first < rhs.first;
  5549. } );
  5550. std::vector<TestCaseHandle> randomized;
  5551. randomized.reserve(indexed_tests.size());
  5552. for (auto const& indexed : indexed_tests) {
  5553. randomized.push_back(indexed.second);
  5554. }
  5555. return randomized;
  5556. }
  5557. }
  5558. CATCH_INTERNAL_ERROR("Unknown test order value!");
  5559. }
  5560. bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ) {
  5561. return !testCase.getTestCaseInfo().throws() || config.allowThrows();
  5562. }
  5563. std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
  5564. std::vector<TestCaseHandle> filtered;
  5565. filtered.reserve( testCases.size() );
  5566. for (auto const& testCase : testCases) {
  5567. if ((!testSpec.hasFilters() && !testCase.getTestCaseInfo().isHidden()) ||
  5568. (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
  5569. filtered.push_back(testCase);
  5570. }
  5571. }
  5572. return createShard(filtered, config.shardCount(), config.shardIndex());
  5573. }
  5574. std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config ) {
  5575. return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
  5576. }
  5577. TestRegistry::~TestRegistry() = default;
  5578. void TestRegistry::registerTest(Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker) {
  5579. m_handles.emplace_back(testInfo.get(), testInvoker.get());
  5580. m_viewed_test_infos.push_back(testInfo.get());
  5581. m_owned_test_infos.push_back(CATCH_MOVE(testInfo));
  5582. m_invokers.push_back(CATCH_MOVE(testInvoker));
  5583. }
  5584. std::vector<TestCaseInfo*> const& TestRegistry::getAllInfos() const {
  5585. return m_viewed_test_infos;
  5586. }
  5587. std::vector<TestCaseHandle> const& TestRegistry::getAllTests() const {
  5588. return m_handles;
  5589. }
  5590. std::vector<TestCaseHandle> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
  5591. if( m_sortedFunctions.empty() )
  5592. enforceNoDuplicateTestCases( m_handles );
  5593. if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
  5594. m_sortedFunctions = sortTests( config, m_handles );
  5595. m_currentSortOrder = config.runOrder();
  5596. }
  5597. return m_sortedFunctions;
  5598. }
  5599. } // end namespace Catch
  5600. #include <algorithm>
  5601. #include <cassert>
  5602. #if defined(__clang__)
  5603. # pragma clang diagnostic push
  5604. # pragma clang diagnostic ignored "-Wexit-time-destructors"
  5605. #endif
  5606. namespace Catch {
  5607. namespace TestCaseTracking {
  5608. NameAndLocation::NameAndLocation( std::string&& _name, SourceLineInfo const& _location )
  5609. : name( CATCH_MOVE(_name) ),
  5610. location( _location )
  5611. {}
  5612. ITracker::~ITracker() = default;
  5613. void ITracker::markAsNeedingAnotherRun() {
  5614. m_runState = NeedsAnotherRun;
  5615. }
  5616. void ITracker::addChild( ITrackerPtr&& child ) {
  5617. m_children.push_back( CATCH_MOVE(child) );
  5618. }
  5619. ITracker* ITracker::findChild( NameAndLocationRef const& nameAndLocation ) {
  5620. auto it = std::find_if(
  5621. m_children.begin(),
  5622. m_children.end(),
  5623. [&nameAndLocation]( ITrackerPtr const& tracker ) {
  5624. auto const& tnameAndLoc = tracker->nameAndLocation();
  5625. if ( tnameAndLoc.location.line !=
  5626. nameAndLocation.location.line ) {
  5627. return false;
  5628. }
  5629. return tnameAndLoc == nameAndLocation;
  5630. } );
  5631. return ( it != m_children.end() ) ? it->get() : nullptr;
  5632. }
  5633. bool ITracker::isSectionTracker() const { return false; }
  5634. bool ITracker::isGeneratorTracker() const { return false; }
  5635. bool ITracker::isOpen() const {
  5636. return m_runState != NotStarted && !isComplete();
  5637. }
  5638. bool ITracker::hasStarted() const { return m_runState != NotStarted; }
  5639. void ITracker::openChild() {
  5640. if (m_runState != ExecutingChildren) {
  5641. m_runState = ExecutingChildren;
  5642. if (m_parent) {
  5643. m_parent->openChild();
  5644. }
  5645. }
  5646. }
  5647. ITracker& TrackerContext::startRun() {
  5648. using namespace std::string_literals;
  5649. m_rootTracker = Catch::Detail::make_unique<SectionTracker>(
  5650. NameAndLocation( "{root}"s, CATCH_INTERNAL_LINEINFO ),
  5651. *this,
  5652. nullptr );
  5653. m_currentTracker = nullptr;
  5654. m_runState = Executing;
  5655. return *m_rootTracker;
  5656. }
  5657. void TrackerContext::completeCycle() {
  5658. m_runState = CompletedCycle;
  5659. }
  5660. bool TrackerContext::completedCycle() const {
  5661. return m_runState == CompletedCycle;
  5662. }
  5663. void TrackerContext::setCurrentTracker( ITracker* tracker ) {
  5664. m_currentTracker = tracker;
  5665. }
  5666. TrackerBase::TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
  5667. ITracker(CATCH_MOVE(nameAndLocation), parent),
  5668. m_ctx( ctx )
  5669. {}
  5670. bool TrackerBase::isComplete() const {
  5671. return m_runState == CompletedSuccessfully || m_runState == Failed;
  5672. }
  5673. void TrackerBase::open() {
  5674. m_runState = Executing;
  5675. moveToThis();
  5676. if( m_parent )
  5677. m_parent->openChild();
  5678. }
  5679. void TrackerBase::close() {
  5680. // Close any still open children (e.g. generators)
  5681. while( &m_ctx.currentTracker() != this )
  5682. m_ctx.currentTracker().close();
  5683. switch( m_runState ) {
  5684. case NeedsAnotherRun:
  5685. break;
  5686. case Executing:
  5687. m_runState = CompletedSuccessfully;
  5688. break;
  5689. case ExecutingChildren:
  5690. if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )
  5691. m_runState = CompletedSuccessfully;
  5692. break;
  5693. case NotStarted:
  5694. case CompletedSuccessfully:
  5695. case Failed:
  5696. CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
  5697. default:
  5698. CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
  5699. }
  5700. moveToParent();
  5701. m_ctx.completeCycle();
  5702. }
  5703. void TrackerBase::fail() {
  5704. m_runState = Failed;
  5705. if( m_parent )
  5706. m_parent->markAsNeedingAnotherRun();
  5707. moveToParent();
  5708. m_ctx.completeCycle();
  5709. }
  5710. void TrackerBase::moveToParent() {
  5711. assert( m_parent );
  5712. m_ctx.setCurrentTracker( m_parent );
  5713. }
  5714. void TrackerBase::moveToThis() {
  5715. m_ctx.setCurrentTracker( this );
  5716. }
  5717. SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
  5718. : TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ),
  5719. m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name)))
  5720. {
  5721. if( parent ) {
  5722. while ( !parent->isSectionTracker() ) {
  5723. parent = parent->parent();
  5724. }
  5725. SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
  5726. addNextFilters( parentSection.m_filters );
  5727. }
  5728. }
  5729. bool SectionTracker::isComplete() const {
  5730. bool complete = true;
  5731. if (m_filters.empty()
  5732. || m_filters[0].empty()
  5733. || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
  5734. complete = TrackerBase::isComplete();
  5735. }
  5736. return complete;
  5737. }
  5738. bool SectionTracker::isSectionTracker() const { return true; }
  5739. SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ) {
  5740. SectionTracker* tracker;
  5741. ITracker& currentTracker = ctx.currentTracker();
  5742. if ( ITracker* childTracker =
  5743. currentTracker.findChild( nameAndLocation ) ) {
  5744. assert( childTracker );
  5745. assert( childTracker->isSectionTracker() );
  5746. tracker = static_cast<SectionTracker*>( childTracker );
  5747. } else {
  5748. auto newTracker = Catch::Detail::make_unique<SectionTracker>(
  5749. NameAndLocation{ static_cast<std::string>(nameAndLocation.name),
  5750. nameAndLocation.location },
  5751. ctx,
  5752. &currentTracker );
  5753. tracker = newTracker.get();
  5754. currentTracker.addChild( CATCH_MOVE( newTracker ) );
  5755. }
  5756. if ( !ctx.completedCycle() ) {
  5757. tracker->tryOpen();
  5758. }
  5759. return *tracker;
  5760. }
  5761. void SectionTracker::tryOpen() {
  5762. if( !isComplete() )
  5763. open();
  5764. }
  5765. void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
  5766. if( !filters.empty() ) {
  5767. m_filters.reserve( m_filters.size() + filters.size() + 2 );
  5768. m_filters.emplace_back(StringRef{}); // Root - should never be consulted
  5769. m_filters.emplace_back(StringRef{}); // Test Case - not a section filter
  5770. m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
  5771. }
  5772. }
  5773. void SectionTracker::addNextFilters( std::vector<StringRef> const& filters ) {
  5774. if( filters.size() > 1 )
  5775. m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
  5776. }
  5777. StringRef SectionTracker::trimmedName() const {
  5778. return m_trimmed_name;
  5779. }
  5780. } // namespace TestCaseTracking
  5781. } // namespace Catch
  5782. #if defined(__clang__)
  5783. # pragma clang diagnostic pop
  5784. #endif
  5785. namespace Catch {
  5786. void throw_test_failure_exception() {
  5787. #if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
  5788. throw TestFailureException{};
  5789. #else
  5790. CATCH_ERROR( "Test failure requires aborting test!" );
  5791. #endif
  5792. }
  5793. void throw_test_skip_exception() {
  5794. #if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
  5795. throw Catch::TestSkipException();
  5796. #else
  5797. CATCH_ERROR( "Explicitly skipping tests during runtime requires exceptions" );
  5798. #endif
  5799. }
  5800. } // namespace Catch
  5801. #include <algorithm>
  5802. #include <iterator>
  5803. namespace Catch {
  5804. void ITestInvoker::prepareTestCase() {}
  5805. void ITestInvoker::tearDownTestCase() {}
  5806. ITestInvoker::~ITestInvoker() = default;
  5807. namespace {
  5808. static StringRef extractClassName( StringRef classOrMethodName ) {
  5809. if ( !startsWith( classOrMethodName, '&' ) ) {
  5810. return classOrMethodName;
  5811. }
  5812. // Remove the leading '&' to avoid having to special case it later
  5813. const auto methodName =
  5814. classOrMethodName.substr( 1, classOrMethodName.size() );
  5815. auto reverseStart = std::make_reverse_iterator( methodName.end() );
  5816. auto reverseEnd = std::make_reverse_iterator( methodName.begin() );
  5817. // We make a simplifying assumption that ":" is only present
  5818. // in the input as part of "::" from C++ typenames (this is
  5819. // relatively safe assumption because the input is generated
  5820. // as stringification of type through preprocessor).
  5821. auto lastColons = std::find( reverseStart, reverseEnd, ':' ) + 1;
  5822. auto secondLastColons =
  5823. std::find( lastColons + 1, reverseEnd, ':' );
  5824. auto const startIdx = reverseEnd - secondLastColons;
  5825. auto const classNameSize = secondLastColons - lastColons - 1;
  5826. return methodName.substr(
  5827. static_cast<std::size_t>( startIdx ),
  5828. static_cast<std::size_t>( classNameSize ) );
  5829. }
  5830. class TestInvokerAsFunction final : public ITestInvoker {
  5831. using TestType = void ( * )();
  5832. TestType m_testAsFunction;
  5833. public:
  5834. constexpr TestInvokerAsFunction( TestType testAsFunction ) noexcept:
  5835. m_testAsFunction( testAsFunction ) {}
  5836. void invoke() const override { m_testAsFunction(); }
  5837. };
  5838. } // namespace
  5839. Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() ) {
  5840. return Detail::make_unique<TestInvokerAsFunction>( testAsFunction );
  5841. }
  5842. AutoReg::AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
  5843. CATCH_TRY {
  5844. getMutableRegistryHub()
  5845. .registerTest(
  5846. makeTestCaseInfo(
  5847. extractClassName( classOrMethod ),
  5848. nameAndTags,
  5849. lineInfo),
  5850. CATCH_MOVE(invoker)
  5851. );
  5852. } CATCH_CATCH_ALL {
  5853. // Do not throw when constructing global objects, instead register the exception to be processed later
  5854. getMutableRegistryHub().registerStartupException();
  5855. }
  5856. }
  5857. }
  5858. namespace Catch {
  5859. TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
  5860. TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
  5861. m_mode = None;
  5862. m_exclusion = false;
  5863. m_arg = m_tagAliases->expandAliases( arg );
  5864. m_escapeChars.clear();
  5865. m_substring.reserve(m_arg.size());
  5866. m_patternName.reserve(m_arg.size());
  5867. m_realPatternPos = 0;
  5868. for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
  5869. //if visitChar fails
  5870. if( !visitChar( m_arg[m_pos] ) ){
  5871. m_testSpec.m_invalidSpecs.push_back(arg);
  5872. break;
  5873. }
  5874. endMode();
  5875. return *this;
  5876. }
  5877. TestSpec TestSpecParser::testSpec() {
  5878. addFilter();
  5879. return CATCH_MOVE(m_testSpec);
  5880. }
  5881. bool TestSpecParser::visitChar( char c ) {
  5882. if( (m_mode != EscapedName) && (c == '\\') ) {
  5883. escape();
  5884. addCharToPattern(c);
  5885. return true;
  5886. }else if((m_mode != EscapedName) && (c == ',') ) {
  5887. return separate();
  5888. }
  5889. switch( m_mode ) {
  5890. case None:
  5891. if( processNoneChar( c ) )
  5892. return true;
  5893. break;
  5894. case Name:
  5895. processNameChar( c );
  5896. break;
  5897. case EscapedName:
  5898. endMode();
  5899. addCharToPattern(c);
  5900. return true;
  5901. default:
  5902. case Tag:
  5903. case QuotedName:
  5904. if( processOtherChar( c ) )
  5905. return true;
  5906. break;
  5907. }
  5908. m_substring += c;
  5909. if( !isControlChar( c ) ) {
  5910. m_patternName += c;
  5911. m_realPatternPos++;
  5912. }
  5913. return true;
  5914. }
  5915. // Two of the processing methods return true to signal the caller to return
  5916. // without adding the given character to the current pattern strings
  5917. bool TestSpecParser::processNoneChar( char c ) {
  5918. switch( c ) {
  5919. case ' ':
  5920. return true;
  5921. case '~':
  5922. m_exclusion = true;
  5923. return false;
  5924. case '[':
  5925. startNewMode( Tag );
  5926. return false;
  5927. case '"':
  5928. startNewMode( QuotedName );
  5929. return false;
  5930. default:
  5931. startNewMode( Name );
  5932. return false;
  5933. }
  5934. }
  5935. void TestSpecParser::processNameChar( char c ) {
  5936. if( c == '[' ) {
  5937. if( m_substring == "exclude:" )
  5938. m_exclusion = true;
  5939. else
  5940. endMode();
  5941. startNewMode( Tag );
  5942. }
  5943. }
  5944. bool TestSpecParser::processOtherChar( char c ) {
  5945. if( !isControlChar( c ) )
  5946. return false;
  5947. m_substring += c;
  5948. endMode();
  5949. return true;
  5950. }
  5951. void TestSpecParser::startNewMode( Mode mode ) {
  5952. m_mode = mode;
  5953. }
  5954. void TestSpecParser::endMode() {
  5955. switch( m_mode ) {
  5956. case Name:
  5957. case QuotedName:
  5958. return addNamePattern();
  5959. case Tag:
  5960. return addTagPattern();
  5961. case EscapedName:
  5962. revertBackToLastMode();
  5963. return;
  5964. case None:
  5965. default:
  5966. return startNewMode( None );
  5967. }
  5968. }
  5969. void TestSpecParser::escape() {
  5970. saveLastMode();
  5971. m_mode = EscapedName;
  5972. m_escapeChars.push_back(m_realPatternPos);
  5973. }
  5974. bool TestSpecParser::isControlChar( char c ) const {
  5975. switch( m_mode ) {
  5976. default:
  5977. return false;
  5978. case None:
  5979. return c == '~';
  5980. case Name:
  5981. return c == '[';
  5982. case EscapedName:
  5983. return true;
  5984. case QuotedName:
  5985. return c == '"';
  5986. case Tag:
  5987. return c == '[' || c == ']';
  5988. }
  5989. }
  5990. void TestSpecParser::addFilter() {
  5991. if( !m_currentFilter.m_required.empty() || !m_currentFilter.m_forbidden.empty() ) {
  5992. m_testSpec.m_filters.push_back( CATCH_MOVE(m_currentFilter) );
  5993. m_currentFilter = TestSpec::Filter();
  5994. }
  5995. }
  5996. void TestSpecParser::saveLastMode() {
  5997. lastMode = m_mode;
  5998. }
  5999. void TestSpecParser::revertBackToLastMode() {
  6000. m_mode = lastMode;
  6001. }
  6002. bool TestSpecParser::separate() {
  6003. if( (m_mode==QuotedName) || (m_mode==Tag) ){
  6004. //invalid argument, signal failure to previous scope.
  6005. m_mode = None;
  6006. m_pos = m_arg.size();
  6007. m_substring.clear();
  6008. m_patternName.clear();
  6009. m_realPatternPos = 0;
  6010. return false;
  6011. }
  6012. endMode();
  6013. addFilter();
  6014. return true; //success
  6015. }
  6016. std::string TestSpecParser::preprocessPattern() {
  6017. std::string token = m_patternName;
  6018. for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
  6019. token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
  6020. m_escapeChars.clear();
  6021. if (startsWith(token, "exclude:")) {
  6022. m_exclusion = true;
  6023. token = token.substr(8);
  6024. }
  6025. m_patternName.clear();
  6026. m_realPatternPos = 0;
  6027. return token;
  6028. }
  6029. void TestSpecParser::addNamePattern() {
  6030. auto token = preprocessPattern();
  6031. if (!token.empty()) {
  6032. if (m_exclusion) {
  6033. m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::NamePattern>(token, m_substring));
  6034. } else {
  6035. m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::NamePattern>(token, m_substring));
  6036. }
  6037. }
  6038. m_substring.clear();
  6039. m_exclusion = false;
  6040. m_mode = None;
  6041. }
  6042. void TestSpecParser::addTagPattern() {
  6043. auto token = preprocessPattern();
  6044. if (!token.empty()) {
  6045. // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
  6046. // we have to create a separate hide tag and shorten the real one
  6047. if (token.size() > 1 && token[0] == '.') {
  6048. token.erase(token.begin());
  6049. if (m_exclusion) {
  6050. m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
  6051. } else {
  6052. m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
  6053. }
  6054. }
  6055. if (m_exclusion) {
  6056. m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
  6057. } else {
  6058. m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
  6059. }
  6060. }
  6061. m_substring.clear();
  6062. m_exclusion = false;
  6063. m_mode = None;
  6064. }
  6065. } // namespace Catch
  6066. #include <algorithm>
  6067. #include <cstring>
  6068. #include <ostream>
  6069. namespace {
  6070. bool isWhitespace( char c ) {
  6071. return c == ' ' || c == '\t' || c == '\n' || c == '\r';
  6072. }
  6073. bool isBreakableBefore( char c ) {
  6074. static const char chars[] = "[({<|";
  6075. return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
  6076. }
  6077. bool isBreakableAfter( char c ) {
  6078. static const char chars[] = "])}>.,:;*+-=&/\\";
  6079. return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
  6080. }
  6081. } // namespace
  6082. namespace Catch {
  6083. namespace TextFlow {
  6084. void AnsiSkippingString::preprocessString() {
  6085. for ( auto it = m_string.begin(); it != m_string.end(); ) {
  6086. // try to read through an ansi sequence
  6087. while ( it != m_string.end() && *it == '\033' &&
  6088. it + 1 != m_string.end() && *( it + 1 ) == '[' ) {
  6089. auto cursor = it + 2;
  6090. while ( cursor != m_string.end() &&
  6091. ( isdigit( *cursor ) || *cursor == ';' ) ) {
  6092. ++cursor;
  6093. }
  6094. if ( cursor == m_string.end() || *cursor != 'm' ) {
  6095. break;
  6096. }
  6097. // 'm' -> 0xff
  6098. *cursor = AnsiSkippingString::sentinel;
  6099. // if we've read an ansi sequence, set the iterator and
  6100. // return to the top of the loop
  6101. it = cursor + 1;
  6102. }
  6103. if ( it != m_string.end() ) {
  6104. ++m_size;
  6105. ++it;
  6106. }
  6107. }
  6108. }
  6109. AnsiSkippingString::AnsiSkippingString( std::string const& text ):
  6110. m_string( text ) {
  6111. preprocessString();
  6112. }
  6113. AnsiSkippingString::AnsiSkippingString( std::string&& text ):
  6114. m_string( CATCH_MOVE( text ) ) {
  6115. preprocessString();
  6116. }
  6117. AnsiSkippingString::const_iterator AnsiSkippingString::begin() const {
  6118. return const_iterator( m_string );
  6119. }
  6120. AnsiSkippingString::const_iterator AnsiSkippingString::end() const {
  6121. return const_iterator( m_string, const_iterator::EndTag{} );
  6122. }
  6123. std::string AnsiSkippingString::substring( const_iterator begin,
  6124. const_iterator end ) const {
  6125. // There's one caveat here to an otherwise simple substring: when
  6126. // making a begin iterator we might have skipped ansi sequences at
  6127. // the start. If `begin` here is a begin iterator, skipped over
  6128. // initial ansi sequences, we'll use the true beginning of the
  6129. // string. Lastly: We need to transform any chars we replaced with
  6130. // 0xff back to 'm'
  6131. auto str = std::string( begin == this->begin() ? m_string.begin()
  6132. : begin.m_it,
  6133. end.m_it );
  6134. std::transform( str.begin(), str.end(), str.begin(), []( char c ) {
  6135. return c == AnsiSkippingString::sentinel ? 'm' : c;
  6136. } );
  6137. return str;
  6138. }
  6139. void AnsiSkippingString::const_iterator::tryParseAnsiEscapes() {
  6140. // check if we've landed on an ansi sequence, and if so read through
  6141. // it
  6142. while ( m_it != m_string->end() && *m_it == '\033' &&
  6143. m_it + 1 != m_string->end() && *( m_it + 1 ) == '[' ) {
  6144. auto cursor = m_it + 2;
  6145. while ( cursor != m_string->end() &&
  6146. ( isdigit( *cursor ) || *cursor == ';' ) ) {
  6147. ++cursor;
  6148. }
  6149. if ( cursor == m_string->end() ||
  6150. *cursor != AnsiSkippingString::sentinel ) {
  6151. break;
  6152. }
  6153. // if we've read an ansi sequence, set the iterator and
  6154. // return to the top of the loop
  6155. m_it = cursor + 1;
  6156. }
  6157. }
  6158. void AnsiSkippingString::const_iterator::advance() {
  6159. assert( m_it != m_string->end() );
  6160. m_it++;
  6161. tryParseAnsiEscapes();
  6162. }
  6163. void AnsiSkippingString::const_iterator::unadvance() {
  6164. assert( m_it != m_string->begin() );
  6165. m_it--;
  6166. // if *m_it is 0xff, scan back to the \033 and then m_it-- once more
  6167. // (and repeat check)
  6168. while ( *m_it == AnsiSkippingString::sentinel ) {
  6169. while ( *m_it != '\033' ) {
  6170. assert( m_it != m_string->begin() );
  6171. m_it--;
  6172. }
  6173. // if this happens, we must have been a begin iterator that had
  6174. // skipped over ansi sequences at the start of a string
  6175. assert( m_it != m_string->begin() );
  6176. assert( *m_it == '\033' );
  6177. m_it--;
  6178. }
  6179. }
  6180. static bool isBoundary( AnsiSkippingString const& line,
  6181. AnsiSkippingString::const_iterator it ) {
  6182. return it == line.end() ||
  6183. ( isWhitespace( *it ) &&
  6184. !isWhitespace( *it.oneBefore() ) ) ||
  6185. isBreakableBefore( *it ) ||
  6186. isBreakableAfter( *it.oneBefore() );
  6187. }
  6188. void Column::const_iterator::calcLength() {
  6189. m_addHyphen = false;
  6190. m_parsedTo = m_lineStart;
  6191. AnsiSkippingString const& current_line = m_column.m_string;
  6192. if ( m_parsedTo == current_line.end() ) {
  6193. m_lineEnd = m_parsedTo;
  6194. return;
  6195. }
  6196. assert( m_lineStart != current_line.end() );
  6197. if ( *m_lineStart == '\n' ) { ++m_parsedTo; }
  6198. const auto maxLineLength = m_column.m_width - indentSize();
  6199. std::size_t lineLength = 0;
  6200. while ( m_parsedTo != current_line.end() &&
  6201. lineLength < maxLineLength && *m_parsedTo != '\n' ) {
  6202. ++m_parsedTo;
  6203. ++lineLength;
  6204. }
  6205. // If we encountered a newline before the column is filled,
  6206. // then we linebreak at the newline and consider this line
  6207. // finished.
  6208. if ( lineLength < maxLineLength ) {
  6209. m_lineEnd = m_parsedTo;
  6210. } else {
  6211. // Look for a natural linebreak boundary in the column
  6212. // (We look from the end, so that the first found boundary is
  6213. // the right one)
  6214. m_lineEnd = m_parsedTo;
  6215. while ( lineLength > 0 &&
  6216. !isBoundary( current_line, m_lineEnd ) ) {
  6217. --lineLength;
  6218. --m_lineEnd;
  6219. }
  6220. while ( lineLength > 0 &&
  6221. isWhitespace( *m_lineEnd.oneBefore() ) ) {
  6222. --lineLength;
  6223. --m_lineEnd;
  6224. }
  6225. // If we found one, then that is where we linebreak, otherwise
  6226. // we have to split text with a hyphen
  6227. if ( lineLength == 0 ) {
  6228. m_addHyphen = true;
  6229. m_lineEnd = m_parsedTo.oneBefore();
  6230. }
  6231. }
  6232. }
  6233. size_t Column::const_iterator::indentSize() const {
  6234. auto initial = m_lineStart == m_column.m_string.begin()
  6235. ? m_column.m_initialIndent
  6236. : std::string::npos;
  6237. return initial == std::string::npos ? m_column.m_indent : initial;
  6238. }
  6239. std::string Column::const_iterator::addIndentAndSuffix(
  6240. AnsiSkippingString::const_iterator start,
  6241. AnsiSkippingString::const_iterator end ) const {
  6242. std::string ret;
  6243. const auto desired_indent = indentSize();
  6244. // ret.reserve( desired_indent + (end - start) + m_addHyphen );
  6245. ret.append( desired_indent, ' ' );
  6246. // ret.append( start, end );
  6247. ret += m_column.m_string.substring( start, end );
  6248. if ( m_addHyphen ) { ret.push_back( '-' ); }
  6249. return ret;
  6250. }
  6251. Column::const_iterator::const_iterator( Column const& column ):
  6252. m_column( column ),
  6253. m_lineStart( column.m_string.begin() ),
  6254. m_lineEnd( column.m_string.begin() ),
  6255. m_parsedTo( column.m_string.begin() ) {
  6256. assert( m_column.m_width > m_column.m_indent );
  6257. assert( m_column.m_initialIndent == std::string::npos ||
  6258. m_column.m_width > m_column.m_initialIndent );
  6259. calcLength();
  6260. if ( m_lineStart == m_lineEnd ) {
  6261. m_lineStart = m_column.m_string.end();
  6262. }
  6263. }
  6264. std::string Column::const_iterator::operator*() const {
  6265. assert( m_lineStart <= m_parsedTo );
  6266. return addIndentAndSuffix( m_lineStart, m_lineEnd );
  6267. }
  6268. Column::const_iterator& Column::const_iterator::operator++() {
  6269. m_lineStart = m_lineEnd;
  6270. AnsiSkippingString const& current_line = m_column.m_string;
  6271. if ( m_lineStart != current_line.end() && *m_lineStart == '\n' ) {
  6272. m_lineStart++;
  6273. } else {
  6274. while ( m_lineStart != current_line.end() &&
  6275. isWhitespace( *m_lineStart ) ) {
  6276. ++m_lineStart;
  6277. }
  6278. }
  6279. if ( m_lineStart != current_line.end() ) { calcLength(); }
  6280. return *this;
  6281. }
  6282. Column::const_iterator Column::const_iterator::operator++( int ) {
  6283. const_iterator prev( *this );
  6284. operator++();
  6285. return prev;
  6286. }
  6287. std::ostream& operator<<( std::ostream& os, Column const& col ) {
  6288. bool first = true;
  6289. for ( auto line : col ) {
  6290. if ( first ) {
  6291. first = false;
  6292. } else {
  6293. os << '\n';
  6294. }
  6295. os << line;
  6296. }
  6297. return os;
  6298. }
  6299. Column Spacer( size_t spaceWidth ) {
  6300. Column ret{ "" };
  6301. ret.width( spaceWidth );
  6302. return ret;
  6303. }
  6304. Columns::iterator::iterator( Columns const& columns, EndTag ):
  6305. m_columns( columns.m_columns ), m_activeIterators( 0 ) {
  6306. m_iterators.reserve( m_columns.size() );
  6307. for ( auto const& col : m_columns ) {
  6308. m_iterators.push_back( col.end() );
  6309. }
  6310. }
  6311. Columns::iterator::iterator( Columns const& columns ):
  6312. m_columns( columns.m_columns ),
  6313. m_activeIterators( m_columns.size() ) {
  6314. m_iterators.reserve( m_columns.size() );
  6315. for ( auto const& col : m_columns ) {
  6316. m_iterators.push_back( col.begin() );
  6317. }
  6318. }
  6319. std::string Columns::iterator::operator*() const {
  6320. std::string row, padding;
  6321. for ( size_t i = 0; i < m_columns.size(); ++i ) {
  6322. const auto width = m_columns[i].width();
  6323. if ( m_iterators[i] != m_columns[i].end() ) {
  6324. std::string col = *m_iterators[i];
  6325. row += padding;
  6326. row += col;
  6327. padding.clear();
  6328. if ( col.size() < width ) {
  6329. padding.append( width - col.size(), ' ' );
  6330. }
  6331. } else {
  6332. padding.append( width, ' ' );
  6333. }
  6334. }
  6335. return row;
  6336. }
  6337. Columns::iterator& Columns::iterator::operator++() {
  6338. for ( size_t i = 0; i < m_columns.size(); ++i ) {
  6339. if ( m_iterators[i] != m_columns[i].end() ) {
  6340. ++m_iterators[i];
  6341. }
  6342. }
  6343. return *this;
  6344. }
  6345. Columns::iterator Columns::iterator::operator++( int ) {
  6346. iterator prev( *this );
  6347. operator++();
  6348. return prev;
  6349. }
  6350. std::ostream& operator<<( std::ostream& os, Columns const& cols ) {
  6351. bool first = true;
  6352. for ( auto line : cols ) {
  6353. if ( first ) {
  6354. first = false;
  6355. } else {
  6356. os << '\n';
  6357. }
  6358. os << line;
  6359. }
  6360. return os;
  6361. }
  6362. Columns operator+( Column const& lhs, Column const& rhs ) {
  6363. Columns cols;
  6364. cols += lhs;
  6365. cols += rhs;
  6366. return cols;
  6367. }
  6368. Columns operator+( Column&& lhs, Column&& rhs ) {
  6369. Columns cols;
  6370. cols += CATCH_MOVE( lhs );
  6371. cols += CATCH_MOVE( rhs );
  6372. return cols;
  6373. }
  6374. Columns& operator+=( Columns& lhs, Column const& rhs ) {
  6375. lhs.m_columns.push_back( rhs );
  6376. return lhs;
  6377. }
  6378. Columns& operator+=( Columns& lhs, Column&& rhs ) {
  6379. lhs.m_columns.push_back( CATCH_MOVE( rhs ) );
  6380. return lhs;
  6381. }
  6382. Columns operator+( Columns const& lhs, Column const& rhs ) {
  6383. auto combined( lhs );
  6384. combined += rhs;
  6385. return combined;
  6386. }
  6387. Columns operator+( Columns&& lhs, Column&& rhs ) {
  6388. lhs += CATCH_MOVE( rhs );
  6389. return CATCH_MOVE( lhs );
  6390. }
  6391. } // namespace TextFlow
  6392. } // namespace Catch
  6393. #include <exception>
  6394. namespace Catch {
  6395. bool uncaught_exceptions() {
  6396. #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
  6397. return false;
  6398. #elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
  6399. return std::uncaught_exceptions() > 0;
  6400. #else
  6401. return std::uncaught_exception();
  6402. #endif
  6403. }
  6404. } // end namespace Catch
  6405. namespace Catch {
  6406. WildcardPattern::WildcardPattern( std::string const& pattern,
  6407. CaseSensitive caseSensitivity )
  6408. : m_caseSensitivity( caseSensitivity ),
  6409. m_pattern( normaliseString( pattern ) )
  6410. {
  6411. if( startsWith( m_pattern, '*' ) ) {
  6412. m_pattern = m_pattern.substr( 1 );
  6413. m_wildcard = WildcardAtStart;
  6414. }
  6415. if( endsWith( m_pattern, '*' ) ) {
  6416. m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
  6417. m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
  6418. }
  6419. }
  6420. bool WildcardPattern::matches( std::string const& str ) const {
  6421. switch( m_wildcard ) {
  6422. case NoWildcard:
  6423. return m_pattern == normaliseString( str );
  6424. case WildcardAtStart:
  6425. return endsWith( normaliseString( str ), m_pattern );
  6426. case WildcardAtEnd:
  6427. return startsWith( normaliseString( str ), m_pattern );
  6428. case WildcardAtBothEnds:
  6429. return contains( normaliseString( str ), m_pattern );
  6430. default:
  6431. CATCH_INTERNAL_ERROR( "Unknown enum" );
  6432. }
  6433. }
  6434. std::string WildcardPattern::normaliseString( std::string const& str ) const {
  6435. return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );
  6436. }
  6437. }
  6438. // Note: swapping these two includes around causes MSVC to error out
  6439. // while in /permissive- mode. No, I don't know why.
  6440. // Tested on VS 2019, 18.{3, 4}.x
  6441. #include <cstdint>
  6442. #include <iomanip>
  6443. #include <type_traits>
  6444. namespace Catch {
  6445. namespace {
  6446. size_t trailingBytes(unsigned char c) {
  6447. if ((c & 0xE0) == 0xC0) {
  6448. return 2;
  6449. }
  6450. if ((c & 0xF0) == 0xE0) {
  6451. return 3;
  6452. }
  6453. if ((c & 0xF8) == 0xF0) {
  6454. return 4;
  6455. }
  6456. CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
  6457. }
  6458. uint32_t headerValue(unsigned char c) {
  6459. if ((c & 0xE0) == 0xC0) {
  6460. return c & 0x1F;
  6461. }
  6462. if ((c & 0xF0) == 0xE0) {
  6463. return c & 0x0F;
  6464. }
  6465. if ((c & 0xF8) == 0xF0) {
  6466. return c & 0x07;
  6467. }
  6468. CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
  6469. }
  6470. void hexEscapeChar(std::ostream& os, unsigned char c) {
  6471. std::ios_base::fmtflags f(os.flags());
  6472. os << "\\x"
  6473. << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
  6474. << static_cast<int>(c);
  6475. os.flags(f);
  6476. }
  6477. constexpr bool shouldNewline(XmlFormatting fmt) {
  6478. return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Newline));
  6479. }
  6480. constexpr bool shouldIndent(XmlFormatting fmt) {
  6481. return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Indent));
  6482. }
  6483. } // anonymous namespace
  6484. void XmlEncode::encodeTo( std::ostream& os ) const {
  6485. // Apostrophe escaping not necessary if we always use " to write attributes
  6486. // (see: http://www.w3.org/TR/xml/#syntax)
  6487. for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
  6488. unsigned char c = static_cast<unsigned char>(m_str[idx]);
  6489. switch (c) {
  6490. case '<': os << "&lt;"; break;
  6491. case '&': os << "&amp;"; break;
  6492. case '>':
  6493. // See: http://www.w3.org/TR/xml/#syntax
  6494. if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
  6495. os << "&gt;";
  6496. else
  6497. os << c;
  6498. break;
  6499. case '\"':
  6500. if (m_forWhat == ForAttributes)
  6501. os << "&quot;";
  6502. else
  6503. os << c;
  6504. break;
  6505. default:
  6506. // Check for control characters and invalid utf-8
  6507. // Escape control characters in standard ascii
  6508. // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
  6509. if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
  6510. hexEscapeChar(os, c);
  6511. break;
  6512. }
  6513. // Plain ASCII: Write it to stream
  6514. if (c < 0x7F) {
  6515. os << c;
  6516. break;
  6517. }
  6518. // UTF-8 territory
  6519. // Check if the encoding is valid and if it is not, hex escape bytes.
  6520. // Important: We do not check the exact decoded values for validity, only the encoding format
  6521. // First check that this bytes is a valid lead byte:
  6522. // This means that it is not encoded as 1111 1XXX
  6523. // Or as 10XX XXXX
  6524. if (c < 0xC0 ||
  6525. c >= 0xF8) {
  6526. hexEscapeChar(os, c);
  6527. break;
  6528. }
  6529. auto encBytes = trailingBytes(c);
  6530. // Are there enough bytes left to avoid accessing out-of-bounds memory?
  6531. if (idx + encBytes - 1 >= m_str.size()) {
  6532. hexEscapeChar(os, c);
  6533. break;
  6534. }
  6535. // The header is valid, check data
  6536. // The next encBytes bytes must together be a valid utf-8
  6537. // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
  6538. bool valid = true;
  6539. uint32_t value = headerValue(c);
  6540. for (std::size_t n = 1; n < encBytes; ++n) {
  6541. unsigned char nc = static_cast<unsigned char>(m_str[idx + n]);
  6542. valid &= ((nc & 0xC0) == 0x80);
  6543. value = (value << 6) | (nc & 0x3F);
  6544. }
  6545. if (
  6546. // Wrong bit pattern of following bytes
  6547. (!valid) ||
  6548. // Overlong encodings
  6549. (value < 0x80) ||
  6550. (0x80 <= value && value < 0x800 && encBytes > 2) ||
  6551. (0x800 < value && value < 0x10000 && encBytes > 3) ||
  6552. // Encoded value out of range
  6553. (value >= 0x110000)
  6554. ) {
  6555. hexEscapeChar(os, c);
  6556. break;
  6557. }
  6558. // If we got here, this is in fact a valid(ish) utf-8 sequence
  6559. for (std::size_t n = 0; n < encBytes; ++n) {
  6560. os << m_str[idx + n];
  6561. }
  6562. idx += encBytes - 1;
  6563. break;
  6564. }
  6565. }
  6566. }
  6567. std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
  6568. xmlEncode.encodeTo( os );
  6569. return os;
  6570. }
  6571. XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt )
  6572. : m_writer( writer ),
  6573. m_fmt(fmt)
  6574. {}
  6575. XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
  6576. : m_writer( other.m_writer ),
  6577. m_fmt(other.m_fmt)
  6578. {
  6579. other.m_writer = nullptr;
  6580. other.m_fmt = XmlFormatting::None;
  6581. }
  6582. XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
  6583. if ( m_writer ) {
  6584. m_writer->endElement();
  6585. }
  6586. m_writer = other.m_writer;
  6587. other.m_writer = nullptr;
  6588. m_fmt = other.m_fmt;
  6589. other.m_fmt = XmlFormatting::None;
  6590. return *this;
  6591. }
  6592. XmlWriter::ScopedElement::~ScopedElement() {
  6593. if (m_writer) {
  6594. m_writer->endElement(m_fmt);
  6595. }
  6596. }
  6597. XmlWriter::ScopedElement&
  6598. XmlWriter::ScopedElement::writeText( StringRef text, XmlFormatting fmt ) {
  6599. m_writer->writeText( text, fmt );
  6600. return *this;
  6601. }
  6602. XmlWriter::ScopedElement&
  6603. XmlWriter::ScopedElement::writeAttribute( StringRef name,
  6604. StringRef attribute ) {
  6605. m_writer->writeAttribute( name, attribute );
  6606. return *this;
  6607. }
  6608. XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
  6609. {
  6610. writeDeclaration();
  6611. }
  6612. XmlWriter::~XmlWriter() {
  6613. while (!m_tags.empty()) {
  6614. endElement();
  6615. }
  6616. newlineIfNecessary();
  6617. }
  6618. XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) {
  6619. ensureTagClosed();
  6620. newlineIfNecessary();
  6621. if (shouldIndent(fmt)) {
  6622. m_os << m_indent;
  6623. m_indent += " ";
  6624. }
  6625. m_os << '<' << name;
  6626. m_tags.push_back( name );
  6627. m_tagIsOpen = true;
  6628. applyFormatting(fmt);
  6629. return *this;
  6630. }
  6631. XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) {
  6632. ScopedElement scoped( this, fmt );
  6633. startElement( name, fmt );
  6634. return scoped;
  6635. }
  6636. XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {
  6637. m_indent = m_indent.substr(0, m_indent.size() - 2);
  6638. if( m_tagIsOpen ) {
  6639. m_os << "/>";
  6640. m_tagIsOpen = false;
  6641. } else {
  6642. newlineIfNecessary();
  6643. if (shouldIndent(fmt)) {
  6644. m_os << m_indent;
  6645. }
  6646. m_os << "</" << m_tags.back() << '>';
  6647. }
  6648. m_os << std::flush;
  6649. applyFormatting(fmt);
  6650. m_tags.pop_back();
  6651. return *this;
  6652. }
  6653. XmlWriter& XmlWriter::writeAttribute( StringRef name,
  6654. StringRef attribute ) {
  6655. if( !name.empty() && !attribute.empty() )
  6656. m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
  6657. return *this;
  6658. }
  6659. XmlWriter& XmlWriter::writeAttribute( StringRef name, bool attribute ) {
  6660. writeAttribute(name, (attribute ? "true"_sr : "false"_sr));
  6661. return *this;
  6662. }
  6663. XmlWriter& XmlWriter::writeAttribute( StringRef name,
  6664. char const* attribute ) {
  6665. writeAttribute( name, StringRef( attribute ) );
  6666. return *this;
  6667. }
  6668. XmlWriter& XmlWriter::writeText( StringRef text, XmlFormatting fmt ) {
  6669. CATCH_ENFORCE(!m_tags.empty(), "Cannot write text as top level element");
  6670. if( !text.empty() ){
  6671. bool tagWasOpen = m_tagIsOpen;
  6672. ensureTagClosed();
  6673. if (tagWasOpen && shouldIndent(fmt)) {
  6674. m_os << m_indent;
  6675. }
  6676. m_os << XmlEncode( text, XmlEncode::ForTextNodes );
  6677. applyFormatting(fmt);
  6678. }
  6679. return *this;
  6680. }
  6681. XmlWriter& XmlWriter::writeComment( StringRef text, XmlFormatting fmt ) {
  6682. ensureTagClosed();
  6683. if (shouldIndent(fmt)) {
  6684. m_os << m_indent;
  6685. }
  6686. m_os << "<!-- " << text << " -->";
  6687. applyFormatting(fmt);
  6688. return *this;
  6689. }
  6690. void XmlWriter::writeStylesheetRef( StringRef url ) {
  6691. m_os << R"(<?xml-stylesheet type="text/xsl" href=")" << url << R"("?>)" << '\n';
  6692. }
  6693. void XmlWriter::ensureTagClosed() {
  6694. if( m_tagIsOpen ) {
  6695. m_os << '>' << std::flush;
  6696. newlineIfNecessary();
  6697. m_tagIsOpen = false;
  6698. }
  6699. }
  6700. void XmlWriter::applyFormatting(XmlFormatting fmt) {
  6701. m_needsNewline = shouldNewline(fmt);
  6702. }
  6703. void XmlWriter::writeDeclaration() {
  6704. m_os << R"(<?xml version="1.0" encoding="UTF-8"?>)" << '\n';
  6705. }
  6706. void XmlWriter::newlineIfNecessary() {
  6707. if( m_needsNewline ) {
  6708. m_os << '\n' << std::flush;
  6709. m_needsNewline = false;
  6710. }
  6711. }
  6712. }
  6713. namespace Catch {
  6714. namespace Matchers {
  6715. std::string MatcherUntypedBase::toString() const {
  6716. if (m_cachedToString.empty()) {
  6717. m_cachedToString = describe();
  6718. }
  6719. return m_cachedToString;
  6720. }
  6721. MatcherUntypedBase::~MatcherUntypedBase() = default;
  6722. } // namespace Matchers
  6723. } // namespace Catch
  6724. namespace Catch {
  6725. namespace Matchers {
  6726. std::string IsEmptyMatcher::describe() const {
  6727. return "is empty";
  6728. }
  6729. std::string HasSizeMatcher::describe() const {
  6730. ReusableStringStream sstr;
  6731. sstr << "has size == " << m_target_size;
  6732. return sstr.str();
  6733. }
  6734. IsEmptyMatcher IsEmpty() {
  6735. return {};
  6736. }
  6737. HasSizeMatcher SizeIs(std::size_t sz) {
  6738. return HasSizeMatcher{ sz };
  6739. }
  6740. } // end namespace Matchers
  6741. } // end namespace Catch
  6742. namespace Catch {
  6743. namespace Matchers {
  6744. bool ExceptionMessageMatcher::match(std::exception const& ex) const {
  6745. return ex.what() == m_message;
  6746. }
  6747. std::string ExceptionMessageMatcher::describe() const {
  6748. return "exception message matches \"" + m_message + '"';
  6749. }
  6750. ExceptionMessageMatcher Message(std::string const& message) {
  6751. return ExceptionMessageMatcher(message);
  6752. }
  6753. } // namespace Matchers
  6754. } // namespace Catch
  6755. #include <algorithm>
  6756. #include <cmath>
  6757. #include <cstdlib>
  6758. #include <cstdint>
  6759. #include <sstream>
  6760. #include <iomanip>
  6761. #include <limits>
  6762. namespace Catch {
  6763. namespace {
  6764. template <typename FP>
  6765. bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {
  6766. // Comparison with NaN should always be false.
  6767. // This way we can rule it out before getting into the ugly details
  6768. if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
  6769. return false;
  6770. }
  6771. // This should also handle positive and negative zeros, infinities
  6772. const auto ulpDist = ulpDistance(lhs, rhs);
  6773. return ulpDist <= maxUlpDiff;
  6774. }
  6775. template <typename FP>
  6776. FP step(FP start, FP direction, uint64_t steps) {
  6777. for (uint64_t i = 0; i < steps; ++i) {
  6778. start = Catch::nextafter(start, direction);
  6779. }
  6780. return start;
  6781. }
  6782. // Performs equivalent check of std::fabs(lhs - rhs) <= margin
  6783. // But without the subtraction to allow for INFINITY in comparison
  6784. bool marginComparison(double lhs, double rhs, double margin) {
  6785. return (lhs + margin >= rhs) && (rhs + margin >= lhs);
  6786. }
  6787. template <typename FloatingPoint>
  6788. void write(std::ostream& out, FloatingPoint num) {
  6789. out << std::scientific
  6790. << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
  6791. << num;
  6792. }
  6793. } // end anonymous namespace
  6794. namespace Matchers {
  6795. namespace Detail {
  6796. enum class FloatingPointKind : uint8_t {
  6797. Float,
  6798. Double
  6799. };
  6800. } // end namespace Detail
  6801. WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
  6802. :m_target{ target }, m_margin{ margin } {
  6803. CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
  6804. << " Margin has to be non-negative.");
  6805. }
  6806. // Performs equivalent check of std::fabs(lhs - rhs) <= margin
  6807. // But without the subtraction to allow for INFINITY in comparison
  6808. bool WithinAbsMatcher::match(double const& matchee) const {
  6809. return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
  6810. }
  6811. std::string WithinAbsMatcher::describe() const {
  6812. return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
  6813. }
  6814. WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType)
  6815. :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
  6816. CATCH_ENFORCE(m_type == Detail::FloatingPointKind::Double
  6817. || m_ulps < (std::numeric_limits<uint32_t>::max)(),
  6818. "Provided ULP is impossibly large for a float comparison.");
  6819. CATCH_ENFORCE( std::numeric_limits<double>::is_iec559,
  6820. "WithinUlp matcher only supports platforms with "
  6821. "IEEE-754 compatible floating point representation" );
  6822. }
  6823. #if defined(__clang__)
  6824. #pragma clang diagnostic push
  6825. // Clang <3.5 reports on the default branch in the switch below
  6826. #pragma clang diagnostic ignored "-Wunreachable-code"
  6827. #endif
  6828. bool WithinUlpsMatcher::match(double const& matchee) const {
  6829. switch (m_type) {
  6830. case Detail::FloatingPointKind::Float:
  6831. return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
  6832. case Detail::FloatingPointKind::Double:
  6833. return almostEqualUlps<double>(matchee, m_target, m_ulps);
  6834. default:
  6835. CATCH_INTERNAL_ERROR( "Unknown Detail::FloatingPointKind value" );
  6836. }
  6837. }
  6838. #if defined(__clang__)
  6839. #pragma clang diagnostic pop
  6840. #endif
  6841. std::string WithinUlpsMatcher::describe() const {
  6842. std::stringstream ret;
  6843. ret << "is within " << m_ulps << " ULPs of ";
  6844. if (m_type == Detail::FloatingPointKind::Float) {
  6845. write(ret, static_cast<float>(m_target));
  6846. ret << 'f';
  6847. } else {
  6848. write(ret, m_target);
  6849. }
  6850. ret << " ([";
  6851. if (m_type == Detail::FloatingPointKind::Double) {
  6852. write( ret,
  6853. step( m_target,
  6854. -std::numeric_limits<double>::infinity(),
  6855. m_ulps ) );
  6856. ret << ", ";
  6857. write( ret,
  6858. step( m_target,
  6859. std::numeric_limits<double>::infinity(),
  6860. m_ulps ) );
  6861. } else {
  6862. // We have to cast INFINITY to float because of MinGW, see #1782
  6863. write( ret,
  6864. step( static_cast<float>( m_target ),
  6865. -std::numeric_limits<float>::infinity(),
  6866. m_ulps ) );
  6867. ret << ", ";
  6868. write( ret,
  6869. step( static_cast<float>( m_target ),
  6870. std::numeric_limits<float>::infinity(),
  6871. m_ulps ) );
  6872. }
  6873. ret << "])";
  6874. return ret.str();
  6875. }
  6876. WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
  6877. m_target(target),
  6878. m_epsilon(epsilon){
  6879. CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense.");
  6880. CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense.");
  6881. }
  6882. bool WithinRelMatcher::match(double const& matchee) const {
  6883. const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
  6884. return marginComparison(matchee, m_target,
  6885. std::isinf(relMargin)? 0 : relMargin);
  6886. }
  6887. std::string WithinRelMatcher::describe() const {
  6888. Catch::ReusableStringStream sstr;
  6889. sstr << "and " << ::Catch::Detail::stringify(m_target) << " are within " << m_epsilon * 100. << "% of each other";
  6890. return sstr.str();
  6891. }
  6892. WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
  6893. return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Double);
  6894. }
  6895. WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
  6896. return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Float);
  6897. }
  6898. WithinAbsMatcher WithinAbs(double target, double margin) {
  6899. return WithinAbsMatcher(target, margin);
  6900. }
  6901. WithinRelMatcher WithinRel(double target, double eps) {
  6902. return WithinRelMatcher(target, eps);
  6903. }
  6904. WithinRelMatcher WithinRel(double target) {
  6905. return WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
  6906. }
  6907. WithinRelMatcher WithinRel(float target, float eps) {
  6908. return WithinRelMatcher(target, eps);
  6909. }
  6910. WithinRelMatcher WithinRel(float target) {
  6911. return WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
  6912. }
  6913. bool IsNaNMatcher::match( double const& matchee ) const {
  6914. return std::isnan( matchee );
  6915. }
  6916. std::string IsNaNMatcher::describe() const {
  6917. using namespace std::string_literals;
  6918. return "is NaN"s;
  6919. }
  6920. IsNaNMatcher IsNaN() { return IsNaNMatcher(); }
  6921. } // namespace Matchers
  6922. } // namespace Catch
  6923. std::string Catch::Matchers::Detail::finalizeDescription(const std::string& desc) {
  6924. if (desc.empty()) {
  6925. return "matches undescribed predicate";
  6926. } else {
  6927. return "matches predicate: \"" + desc + '"';
  6928. }
  6929. }
  6930. namespace Catch {
  6931. namespace Matchers {
  6932. std::string AllTrueMatcher::describe() const { return "contains only true"; }
  6933. AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
  6934. std::string NoneTrueMatcher::describe() const { return "contains no true"; }
  6935. NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
  6936. std::string AnyTrueMatcher::describe() const { return "contains at least one true"; }
  6937. AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
  6938. } // namespace Matchers
  6939. } // namespace Catch
  6940. #include <regex>
  6941. namespace Catch {
  6942. namespace Matchers {
  6943. CasedString::CasedString( std::string const& str, CaseSensitive caseSensitivity )
  6944. : m_caseSensitivity( caseSensitivity ),
  6945. m_str( adjustString( str ) )
  6946. {}
  6947. std::string CasedString::adjustString( std::string const& str ) const {
  6948. return m_caseSensitivity == CaseSensitive::No
  6949. ? toLower( str )
  6950. : str;
  6951. }
  6952. StringRef CasedString::caseSensitivitySuffix() const {
  6953. return m_caseSensitivity == CaseSensitive::Yes
  6954. ? StringRef()
  6955. : " (case insensitive)"_sr;
  6956. }
  6957. StringMatcherBase::StringMatcherBase( StringRef operation, CasedString const& comparator )
  6958. : m_comparator( comparator ),
  6959. m_operation( operation ) {
  6960. }
  6961. std::string StringMatcherBase::describe() const {
  6962. std::string description;
  6963. description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
  6964. m_comparator.caseSensitivitySuffix().size());
  6965. description += m_operation;
  6966. description += ": \"";
  6967. description += m_comparator.m_str;
  6968. description += '"';
  6969. description += m_comparator.caseSensitivitySuffix();
  6970. return description;
  6971. }
  6972. StringEqualsMatcher::StringEqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals"_sr, comparator ) {}
  6973. bool StringEqualsMatcher::match( std::string const& source ) const {
  6974. return m_comparator.adjustString( source ) == m_comparator.m_str;
  6975. }
  6976. StringContainsMatcher::StringContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains"_sr, comparator ) {}
  6977. bool StringContainsMatcher::match( std::string const& source ) const {
  6978. return contains( m_comparator.adjustString( source ), m_comparator.m_str );
  6979. }
  6980. StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with"_sr, comparator ) {}
  6981. bool StartsWithMatcher::match( std::string const& source ) const {
  6982. return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
  6983. }
  6984. EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with"_sr, comparator ) {}
  6985. bool EndsWithMatcher::match( std::string const& source ) const {
  6986. return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
  6987. }
  6988. RegexMatcher::RegexMatcher(std::string regex, CaseSensitive caseSensitivity): m_regex(CATCH_MOVE(regex)), m_caseSensitivity(caseSensitivity) {}
  6989. bool RegexMatcher::match(std::string const& matchee) const {
  6990. auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
  6991. if (m_caseSensitivity == CaseSensitive::No) {
  6992. flags |= std::regex::icase;
  6993. }
  6994. auto reg = std::regex(m_regex, flags);
  6995. return std::regex_match(matchee, reg);
  6996. }
  6997. std::string RegexMatcher::describe() const {
  6998. return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Yes)? " case sensitively" : " case insensitively");
  6999. }
  7000. StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity ) {
  7001. return StringEqualsMatcher( CasedString( str, caseSensitivity) );
  7002. }
  7003. StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity ) {
  7004. return StringContainsMatcher( CasedString( str, caseSensitivity) );
  7005. }
  7006. EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity ) {
  7007. return EndsWithMatcher( CasedString( str, caseSensitivity) );
  7008. }
  7009. StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity ) {
  7010. return StartsWithMatcher( CasedString( str, caseSensitivity) );
  7011. }
  7012. RegexMatcher Matches(std::string const& regex, CaseSensitive caseSensitivity) {
  7013. return RegexMatcher(regex, caseSensitivity);
  7014. }
  7015. } // namespace Matchers
  7016. } // namespace Catch
  7017. namespace Catch {
  7018. namespace Matchers {
  7019. MatcherGenericBase::~MatcherGenericBase() = default;
  7020. namespace Detail {
  7021. std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end) {
  7022. std::string description;
  7023. std::size_t combined_size = 4;
  7024. for ( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
  7025. combined_size += desc->size();
  7026. }
  7027. combined_size += static_cast<size_t>(descriptions_end - descriptions_begin - 1) * combine.size();
  7028. description.reserve(combined_size);
  7029. description += "( ";
  7030. bool first = true;
  7031. for( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
  7032. if( first )
  7033. first = false;
  7034. else
  7035. description += combine;
  7036. description += *desc;
  7037. }
  7038. description += " )";
  7039. return description;
  7040. }
  7041. } // namespace Detail
  7042. } // namespace Matchers
  7043. } // namespace Catch
  7044. namespace Catch {
  7045. // This is the general overload that takes a any string matcher
  7046. // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
  7047. // the Equals matcher (so the header does not mention matchers)
  7048. void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher ) {
  7049. std::string exceptionMessage = Catch::translateActiveException();
  7050. MatchExpr<std::string, StringMatcher const&> expr( CATCH_MOVE(exceptionMessage), matcher );
  7051. handler.handleExpr( expr );
  7052. }
  7053. } // namespace Catch
  7054. #include <ostream>
  7055. namespace Catch {
  7056. AutomakeReporter::~AutomakeReporter() = default;
  7057. void AutomakeReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
  7058. // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR.
  7059. m_stream << ":test-result: ";
  7060. if ( _testCaseStats.totals.testCases.skipped > 0 ) {
  7061. m_stream << "SKIP";
  7062. } else if (_testCaseStats.totals.assertions.allPassed()) {
  7063. m_stream << "PASS";
  7064. } else if (_testCaseStats.totals.assertions.allOk()) {
  7065. m_stream << "XFAIL";
  7066. } else {
  7067. m_stream << "FAIL";
  7068. }
  7069. m_stream << ' ' << _testCaseStats.testInfo->name << '\n';
  7070. StreamingReporterBase::testCaseEnded(_testCaseStats);
  7071. }
  7072. void AutomakeReporter::skipTest(TestCaseInfo const& testInfo) {
  7073. m_stream << ":test-result: SKIP " << testInfo.name << '\n';
  7074. }
  7075. } // end namespace Catch
  7076. namespace Catch {
  7077. ReporterBase::ReporterBase( ReporterConfig&& config ):
  7078. IEventListener( config.fullConfig() ),
  7079. m_wrapped_stream( CATCH_MOVE(config).takeStream() ),
  7080. m_stream( m_wrapped_stream->stream() ),
  7081. m_colour( makeColourImpl( config.colourMode(), m_wrapped_stream.get() ) ),
  7082. m_customOptions( config.customOptions() )
  7083. {}
  7084. ReporterBase::~ReporterBase() = default;
  7085. void ReporterBase::listReporters(
  7086. std::vector<ReporterDescription> const& descriptions ) {
  7087. defaultListReporters(m_stream, descriptions, m_config->verbosity());
  7088. }
  7089. void ReporterBase::listListeners(
  7090. std::vector<ListenerDescription> const& descriptions ) {
  7091. defaultListListeners( m_stream, descriptions );
  7092. }
  7093. void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
  7094. defaultListTests(m_stream,
  7095. m_colour.get(),
  7096. tests,
  7097. m_config->hasTestFilters(),
  7098. m_config->verbosity());
  7099. }
  7100. void ReporterBase::listTags(std::vector<TagInfo> const& tags) {
  7101. defaultListTags( m_stream, tags, m_config->hasTestFilters() );
  7102. }
  7103. } // namespace Catch
  7104. #include <ostream>
  7105. namespace Catch {
  7106. namespace {
  7107. // Colour::LightGrey
  7108. static constexpr Colour::Code compactDimColour = Colour::FileName;
  7109. #ifdef CATCH_PLATFORM_MAC
  7110. static constexpr Catch::StringRef compactFailedString = "FAILED"_sr;
  7111. static constexpr Catch::StringRef compactPassedString = "PASSED"_sr;
  7112. #else
  7113. static constexpr Catch::StringRef compactFailedString = "failed"_sr;
  7114. static constexpr Catch::StringRef compactPassedString = "passed"_sr;
  7115. #endif
  7116. // Implementation of CompactReporter formatting
  7117. class AssertionPrinter {
  7118. public:
  7119. AssertionPrinter& operator= (AssertionPrinter const&) = delete;
  7120. AssertionPrinter(AssertionPrinter const&) = delete;
  7121. AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages, ColourImpl* colourImpl_)
  7122. : stream(_stream)
  7123. , result(_stats.assertionResult)
  7124. , messages(_stats.infoMessages)
  7125. , itMessage(_stats.infoMessages.begin())
  7126. , printInfoMessages(_printInfoMessages)
  7127. , colourImpl(colourImpl_)
  7128. {}
  7129. void print() {
  7130. printSourceInfo();
  7131. itMessage = messages.begin();
  7132. switch (result.getResultType()) {
  7133. case ResultWas::Ok:
  7134. printResultType(Colour::ResultSuccess, compactPassedString);
  7135. printOriginalExpression();
  7136. printReconstructedExpression();
  7137. if (!result.hasExpression())
  7138. printRemainingMessages(Colour::None);
  7139. else
  7140. printRemainingMessages();
  7141. break;
  7142. case ResultWas::ExpressionFailed:
  7143. if (result.isOk())
  7144. printResultType(Colour::ResultSuccess, compactFailedString + " - but was ok"_sr);
  7145. else
  7146. printResultType(Colour::Error, compactFailedString);
  7147. printOriginalExpression();
  7148. printReconstructedExpression();
  7149. printRemainingMessages();
  7150. break;
  7151. case ResultWas::ThrewException:
  7152. printResultType(Colour::Error, compactFailedString);
  7153. printIssue("unexpected exception with message:");
  7154. printMessage();
  7155. printExpressionWas();
  7156. printRemainingMessages();
  7157. break;
  7158. case ResultWas::FatalErrorCondition:
  7159. printResultType(Colour::Error, compactFailedString);
  7160. printIssue("fatal error condition with message:");
  7161. printMessage();
  7162. printExpressionWas();
  7163. printRemainingMessages();
  7164. break;
  7165. case ResultWas::DidntThrowException:
  7166. printResultType(Colour::Error, compactFailedString);
  7167. printIssue("expected exception, got none");
  7168. printExpressionWas();
  7169. printRemainingMessages();
  7170. break;
  7171. case ResultWas::Info:
  7172. printResultType(Colour::None, "info"_sr);
  7173. printMessage();
  7174. printRemainingMessages();
  7175. break;
  7176. case ResultWas::Warning:
  7177. printResultType(Colour::None, "warning"_sr);
  7178. printMessage();
  7179. printRemainingMessages();
  7180. break;
  7181. case ResultWas::ExplicitFailure:
  7182. printResultType(Colour::Error, compactFailedString);
  7183. printIssue("explicitly");
  7184. printRemainingMessages(Colour::None);
  7185. break;
  7186. case ResultWas::ExplicitSkip:
  7187. printResultType(Colour::Skip, "skipped"_sr);
  7188. printMessage();
  7189. printRemainingMessages();
  7190. break;
  7191. // These cases are here to prevent compiler warnings
  7192. case ResultWas::Unknown:
  7193. case ResultWas::FailureBit:
  7194. case ResultWas::Exception:
  7195. printResultType(Colour::Error, "** internal error **");
  7196. break;
  7197. }
  7198. }
  7199. private:
  7200. void printSourceInfo() const {
  7201. stream << colourImpl->guardColour( Colour::FileName )
  7202. << result.getSourceInfo() << ':';
  7203. }
  7204. void printResultType(Colour::Code colour, StringRef passOrFail) const {
  7205. if (!passOrFail.empty()) {
  7206. stream << colourImpl->guardColour(colour) << ' ' << passOrFail;
  7207. stream << ':';
  7208. }
  7209. }
  7210. void printIssue(char const* issue) const {
  7211. stream << ' ' << issue;
  7212. }
  7213. void printExpressionWas() {
  7214. if (result.hasExpression()) {
  7215. stream << ';';
  7216. {
  7217. stream << colourImpl->guardColour(compactDimColour) << " expression was:";
  7218. }
  7219. printOriginalExpression();
  7220. }
  7221. }
  7222. void printOriginalExpression() const {
  7223. if (result.hasExpression()) {
  7224. stream << ' ' << result.getExpression();
  7225. }
  7226. }
  7227. void printReconstructedExpression() const {
  7228. if (result.hasExpandedExpression()) {
  7229. stream << colourImpl->guardColour(compactDimColour) << " for: ";
  7230. stream << result.getExpandedExpression();
  7231. }
  7232. }
  7233. void printMessage() {
  7234. if (itMessage != messages.end()) {
  7235. stream << " '" << itMessage->message << '\'';
  7236. ++itMessage;
  7237. }
  7238. }
  7239. void printRemainingMessages(Colour::Code colour = compactDimColour) {
  7240. if (itMessage == messages.end())
  7241. return;
  7242. const auto itEnd = messages.cend();
  7243. const auto N = static_cast<std::size_t>(itEnd - itMessage);
  7244. stream << colourImpl->guardColour( colour ) << " with "
  7245. << pluralise( N, "message"_sr ) << ':';
  7246. while (itMessage != itEnd) {
  7247. // If this assertion is a warning ignore any INFO messages
  7248. if (printInfoMessages || itMessage->type != ResultWas::Info) {
  7249. printMessage();
  7250. if (itMessage != itEnd) {
  7251. stream << colourImpl->guardColour(compactDimColour) << " and";
  7252. }
  7253. continue;
  7254. }
  7255. ++itMessage;
  7256. }
  7257. }
  7258. private:
  7259. std::ostream& stream;
  7260. AssertionResult const& result;
  7261. std::vector<MessageInfo> const& messages;
  7262. std::vector<MessageInfo>::const_iterator itMessage;
  7263. bool printInfoMessages;
  7264. ColourImpl* colourImpl;
  7265. };
  7266. } // anon namespace
  7267. std::string CompactReporter::getDescription() {
  7268. return "Reports test results on a single line, suitable for IDEs";
  7269. }
  7270. void CompactReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
  7271. m_stream << "No test cases matched '" << unmatchedSpec << "'\n";
  7272. }
  7273. void CompactReporter::testRunStarting( TestRunInfo const& ) {
  7274. if ( m_config->testSpec().hasFilters() ) {
  7275. m_stream << m_colour->guardColour( Colour::BrightYellow )
  7276. << "Filters: "
  7277. << m_config->testSpec()
  7278. << '\n';
  7279. }
  7280. m_stream << "RNG seed: " << getSeed() << '\n';
  7281. }
  7282. void CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
  7283. AssertionResult const& result = _assertionStats.assertionResult;
  7284. bool printInfoMessages = true;
  7285. // Drop out if result was successful and we're not printing those
  7286. if( !m_config->includeSuccessfulResults() && result.isOk() ) {
  7287. if( result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip )
  7288. return;
  7289. printInfoMessages = false;
  7290. }
  7291. AssertionPrinter printer( m_stream, _assertionStats, printInfoMessages, m_colour.get() );
  7292. printer.print();
  7293. m_stream << '\n' << std::flush;
  7294. }
  7295. void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
  7296. double dur = _sectionStats.durationInSeconds;
  7297. if ( shouldShowDuration( *m_config, dur ) ) {
  7298. m_stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << '\n' << std::flush;
  7299. }
  7300. }
  7301. void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {
  7302. printTestRunTotals( m_stream, *m_colour, _testRunStats.totals );
  7303. m_stream << "\n\n" << std::flush;
  7304. StreamingReporterBase::testRunEnded( _testRunStats );
  7305. }
  7306. CompactReporter::~CompactReporter() = default;
  7307. } // end namespace Catch
  7308. #include <cstdio>
  7309. #if defined(_MSC_VER)
  7310. #pragma warning(push)
  7311. #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
  7312. // Note that 4062 (not all labels are handled and default is missing) is enabled
  7313. #endif
  7314. #if defined(__clang__)
  7315. # pragma clang diagnostic push
  7316. // For simplicity, benchmarking-only helpers are always enabled
  7317. # pragma clang diagnostic ignored "-Wunused-function"
  7318. #endif
  7319. namespace Catch {
  7320. namespace {
  7321. // Formatter impl for ConsoleReporter
  7322. class ConsoleAssertionPrinter {
  7323. public:
  7324. ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;
  7325. ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
  7326. ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, ColourImpl* colourImpl_, bool _printInfoMessages)
  7327. : stream(_stream),
  7328. stats(_stats),
  7329. result(_stats.assertionResult),
  7330. colour(Colour::None),
  7331. messages(_stats.infoMessages),
  7332. colourImpl(colourImpl_),
  7333. printInfoMessages(_printInfoMessages) {
  7334. switch (result.getResultType()) {
  7335. case ResultWas::Ok:
  7336. colour = Colour::Success;
  7337. passOrFail = "PASSED"_sr;
  7338. //if( result.hasMessage() )
  7339. if (messages.size() == 1)
  7340. messageLabel = "with message"_sr;
  7341. if (messages.size() > 1)
  7342. messageLabel = "with messages"_sr;
  7343. break;
  7344. case ResultWas::ExpressionFailed:
  7345. if (result.isOk()) {
  7346. colour = Colour::Success;
  7347. passOrFail = "FAILED - but was ok"_sr;
  7348. } else {
  7349. colour = Colour::Error;
  7350. passOrFail = "FAILED"_sr;
  7351. }
  7352. if (messages.size() == 1)
  7353. messageLabel = "with message"_sr;
  7354. if (messages.size() > 1)
  7355. messageLabel = "with messages"_sr;
  7356. break;
  7357. case ResultWas::ThrewException:
  7358. colour = Colour::Error;
  7359. passOrFail = "FAILED"_sr;
  7360. // todo switch
  7361. switch (messages.size()) { case 0:
  7362. messageLabel = "due to unexpected exception with "_sr;
  7363. break;
  7364. case 1:
  7365. messageLabel = "due to unexpected exception with message"_sr;
  7366. break;
  7367. default:
  7368. messageLabel = "due to unexpected exception with messages"_sr;
  7369. break;
  7370. }
  7371. break;
  7372. case ResultWas::FatalErrorCondition:
  7373. colour = Colour::Error;
  7374. passOrFail = "FAILED"_sr;
  7375. messageLabel = "due to a fatal error condition"_sr;
  7376. break;
  7377. case ResultWas::DidntThrowException:
  7378. colour = Colour::Error;
  7379. passOrFail = "FAILED"_sr;
  7380. messageLabel = "because no exception was thrown where one was expected"_sr;
  7381. break;
  7382. case ResultWas::Info:
  7383. messageLabel = "info"_sr;
  7384. break;
  7385. case ResultWas::Warning:
  7386. messageLabel = "warning"_sr;
  7387. break;
  7388. case ResultWas::ExplicitFailure:
  7389. passOrFail = "FAILED"_sr;
  7390. colour = Colour::Error;
  7391. if (messages.size() == 1)
  7392. messageLabel = "explicitly with message"_sr;
  7393. if (messages.size() > 1)
  7394. messageLabel = "explicitly with messages"_sr;
  7395. break;
  7396. case ResultWas::ExplicitSkip:
  7397. colour = Colour::Skip;
  7398. passOrFail = "SKIPPED"_sr;
  7399. if (messages.size() == 1)
  7400. messageLabel = "explicitly with message"_sr;
  7401. if (messages.size() > 1)
  7402. messageLabel = "explicitly with messages"_sr;
  7403. break;
  7404. // These cases are here to prevent compiler warnings
  7405. case ResultWas::Unknown:
  7406. case ResultWas::FailureBit:
  7407. case ResultWas::Exception:
  7408. passOrFail = "** internal error **"_sr;
  7409. colour = Colour::Error;
  7410. break;
  7411. }
  7412. }
  7413. void print() const {
  7414. printSourceInfo();
  7415. if (stats.totals.assertions.total() > 0) {
  7416. printResultType();
  7417. printOriginalExpression();
  7418. printReconstructedExpression();
  7419. } else {
  7420. stream << '\n';
  7421. }
  7422. printMessage();
  7423. }
  7424. private:
  7425. void printResultType() const {
  7426. if (!passOrFail.empty()) {
  7427. stream << colourImpl->guardColour(colour) << passOrFail << ":\n";
  7428. }
  7429. }
  7430. void printOriginalExpression() const {
  7431. if (result.hasExpression()) {
  7432. stream << colourImpl->guardColour( Colour::OriginalExpression )
  7433. << " " << result.getExpressionInMacro() << '\n';
  7434. }
  7435. }
  7436. void printReconstructedExpression() const {
  7437. if (result.hasExpandedExpression()) {
  7438. stream << "with expansion:\n";
  7439. stream << colourImpl->guardColour( Colour::ReconstructedExpression )
  7440. << TextFlow::Column( result.getExpandedExpression() )
  7441. .indent( 2 )
  7442. << '\n';
  7443. }
  7444. }
  7445. void printMessage() const {
  7446. if (!messageLabel.empty())
  7447. stream << messageLabel << ':' << '\n';
  7448. for (auto const& msg : messages) {
  7449. // If this assertion is a warning ignore any INFO messages
  7450. if (printInfoMessages || msg.type != ResultWas::Info)
  7451. stream << TextFlow::Column(msg.message).indent(2) << '\n';
  7452. }
  7453. }
  7454. void printSourceInfo() const {
  7455. stream << colourImpl->guardColour( Colour::FileName )
  7456. << result.getSourceInfo() << ": ";
  7457. }
  7458. std::ostream& stream;
  7459. AssertionStats const& stats;
  7460. AssertionResult const& result;
  7461. Colour::Code colour;
  7462. StringRef passOrFail;
  7463. StringRef messageLabel;
  7464. std::vector<MessageInfo> const& messages;
  7465. ColourImpl* colourImpl;
  7466. bool printInfoMessages;
  7467. };
  7468. std::size_t makeRatio( std::uint64_t number, std::uint64_t total ) {
  7469. const auto ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
  7470. return (ratio == 0 && number > 0) ? 1 : static_cast<std::size_t>(ratio);
  7471. }
  7472. std::size_t&
  7473. findMax( std::size_t& i, std::size_t& j, std::size_t& k, std::size_t& l ) {
  7474. if (i > j && i > k && i > l)
  7475. return i;
  7476. else if (j > k && j > l)
  7477. return j;
  7478. else if (k > l)
  7479. return k;
  7480. else
  7481. return l;
  7482. }
  7483. struct ColumnBreak {};
  7484. struct RowBreak {};
  7485. struct OutputFlush {};
  7486. class Duration {
  7487. enum class Unit {
  7488. Auto,
  7489. Nanoseconds,
  7490. Microseconds,
  7491. Milliseconds,
  7492. Seconds,
  7493. Minutes
  7494. };
  7495. static const uint64_t s_nanosecondsInAMicrosecond = 1000;
  7496. static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
  7497. static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
  7498. static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
  7499. double m_inNanoseconds;
  7500. Unit m_units;
  7501. public:
  7502. explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
  7503. : m_inNanoseconds(inNanoseconds),
  7504. m_units(units) {
  7505. if (m_units == Unit::Auto) {
  7506. if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
  7507. m_units = Unit::Nanoseconds;
  7508. else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
  7509. m_units = Unit::Microseconds;
  7510. else if (m_inNanoseconds < s_nanosecondsInASecond)
  7511. m_units = Unit::Milliseconds;
  7512. else if (m_inNanoseconds < s_nanosecondsInAMinute)
  7513. m_units = Unit::Seconds;
  7514. else
  7515. m_units = Unit::Minutes;
  7516. }
  7517. }
  7518. auto value() const -> double {
  7519. switch (m_units) {
  7520. case Unit::Microseconds:
  7521. return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
  7522. case Unit::Milliseconds:
  7523. return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
  7524. case Unit::Seconds:
  7525. return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
  7526. case Unit::Minutes:
  7527. return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
  7528. default:
  7529. return m_inNanoseconds;
  7530. }
  7531. }
  7532. StringRef unitsAsString() const {
  7533. switch (m_units) {
  7534. case Unit::Nanoseconds:
  7535. return "ns"_sr;
  7536. case Unit::Microseconds:
  7537. return "us"_sr;
  7538. case Unit::Milliseconds:
  7539. return "ms"_sr;
  7540. case Unit::Seconds:
  7541. return "s"_sr;
  7542. case Unit::Minutes:
  7543. return "m"_sr;
  7544. default:
  7545. return "** internal error **"_sr;
  7546. }
  7547. }
  7548. friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
  7549. return os << duration.value() << ' ' << duration.unitsAsString();
  7550. }
  7551. };
  7552. } // end anon namespace
  7553. enum class Justification { Left, Right };
  7554. struct ColumnInfo {
  7555. std::string name;
  7556. std::size_t width;
  7557. Justification justification;
  7558. };
  7559. class TablePrinter {
  7560. std::ostream& m_os;
  7561. std::vector<ColumnInfo> m_columnInfos;
  7562. ReusableStringStream m_oss;
  7563. int m_currentColumn = -1;
  7564. bool m_isOpen = false;
  7565. public:
  7566. TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
  7567. : m_os( os ),
  7568. m_columnInfos( CATCH_MOVE( columnInfos ) ) {}
  7569. auto columnInfos() const -> std::vector<ColumnInfo> const& {
  7570. return m_columnInfos;
  7571. }
  7572. void open() {
  7573. if (!m_isOpen) {
  7574. m_isOpen = true;
  7575. *this << RowBreak();
  7576. TextFlow::Columns headerCols;
  7577. for (auto const& info : m_columnInfos) {
  7578. assert(info.width > 2);
  7579. headerCols += TextFlow::Column(info.name).width(info.width - 2);
  7580. headerCols += TextFlow::Spacer( 2 );
  7581. }
  7582. m_os << headerCols << '\n';
  7583. m_os << lineOfChars('-') << '\n';
  7584. }
  7585. }
  7586. void close() {
  7587. if (m_isOpen) {
  7588. *this << RowBreak();
  7589. m_os << '\n' << std::flush;
  7590. m_isOpen = false;
  7591. }
  7592. }
  7593. template<typename T>
  7594. friend TablePrinter& operator<< (TablePrinter& tp, T const& value) {
  7595. tp.m_oss << value;
  7596. return tp;
  7597. }
  7598. friend TablePrinter& operator<< (TablePrinter& tp, ColumnBreak) {
  7599. auto colStr = tp.m_oss.str();
  7600. const auto strSize = colStr.size();
  7601. tp.m_oss.str("");
  7602. tp.open();
  7603. if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
  7604. tp.m_currentColumn = -1;
  7605. tp.m_os << '\n';
  7606. }
  7607. tp.m_currentColumn++;
  7608. auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
  7609. auto padding = (strSize + 1 < colInfo.width)
  7610. ? std::string(colInfo.width - (strSize + 1), ' ')
  7611. : std::string();
  7612. if (colInfo.justification == Justification::Left)
  7613. tp.m_os << colStr << padding << ' ';
  7614. else
  7615. tp.m_os << padding << colStr << ' ';
  7616. return tp;
  7617. }
  7618. friend TablePrinter& operator<< (TablePrinter& tp, RowBreak) {
  7619. if (tp.m_currentColumn > 0) {
  7620. tp.m_os << '\n';
  7621. tp.m_currentColumn = -1;
  7622. }
  7623. return tp;
  7624. }
  7625. friend TablePrinter& operator<<(TablePrinter& tp, OutputFlush) {
  7626. tp.m_os << std::flush;
  7627. return tp;
  7628. }
  7629. };
  7630. ConsoleReporter::ConsoleReporter(ReporterConfig&& config):
  7631. StreamingReporterBase( CATCH_MOVE( config ) ),
  7632. m_tablePrinter(Detail::make_unique<TablePrinter>(m_stream,
  7633. [&config]() -> std::vector<ColumnInfo> {
  7634. if (config.fullConfig()->benchmarkNoAnalysis())
  7635. {
  7636. return{
  7637. { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, Justification::Left },
  7638. { " samples", 14, Justification::Right },
  7639. { " iterations", 14, Justification::Right },
  7640. { " mean", 14, Justification::Right }
  7641. };
  7642. }
  7643. else
  7644. {
  7645. return{
  7646. { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, Justification::Left },
  7647. { "samples mean std dev", 14, Justification::Right },
  7648. { "iterations low mean low std dev", 14, Justification::Right },
  7649. { "est run time high mean high std dev", 14, Justification::Right }
  7650. };
  7651. }
  7652. }())) {}
  7653. ConsoleReporter::~ConsoleReporter() = default;
  7654. std::string ConsoleReporter::getDescription() {
  7655. return "Reports test results as plain lines of text";
  7656. }
  7657. void ConsoleReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
  7658. m_stream << "No test cases matched '" << unmatchedSpec << "'\n";
  7659. }
  7660. void ConsoleReporter::reportInvalidTestSpec( StringRef arg ) {
  7661. m_stream << "Invalid Filter: " << arg << '\n';
  7662. }
  7663. void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
  7664. void ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
  7665. AssertionResult const& result = _assertionStats.assertionResult;
  7666. bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
  7667. // Drop out if result was successful but we're not printing them.
  7668. // TODO: Make configurable whether skips should be printed
  7669. if (!includeResults && result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip)
  7670. return;
  7671. lazyPrint();
  7672. ConsoleAssertionPrinter printer(m_stream, _assertionStats, m_colour.get(), includeResults);
  7673. printer.print();
  7674. m_stream << '\n' << std::flush;
  7675. }
  7676. void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
  7677. m_tablePrinter->close();
  7678. m_headerPrinted = false;
  7679. StreamingReporterBase::sectionStarting(_sectionInfo);
  7680. }
  7681. void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
  7682. m_tablePrinter->close();
  7683. if (_sectionStats.missingAssertions) {
  7684. lazyPrint();
  7685. auto guard =
  7686. m_colour->guardColour( Colour::ResultError ).engage( m_stream );
  7687. if (m_sectionStack.size() > 1)
  7688. m_stream << "\nNo assertions in section";
  7689. else
  7690. m_stream << "\nNo assertions in test case";
  7691. m_stream << " '" << _sectionStats.sectionInfo.name << "'\n\n" << std::flush;
  7692. }
  7693. double dur = _sectionStats.durationInSeconds;
  7694. if (shouldShowDuration(*m_config, dur)) {
  7695. m_stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << '\n' << std::flush;
  7696. }
  7697. if (m_headerPrinted) {
  7698. m_headerPrinted = false;
  7699. }
  7700. StreamingReporterBase::sectionEnded(_sectionStats);
  7701. }
  7702. void ConsoleReporter::benchmarkPreparing( StringRef name ) {
  7703. lazyPrintWithoutClosingBenchmarkTable();
  7704. auto nameCol = TextFlow::Column( static_cast<std::string>( name ) )
  7705. .width( m_tablePrinter->columnInfos()[0].width - 2 );
  7706. bool firstLine = true;
  7707. for (auto line : nameCol) {
  7708. if (!firstLine)
  7709. (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
  7710. else
  7711. firstLine = false;
  7712. (*m_tablePrinter) << line << ColumnBreak();
  7713. }
  7714. }
  7715. void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
  7716. (*m_tablePrinter) << info.samples << ColumnBreak()
  7717. << info.iterations << ColumnBreak();
  7718. if ( !m_config->benchmarkNoAnalysis() ) {
  7719. ( *m_tablePrinter )
  7720. << Duration( info.estimatedDuration ) << ColumnBreak();
  7721. }
  7722. ( *m_tablePrinter ) << OutputFlush{};
  7723. }
  7724. void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
  7725. if (m_config->benchmarkNoAnalysis())
  7726. {
  7727. (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
  7728. }
  7729. else
  7730. {
  7731. (*m_tablePrinter) << ColumnBreak()
  7732. << Duration(stats.mean.point.count()) << ColumnBreak()
  7733. << Duration(stats.mean.lower_bound.count()) << ColumnBreak()
  7734. << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
  7735. << Duration(stats.standardDeviation.point.count()) << ColumnBreak()
  7736. << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
  7737. << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
  7738. }
  7739. }
  7740. void ConsoleReporter::benchmarkFailed( StringRef error ) {
  7741. auto guard = m_colour->guardColour( Colour::Red ).engage( m_stream );
  7742. (*m_tablePrinter)
  7743. << "Benchmark failed (" << error << ')'
  7744. << ColumnBreak() << RowBreak();
  7745. }
  7746. void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
  7747. m_tablePrinter->close();
  7748. StreamingReporterBase::testCaseEnded(_testCaseStats);
  7749. m_headerPrinted = false;
  7750. }
  7751. void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
  7752. printTotalsDivider(_testRunStats.totals);
  7753. printTestRunTotals( m_stream, *m_colour, _testRunStats.totals );
  7754. m_stream << '\n' << std::flush;
  7755. StreamingReporterBase::testRunEnded(_testRunStats);
  7756. }
  7757. void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) {
  7758. StreamingReporterBase::testRunStarting(_testRunInfo);
  7759. if ( m_config->testSpec().hasFilters() ) {
  7760. m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
  7761. << m_config->testSpec() << '\n';
  7762. }
  7763. m_stream << "Randomness seeded to: " << getSeed() << '\n';
  7764. }
  7765. void ConsoleReporter::lazyPrint() {
  7766. m_tablePrinter->close();
  7767. lazyPrintWithoutClosingBenchmarkTable();
  7768. }
  7769. void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
  7770. if ( !m_testRunInfoPrinted ) {
  7771. lazyPrintRunInfo();
  7772. }
  7773. if (!m_headerPrinted) {
  7774. printTestCaseAndSectionHeader();
  7775. m_headerPrinted = true;
  7776. }
  7777. }
  7778. void ConsoleReporter::lazyPrintRunInfo() {
  7779. m_stream << '\n'
  7780. << lineOfChars( '~' ) << '\n'
  7781. << m_colour->guardColour( Colour::SecondaryText )
  7782. << currentTestRunInfo.name << " is a Catch2 v" << libraryVersion()
  7783. << " host application.\n"
  7784. << "Run with -? for options\n\n";
  7785. m_testRunInfoPrinted = true;
  7786. }
  7787. void ConsoleReporter::printTestCaseAndSectionHeader() {
  7788. assert(!m_sectionStack.empty());
  7789. printOpenHeader(currentTestCaseInfo->name);
  7790. if (m_sectionStack.size() > 1) {
  7791. auto guard = m_colour->guardColour( Colour::Headers ).engage( m_stream );
  7792. auto
  7793. it = m_sectionStack.begin() + 1, // Skip first section (test case)
  7794. itEnd = m_sectionStack.end();
  7795. for (; it != itEnd; ++it)
  7796. printHeaderString(it->name, 2);
  7797. }
  7798. SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
  7799. m_stream << lineOfChars( '-' ) << '\n'
  7800. << m_colour->guardColour( Colour::FileName ) << lineInfo << '\n'
  7801. << lineOfChars( '.' ) << "\n\n"
  7802. << std::flush;
  7803. }
  7804. void ConsoleReporter::printClosedHeader(std::string const& _name) {
  7805. printOpenHeader(_name);
  7806. m_stream << lineOfChars('.') << '\n';
  7807. }
  7808. void ConsoleReporter::printOpenHeader(std::string const& _name) {
  7809. m_stream << lineOfChars('-') << '\n';
  7810. {
  7811. auto guard = m_colour->guardColour( Colour::Headers ).engage( m_stream );
  7812. printHeaderString(_name);
  7813. }
  7814. }
  7815. void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {
  7816. // We want to get a bit fancy with line breaking here, so that subsequent
  7817. // lines start after ":" if one is present, e.g.
  7818. // ```
  7819. // blablabla: Fancy
  7820. // linebreaking
  7821. // ```
  7822. // but we also want to avoid problems with overly long indentation causing
  7823. // the text to take up too many lines, e.g.
  7824. // ```
  7825. // blablabla: F
  7826. // a
  7827. // n
  7828. // c
  7829. // y
  7830. // .
  7831. // .
  7832. // .
  7833. // ```
  7834. // So we limit the prefix indentation check to first quarter of the possible
  7835. // width
  7836. std::size_t idx = _string.find( ": " );
  7837. if ( idx != std::string::npos && idx < CATCH_CONFIG_CONSOLE_WIDTH / 4 ) {
  7838. idx += 2;
  7839. } else {
  7840. idx = 0;
  7841. }
  7842. m_stream << TextFlow::Column( _string )
  7843. .indent( indent + idx )
  7844. .initialIndent( indent )
  7845. << '\n';
  7846. }
  7847. void ConsoleReporter::printTotalsDivider(Totals const& totals) {
  7848. if (totals.testCases.total() > 0) {
  7849. std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
  7850. std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
  7851. std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
  7852. std::size_t skippedRatio = makeRatio(totals.testCases.skipped, totals.testCases.total());
  7853. while (failedRatio + failedButOkRatio + passedRatio + skippedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
  7854. findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)++;
  7855. while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
  7856. findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)--;
  7857. m_stream << m_colour->guardColour( Colour::Error )
  7858. << std::string( failedRatio, '=' )
  7859. << m_colour->guardColour( Colour::ResultExpectedFailure )
  7860. << std::string( failedButOkRatio, '=' );
  7861. if ( totals.testCases.allPassed() ) {
  7862. m_stream << m_colour->guardColour( Colour::ResultSuccess )
  7863. << std::string( passedRatio, '=' );
  7864. } else {
  7865. m_stream << m_colour->guardColour( Colour::Success )
  7866. << std::string( passedRatio, '=' );
  7867. }
  7868. m_stream << m_colour->guardColour( Colour::Skip )
  7869. << std::string( skippedRatio, '=' );
  7870. } else {
  7871. m_stream << m_colour->guardColour( Colour::Warning )
  7872. << std::string( CATCH_CONFIG_CONSOLE_WIDTH - 1, '=' );
  7873. }
  7874. m_stream << '\n';
  7875. }
  7876. } // end namespace Catch
  7877. #if defined(_MSC_VER)
  7878. #pragma warning(pop)
  7879. #endif
  7880. #if defined(__clang__)
  7881. # pragma clang diagnostic pop
  7882. #endif
  7883. #include <algorithm>
  7884. #include <cassert>
  7885. namespace Catch {
  7886. namespace {
  7887. struct BySectionInfo {
  7888. BySectionInfo( SectionInfo const& other ): m_other( other ) {}
  7889. BySectionInfo( BySectionInfo const& other ) = default;
  7890. bool operator()(
  7891. Detail::unique_ptr<CumulativeReporterBase::SectionNode> const&
  7892. node ) const {
  7893. return (
  7894. ( node->stats.sectionInfo.name == m_other.name ) &&
  7895. ( node->stats.sectionInfo.lineInfo == m_other.lineInfo ) );
  7896. }
  7897. void operator=( BySectionInfo const& ) = delete;
  7898. private:
  7899. SectionInfo const& m_other;
  7900. };
  7901. } // namespace
  7902. namespace Detail {
  7903. AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
  7904. AssertionStats const& assertion ):
  7905. m_assertion( assertion ) {}
  7906. AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
  7907. BenchmarkStats<> const& benchmark ):
  7908. m_benchmark( benchmark ) {}
  7909. bool AssertionOrBenchmarkResult::isAssertion() const {
  7910. return m_assertion.some();
  7911. }
  7912. bool AssertionOrBenchmarkResult::isBenchmark() const {
  7913. return m_benchmark.some();
  7914. }
  7915. AssertionStats const& AssertionOrBenchmarkResult::asAssertion() const {
  7916. assert(m_assertion.some());
  7917. return *m_assertion;
  7918. }
  7919. BenchmarkStats<> const& AssertionOrBenchmarkResult::asBenchmark() const {
  7920. assert(m_benchmark.some());
  7921. return *m_benchmark;
  7922. }
  7923. }
  7924. CumulativeReporterBase::~CumulativeReporterBase() = default;
  7925. void CumulativeReporterBase::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
  7926. m_sectionStack.back()->assertionsAndBenchmarks.emplace_back(benchmarkStats);
  7927. }
  7928. void
  7929. CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
  7930. // We need a copy, because SectionStats expect to take ownership
  7931. SectionStats incompleteStats( SectionInfo(sectionInfo), Counts(), 0, false );
  7932. SectionNode* node;
  7933. if ( m_sectionStack.empty() ) {
  7934. if ( !m_rootSection ) {
  7935. m_rootSection =
  7936. Detail::make_unique<SectionNode>( incompleteStats );
  7937. }
  7938. node = m_rootSection.get();
  7939. } else {
  7940. SectionNode& parentNode = *m_sectionStack.back();
  7941. auto it = std::find_if( parentNode.childSections.begin(),
  7942. parentNode.childSections.end(),
  7943. BySectionInfo( sectionInfo ) );
  7944. if ( it == parentNode.childSections.end() ) {
  7945. auto newNode =
  7946. Detail::make_unique<SectionNode>( incompleteStats );
  7947. node = newNode.get();
  7948. parentNode.childSections.push_back( CATCH_MOVE( newNode ) );
  7949. } else {
  7950. node = it->get();
  7951. }
  7952. }
  7953. m_deepestSection = node;
  7954. m_sectionStack.push_back( node );
  7955. }
  7956. void CumulativeReporterBase::assertionEnded(
  7957. AssertionStats const& assertionStats ) {
  7958. assert( !m_sectionStack.empty() );
  7959. // AssertionResult holds a pointer to a temporary DecomposedExpression,
  7960. // which getExpandedExpression() calls to build the expression string.
  7961. // Our section stack copy of the assertionResult will likely outlive the
  7962. // temporary, so it must be expanded or discarded now to avoid calling
  7963. // a destroyed object later.
  7964. if ( m_shouldStoreFailedAssertions &&
  7965. !assertionStats.assertionResult.isOk() ) {
  7966. static_cast<void>(
  7967. assertionStats.assertionResult.getExpandedExpression() );
  7968. }
  7969. if ( m_shouldStoreSuccesfulAssertions &&
  7970. assertionStats.assertionResult.isOk() ) {
  7971. static_cast<void>(
  7972. assertionStats.assertionResult.getExpandedExpression() );
  7973. }
  7974. SectionNode& sectionNode = *m_sectionStack.back();
  7975. sectionNode.assertionsAndBenchmarks.emplace_back( assertionStats );
  7976. }
  7977. void CumulativeReporterBase::sectionEnded( SectionStats const& sectionStats ) {
  7978. assert( !m_sectionStack.empty() );
  7979. SectionNode& node = *m_sectionStack.back();
  7980. node.stats = sectionStats;
  7981. m_sectionStack.pop_back();
  7982. }
  7983. void CumulativeReporterBase::testCaseEnded(
  7984. TestCaseStats const& testCaseStats ) {
  7985. auto node = Detail::make_unique<TestCaseNode>( testCaseStats );
  7986. assert( m_sectionStack.size() == 0 );
  7987. node->children.push_back( CATCH_MOVE(m_rootSection) );
  7988. m_testCases.push_back( CATCH_MOVE(node) );
  7989. assert( m_deepestSection );
  7990. m_deepestSection->stdOut = testCaseStats.stdOut;
  7991. m_deepestSection->stdErr = testCaseStats.stdErr;
  7992. }
  7993. void CumulativeReporterBase::testRunEnded( TestRunStats const& testRunStats ) {
  7994. assert(!m_testRun && "CumulativeReporterBase assumes there can only be one test run");
  7995. m_testRun = Detail::make_unique<TestRunNode>( testRunStats );
  7996. m_testRun->children.swap( m_testCases );
  7997. testRunEndedCumulative();
  7998. }
  7999. bool CumulativeReporterBase::SectionNode::hasAnyAssertions() const {
  8000. return std::any_of(
  8001. assertionsAndBenchmarks.begin(),
  8002. assertionsAndBenchmarks.end(),
  8003. []( Detail::AssertionOrBenchmarkResult const& res ) {
  8004. return res.isAssertion();
  8005. } );
  8006. }
  8007. } // end namespace Catch
  8008. namespace Catch {
  8009. void EventListenerBase::fatalErrorEncountered( StringRef ) {}
  8010. void EventListenerBase::benchmarkPreparing( StringRef ) {}
  8011. void EventListenerBase::benchmarkStarting( BenchmarkInfo const& ) {}
  8012. void EventListenerBase::benchmarkEnded( BenchmarkStats<> const& ) {}
  8013. void EventListenerBase::benchmarkFailed( StringRef ) {}
  8014. void EventListenerBase::assertionStarting( AssertionInfo const& ) {}
  8015. void EventListenerBase::assertionEnded( AssertionStats const& ) {}
  8016. void EventListenerBase::listReporters(
  8017. std::vector<ReporterDescription> const& ) {}
  8018. void EventListenerBase::listListeners(
  8019. std::vector<ListenerDescription> const& ) {}
  8020. void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {}
  8021. void EventListenerBase::listTags( std::vector<TagInfo> const& ) {}
  8022. void EventListenerBase::noMatchingTestCases( StringRef ) {}
  8023. void EventListenerBase::reportInvalidTestSpec( StringRef ) {}
  8024. void EventListenerBase::testRunStarting( TestRunInfo const& ) {}
  8025. void EventListenerBase::testCaseStarting( TestCaseInfo const& ) {}
  8026. void EventListenerBase::testCasePartialStarting(TestCaseInfo const&, uint64_t) {}
  8027. void EventListenerBase::sectionStarting( SectionInfo const& ) {}
  8028. void EventListenerBase::sectionEnded( SectionStats const& ) {}
  8029. void EventListenerBase::testCasePartialEnded(TestCaseStats const&, uint64_t) {}
  8030. void EventListenerBase::testCaseEnded( TestCaseStats const& ) {}
  8031. void EventListenerBase::testRunEnded( TestRunStats const& ) {}
  8032. void EventListenerBase::skipTest( TestCaseInfo const& ) {}
  8033. } // namespace Catch
  8034. #include <algorithm>
  8035. #include <cfloat>
  8036. #include <cstdio>
  8037. #include <ostream>
  8038. #include <iomanip>
  8039. namespace Catch {
  8040. namespace {
  8041. void listTestNamesOnly(std::ostream& out,
  8042. std::vector<TestCaseHandle> const& tests) {
  8043. for (auto const& test : tests) {
  8044. auto const& testCaseInfo = test.getTestCaseInfo();
  8045. if (startsWith(testCaseInfo.name, '#')) {
  8046. out << '"' << testCaseInfo.name << '"';
  8047. } else {
  8048. out << testCaseInfo.name;
  8049. }
  8050. out << '\n';
  8051. }
  8052. out << std::flush;
  8053. }
  8054. } // end unnamed namespace
  8055. // Because formatting using c++ streams is stateful, drop down to C is
  8056. // required Alternatively we could use stringstream, but its performance
  8057. // is... not good.
  8058. std::string getFormattedDuration( double duration ) {
  8059. // Max exponent + 1 is required to represent the whole part
  8060. // + 1 for decimal point
  8061. // + 3 for the 3 decimal places
  8062. // + 1 for null terminator
  8063. const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
  8064. char buffer[maxDoubleSize];
  8065. // Save previous errno, to prevent sprintf from overwriting it
  8066. ErrnoGuard guard;
  8067. #ifdef _MSC_VER
  8068. size_t printedLength = static_cast<size_t>(
  8069. sprintf_s( buffer, "%.3f", duration ) );
  8070. #else
  8071. size_t printedLength = static_cast<size_t>(
  8072. std::snprintf( buffer, maxDoubleSize, "%.3f", duration ) );
  8073. #endif
  8074. return std::string( buffer, printedLength );
  8075. }
  8076. bool shouldShowDuration( IConfig const& config, double duration ) {
  8077. if ( config.showDurations() == ShowDurations::Always ) {
  8078. return true;
  8079. }
  8080. if ( config.showDurations() == ShowDurations::Never ) {
  8081. return false;
  8082. }
  8083. const double min = config.minDuration();
  8084. return min >= 0 && duration >= min;
  8085. }
  8086. std::string serializeFilters( std::vector<std::string> const& filters ) {
  8087. // We add a ' ' separator between each filter
  8088. size_t serialized_size = filters.size() - 1;
  8089. for (auto const& filter : filters) {
  8090. serialized_size += filter.size();
  8091. }
  8092. std::string serialized;
  8093. serialized.reserve(serialized_size);
  8094. bool first = true;
  8095. for (auto const& filter : filters) {
  8096. if (!first) {
  8097. serialized.push_back(' ');
  8098. }
  8099. first = false;
  8100. serialized.append(filter);
  8101. }
  8102. return serialized;
  8103. }
  8104. std::ostream& operator<<( std::ostream& out, lineOfChars value ) {
  8105. for ( size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx ) {
  8106. out.put( value.c );
  8107. }
  8108. return out;
  8109. }
  8110. void
  8111. defaultListReporters( std::ostream& out,
  8112. std::vector<ReporterDescription> const& descriptions,
  8113. Verbosity verbosity ) {
  8114. out << "Available reporters:\n";
  8115. const auto maxNameLen =
  8116. std::max_element( descriptions.begin(),
  8117. descriptions.end(),
  8118. []( ReporterDescription const& lhs,
  8119. ReporterDescription const& rhs ) {
  8120. return lhs.name.size() < rhs.name.size();
  8121. } )
  8122. ->name.size();
  8123. for ( auto const& desc : descriptions ) {
  8124. if ( verbosity == Verbosity::Quiet ) {
  8125. out << TextFlow::Column( desc.name )
  8126. .indent( 2 )
  8127. .width( 5 + maxNameLen )
  8128. << '\n';
  8129. } else {
  8130. out << TextFlow::Column( desc.name + ':' )
  8131. .indent( 2 )
  8132. .width( 5 + maxNameLen ) +
  8133. TextFlow::Column( desc.description )
  8134. .initialIndent( 0 )
  8135. .indent( 2 )
  8136. .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
  8137. << '\n';
  8138. }
  8139. }
  8140. out << '\n' << std::flush;
  8141. }
  8142. void defaultListListeners( std::ostream& out,
  8143. std::vector<ListenerDescription> const& descriptions ) {
  8144. out << "Registered listeners:\n";
  8145. if(descriptions.empty()) {
  8146. return;
  8147. }
  8148. const auto maxNameLen =
  8149. std::max_element( descriptions.begin(),
  8150. descriptions.end(),
  8151. []( ListenerDescription const& lhs,
  8152. ListenerDescription const& rhs ) {
  8153. return lhs.name.size() < rhs.name.size();
  8154. } )
  8155. ->name.size();
  8156. for ( auto const& desc : descriptions ) {
  8157. out << TextFlow::Column( static_cast<std::string>( desc.name ) +
  8158. ':' )
  8159. .indent( 2 )
  8160. .width( maxNameLen + 5 ) +
  8161. TextFlow::Column( desc.description )
  8162. .initialIndent( 0 )
  8163. .indent( 2 )
  8164. .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
  8165. << '\n';
  8166. }
  8167. out << '\n' << std::flush;
  8168. }
  8169. void defaultListTags( std::ostream& out,
  8170. std::vector<TagInfo> const& tags,
  8171. bool isFiltered ) {
  8172. if ( isFiltered ) {
  8173. out << "Tags for matching test cases:\n";
  8174. } else {
  8175. out << "All available tags:\n";
  8176. }
  8177. for ( auto const& tagCount : tags ) {
  8178. ReusableStringStream rss;
  8179. rss << " " << std::setw( 2 ) << tagCount.count << " ";
  8180. auto str = rss.str();
  8181. auto wrapper = TextFlow::Column( tagCount.all() )
  8182. .initialIndent( 0 )
  8183. .indent( str.size() )
  8184. .width( CATCH_CONFIG_CONSOLE_WIDTH - 10 );
  8185. out << str << wrapper << '\n';
  8186. }
  8187. out << pluralise(tags.size(), "tag"_sr) << "\n\n" << std::flush;
  8188. }
  8189. void defaultListTests(std::ostream& out, ColourImpl* streamColour, std::vector<TestCaseHandle> const& tests, bool isFiltered, Verbosity verbosity) {
  8190. // We special case this to provide the equivalent of old
  8191. // `--list-test-names-only`, which could then be used by the
  8192. // `--input-file` option.
  8193. if (verbosity == Verbosity::Quiet) {
  8194. listTestNamesOnly(out, tests);
  8195. return;
  8196. }
  8197. if (isFiltered) {
  8198. out << "Matching test cases:\n";
  8199. } else {
  8200. out << "All available test cases:\n";
  8201. }
  8202. for (auto const& test : tests) {
  8203. auto const& testCaseInfo = test.getTestCaseInfo();
  8204. Colour::Code colour = testCaseInfo.isHidden()
  8205. ? Colour::SecondaryText
  8206. : Colour::None;
  8207. auto colourGuard = streamColour->guardColour( colour ).engage( out );
  8208. out << TextFlow::Column(testCaseInfo.name).indent(2) << '\n';
  8209. if (verbosity >= Verbosity::High) {
  8210. out << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << '\n';
  8211. }
  8212. if (!testCaseInfo.tags.empty() &&
  8213. verbosity > Verbosity::Quiet) {
  8214. out << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
  8215. }
  8216. }
  8217. if (isFiltered) {
  8218. out << pluralise(tests.size(), "matching test case"_sr);
  8219. } else {
  8220. out << pluralise(tests.size(), "test case"_sr);
  8221. }
  8222. out << "\n\n" << std::flush;
  8223. }
  8224. namespace {
  8225. class SummaryColumn {
  8226. public:
  8227. SummaryColumn( std::string suffix, Colour::Code colour ):
  8228. m_suffix( CATCH_MOVE( suffix ) ), m_colour( colour ) {}
  8229. SummaryColumn&& addRow( std::uint64_t count ) && {
  8230. std::string row = std::to_string(count);
  8231. auto const new_width = std::max( m_width, row.size() );
  8232. if ( new_width > m_width ) {
  8233. for ( auto& oldRow : m_rows ) {
  8234. oldRow.insert( 0, new_width - m_width, ' ' );
  8235. }
  8236. } else {
  8237. row.insert( 0, m_width - row.size(), ' ' );
  8238. }
  8239. m_width = new_width;
  8240. m_rows.push_back( row );
  8241. return std::move( *this );
  8242. }
  8243. std::string const& getSuffix() const { return m_suffix; }
  8244. Colour::Code getColour() const { return m_colour; }
  8245. std::string const& getRow( std::size_t index ) const {
  8246. return m_rows[index];
  8247. }
  8248. private:
  8249. std::string m_suffix;
  8250. Colour::Code m_colour;
  8251. std::size_t m_width = 0;
  8252. std::vector<std::string> m_rows;
  8253. };
  8254. void printSummaryRow( std::ostream& stream,
  8255. ColourImpl& colour,
  8256. StringRef label,
  8257. std::vector<SummaryColumn> const& cols,
  8258. std::size_t row ) {
  8259. for ( auto const& col : cols ) {
  8260. auto const& value = col.getRow( row );
  8261. auto const& suffix = col.getSuffix();
  8262. if ( suffix.empty() ) {
  8263. stream << label << ": ";
  8264. if ( value != "0" ) {
  8265. stream << value;
  8266. } else {
  8267. stream << colour.guardColour( Colour::Warning )
  8268. << "- none -";
  8269. }
  8270. } else if ( value != "0" ) {
  8271. stream << colour.guardColour( Colour::LightGrey ) << " | "
  8272. << colour.guardColour( col.getColour() ) << value
  8273. << ' ' << suffix;
  8274. }
  8275. }
  8276. stream << '\n';
  8277. }
  8278. } // namespace
  8279. void printTestRunTotals( std::ostream& stream,
  8280. ColourImpl& streamColour,
  8281. Totals const& totals ) {
  8282. if ( totals.testCases.total() == 0 ) {
  8283. stream << streamColour.guardColour( Colour::Warning )
  8284. << "No tests ran\n";
  8285. return;
  8286. }
  8287. if ( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
  8288. stream << streamColour.guardColour( Colour::ResultSuccess )
  8289. << "All tests passed";
  8290. stream << " ("
  8291. << pluralise( totals.assertions.passed, "assertion"_sr )
  8292. << " in "
  8293. << pluralise( totals.testCases.passed, "test case"_sr )
  8294. << ')' << '\n';
  8295. return;
  8296. }
  8297. std::vector<SummaryColumn> columns;
  8298. // Don't include "skipped assertions" in total count
  8299. const auto totalAssertionCount =
  8300. totals.assertions.total() - totals.assertions.skipped;
  8301. columns.push_back( SummaryColumn( "", Colour::None )
  8302. .addRow( totals.testCases.total() )
  8303. .addRow( totalAssertionCount ) );
  8304. columns.push_back( SummaryColumn( "passed", Colour::Success )
  8305. .addRow( totals.testCases.passed )
  8306. .addRow( totals.assertions.passed ) );
  8307. columns.push_back( SummaryColumn( "failed", Colour::ResultError )
  8308. .addRow( totals.testCases.failed )
  8309. .addRow( totals.assertions.failed ) );
  8310. columns.push_back( SummaryColumn( "skipped", Colour::Skip )
  8311. .addRow( totals.testCases.skipped )
  8312. // Don't print "skipped assertions"
  8313. .addRow( 0 ) );
  8314. columns.push_back(
  8315. SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
  8316. .addRow( totals.testCases.failedButOk )
  8317. .addRow( totals.assertions.failedButOk ) );
  8318. printSummaryRow( stream, streamColour, "test cases"_sr, columns, 0 );
  8319. printSummaryRow( stream, streamColour, "assertions"_sr, columns, 1 );
  8320. }
  8321. } // namespace Catch
  8322. //
  8323. namespace Catch {
  8324. namespace {
  8325. void writeSourceInfo( JsonObjectWriter& writer,
  8326. SourceLineInfo const& sourceInfo ) {
  8327. auto source_location_writer =
  8328. writer.write( "source-location"_sr ).writeObject();
  8329. source_location_writer.write( "filename"_sr )
  8330. .write( sourceInfo.file );
  8331. source_location_writer.write( "line"_sr ).write( sourceInfo.line );
  8332. }
  8333. void writeTags( JsonArrayWriter writer, std::vector<Tag> const& tags ) {
  8334. for ( auto const& tag : tags ) {
  8335. writer.write( tag.original );
  8336. }
  8337. }
  8338. void writeProperties( JsonArrayWriter writer,
  8339. TestCaseInfo const& info ) {
  8340. if ( info.isHidden() ) { writer.write( "is-hidden"_sr ); }
  8341. if ( info.okToFail() ) { writer.write( "ok-to-fail"_sr ); }
  8342. if ( info.expectedToFail() ) {
  8343. writer.write( "expected-to-fail"_sr );
  8344. }
  8345. if ( info.throws() ) { writer.write( "throws"_sr ); }
  8346. }
  8347. } // namespace
  8348. JsonReporter::JsonReporter( ReporterConfig&& config ):
  8349. StreamingReporterBase{ CATCH_MOVE( config ) } {
  8350. m_preferences.shouldRedirectStdOut = true;
  8351. // TBD: Do we want to report all assertions? XML reporter does
  8352. // not, but for machine-parseable reporters I think the answer
  8353. // should be yes.
  8354. m_preferences.shouldReportAllAssertions = true;
  8355. m_objectWriters.emplace( m_stream );
  8356. m_writers.emplace( Writer::Object );
  8357. auto& writer = m_objectWriters.top();
  8358. writer.write( "version"_sr ).write( 1 );
  8359. {
  8360. auto metadata_writer = writer.write( "metadata"_sr ).writeObject();
  8361. metadata_writer.write( "name"_sr ).write( m_config->name() );
  8362. metadata_writer.write( "rng-seed"_sr ).write( m_config->rngSeed() );
  8363. metadata_writer.write( "catch2-version"_sr )
  8364. .write( libraryVersion() );
  8365. if ( m_config->testSpec().hasFilters() ) {
  8366. metadata_writer.write( "filters"_sr )
  8367. .write( m_config->testSpec() );
  8368. }
  8369. }
  8370. }
  8371. JsonReporter::~JsonReporter() {
  8372. endListing();
  8373. // TODO: Ensure this closes the top level object, add asserts
  8374. assert( m_writers.size() == 1 && "Only the top level object should be open" );
  8375. assert( m_writers.top() == Writer::Object );
  8376. endObject();
  8377. m_stream << '\n' << std::flush;
  8378. assert( m_writers.empty() );
  8379. }
  8380. JsonArrayWriter& JsonReporter::startArray() {
  8381. m_arrayWriters.emplace( m_arrayWriters.top().writeArray() );
  8382. m_writers.emplace( Writer::Array );
  8383. return m_arrayWriters.top();
  8384. }
  8385. JsonArrayWriter& JsonReporter::startArray( StringRef key ) {
  8386. m_arrayWriters.emplace(
  8387. m_objectWriters.top().write( key ).writeArray() );
  8388. m_writers.emplace( Writer::Array );
  8389. return m_arrayWriters.top();
  8390. }
  8391. JsonObjectWriter& JsonReporter::startObject() {
  8392. m_objectWriters.emplace( m_arrayWriters.top().writeObject() );
  8393. m_writers.emplace( Writer::Object );
  8394. return m_objectWriters.top();
  8395. }
  8396. JsonObjectWriter& JsonReporter::startObject( StringRef key ) {
  8397. m_objectWriters.emplace(
  8398. m_objectWriters.top().write( key ).writeObject() );
  8399. m_writers.emplace( Writer::Object );
  8400. return m_objectWriters.top();
  8401. }
  8402. void JsonReporter::endObject() {
  8403. assert( isInside( Writer::Object ) );
  8404. m_objectWriters.pop();
  8405. m_writers.pop();
  8406. }
  8407. void JsonReporter::endArray() {
  8408. assert( isInside( Writer::Array ) );
  8409. m_arrayWriters.pop();
  8410. m_writers.pop();
  8411. }
  8412. bool JsonReporter::isInside( Writer writer ) {
  8413. return !m_writers.empty() && m_writers.top() == writer;
  8414. }
  8415. void JsonReporter::startListing() {
  8416. if ( !m_startedListing ) { startObject( "listings"_sr ); }
  8417. m_startedListing = true;
  8418. }
  8419. void JsonReporter::endListing() {
  8420. if ( m_startedListing ) { endObject(); }
  8421. m_startedListing = false;
  8422. }
  8423. std::string JsonReporter::getDescription() {
  8424. return "Outputs listings as JSON. Test listing is Work-in-Progress!";
  8425. }
  8426. void JsonReporter::testRunStarting( TestRunInfo const& runInfo ) {
  8427. StreamingReporterBase::testRunStarting( runInfo );
  8428. endListing();
  8429. assert( isInside( Writer::Object ) );
  8430. startObject( "test-run"_sr );
  8431. startArray( "test-cases"_sr );
  8432. }
  8433. static void writeCounts( JsonObjectWriter&& writer, Counts const& counts ) {
  8434. writer.write( "passed"_sr ).write( counts.passed );
  8435. writer.write( "failed"_sr ).write( counts.failed );
  8436. writer.write( "fail-but-ok"_sr ).write( counts.failedButOk );
  8437. writer.write( "skipped"_sr ).write( counts.skipped );
  8438. }
  8439. void JsonReporter::testRunEnded(TestRunStats const& runStats) {
  8440. assert( isInside( Writer::Array ) );
  8441. // End "test-cases"
  8442. endArray();
  8443. {
  8444. auto totals =
  8445. m_objectWriters.top().write( "totals"_sr ).writeObject();
  8446. writeCounts( totals.write( "assertions"_sr ).writeObject(),
  8447. runStats.totals.assertions );
  8448. writeCounts( totals.write( "test-cases"_sr ).writeObject(),
  8449. runStats.totals.testCases );
  8450. }
  8451. // End the "test-run" object
  8452. endObject();
  8453. }
  8454. void JsonReporter::testCaseStarting( TestCaseInfo const& tcInfo ) {
  8455. StreamingReporterBase::testCaseStarting( tcInfo );
  8456. assert( isInside( Writer::Array ) &&
  8457. "We should be in the 'test-cases' array" );
  8458. startObject();
  8459. // "test-info" prelude
  8460. {
  8461. auto testInfo =
  8462. m_objectWriters.top().write( "test-info"_sr ).writeObject();
  8463. // TODO: handle testName vs className!!
  8464. testInfo.write( "name"_sr ).write( tcInfo.name );
  8465. writeSourceInfo(testInfo, tcInfo.lineInfo);
  8466. writeTags( testInfo.write( "tags"_sr ).writeArray(), tcInfo.tags );
  8467. writeProperties( testInfo.write( "properties"_sr ).writeArray(),
  8468. tcInfo );
  8469. }
  8470. // Start the array for individual test runs (testCasePartial pairs)
  8471. startArray( "runs"_sr );
  8472. }
  8473. void JsonReporter::testCaseEnded( TestCaseStats const& tcStats ) {
  8474. StreamingReporterBase::testCaseEnded( tcStats );
  8475. // We need to close the 'runs' array before finishing the test case
  8476. assert( isInside( Writer::Array ) );
  8477. endArray();
  8478. {
  8479. auto totals =
  8480. m_objectWriters.top().write( "totals"_sr ).writeObject();
  8481. writeCounts( totals.write( "assertions"_sr ).writeObject(),
  8482. tcStats.totals.assertions );
  8483. // We do not write the test case totals, because there will always be just one test case here.
  8484. // TODO: overall "result" -> success, skip, fail here? Or in partial result?
  8485. }
  8486. // We do not write out stderr/stdout, because we instead wrote those out in partial runs
  8487. // TODO: aborting?
  8488. // And we also close this test case's object
  8489. assert( isInside( Writer::Object ) );
  8490. endObject();
  8491. }
  8492. void JsonReporter::testCasePartialStarting( TestCaseInfo const& /*tcInfo*/,
  8493. uint64_t index ) {
  8494. startObject();
  8495. m_objectWriters.top().write( "run-idx"_sr ).write( index );
  8496. startArray( "path"_sr );
  8497. // TODO: we want to delay most of the printing to the 'root' section
  8498. // TODO: childSection key name?
  8499. }
  8500. void JsonReporter::testCasePartialEnded( TestCaseStats const& tcStats,
  8501. uint64_t /*index*/ ) {
  8502. // Fixme: the top level section handles this.
  8503. //// path object
  8504. endArray();
  8505. if ( !tcStats.stdOut.empty() ) {
  8506. m_objectWriters.top()
  8507. .write( "captured-stdout"_sr )
  8508. .write( tcStats.stdOut );
  8509. }
  8510. if ( !tcStats.stdErr.empty() ) {
  8511. m_objectWriters.top()
  8512. .write( "captured-stderr"_sr )
  8513. .write( tcStats.stdErr );
  8514. }
  8515. {
  8516. auto totals =
  8517. m_objectWriters.top().write( "totals"_sr ).writeObject();
  8518. writeCounts( totals.write( "assertions"_sr ).writeObject(),
  8519. tcStats.totals.assertions );
  8520. // We do not write the test case totals, because there will
  8521. // always be just one test case here.
  8522. // TODO: overall "result" -> success, skip, fail here? Or in
  8523. // partial result?
  8524. }
  8525. // TODO: aborting?
  8526. // run object
  8527. endObject();
  8528. }
  8529. void JsonReporter::sectionStarting( SectionInfo const& sectionInfo ) {
  8530. assert( isInside( Writer::Array ) &&
  8531. "Section should always start inside an object" );
  8532. // We want to nest top level sections, even though it shares name
  8533. // and source loc with the TEST_CASE
  8534. auto& sectionObject = startObject();
  8535. sectionObject.write( "kind"_sr ).write( "section"_sr );
  8536. sectionObject.write( "name"_sr ).write( sectionInfo.name );
  8537. writeSourceInfo( m_objectWriters.top(), sectionInfo.lineInfo );
  8538. // TBD: Do we want to create this event lazily? It would become
  8539. // rather complex, but we could do it, and it would look
  8540. // better for empty sections. OTOH, empty sections should
  8541. // be rare.
  8542. startArray( "path"_sr );
  8543. }
  8544. void JsonReporter::sectionEnded( SectionStats const& /*sectionStats */) {
  8545. // End the subpath array
  8546. endArray();
  8547. // TODO: metadata
  8548. // TODO: what info do we have here?
  8549. // End the section object
  8550. endObject();
  8551. }
  8552. void JsonReporter::assertionStarting( AssertionInfo const& /*assertionInfo*/ ) {}
  8553. void JsonReporter::assertionEnded( AssertionStats const& assertionStats ) {
  8554. // TODO: There is lot of different things to handle here, but
  8555. // we can fill it in later, after we show that the basic
  8556. // outline and streaming reporter impl works well enough.
  8557. //if ( !m_config->includeSuccessfulResults()
  8558. // && assertionStats.assertionResult.isOk() ) {
  8559. // return;
  8560. //}
  8561. assert( isInside( Writer::Array ) );
  8562. auto assertionObject = m_arrayWriters.top().writeObject();
  8563. assertionObject.write( "kind"_sr ).write( "assertion"_sr );
  8564. writeSourceInfo( assertionObject,
  8565. assertionStats.assertionResult.getSourceInfo() );
  8566. assertionObject.write( "status"_sr )
  8567. .write( assertionStats.assertionResult.isOk() );
  8568. // TODO: handling of result.
  8569. // TODO: messages
  8570. // TODO: totals?
  8571. }
  8572. void JsonReporter::benchmarkPreparing( StringRef name ) { (void)name; }
  8573. void JsonReporter::benchmarkStarting( BenchmarkInfo const& ) {}
  8574. void JsonReporter::benchmarkEnded( BenchmarkStats<> const& ) {}
  8575. void JsonReporter::benchmarkFailed( StringRef error ) { (void)error; }
  8576. void JsonReporter::listReporters(
  8577. std::vector<ReporterDescription> const& descriptions ) {
  8578. startListing();
  8579. auto writer =
  8580. m_objectWriters.top().write( "reporters"_sr ).writeArray();
  8581. for ( auto const& desc : descriptions ) {
  8582. auto desc_writer = writer.writeObject();
  8583. desc_writer.write( "name"_sr ).write( desc.name );
  8584. desc_writer.write( "description"_sr ).write( desc.description );
  8585. }
  8586. }
  8587. void JsonReporter::listListeners(
  8588. std::vector<ListenerDescription> const& descriptions ) {
  8589. startListing();
  8590. auto writer =
  8591. m_objectWriters.top().write( "listeners"_sr ).writeArray();
  8592. for ( auto const& desc : descriptions ) {
  8593. auto desc_writer = writer.writeObject();
  8594. desc_writer.write( "name"_sr ).write( desc.name );
  8595. desc_writer.write( "description"_sr ).write( desc.description );
  8596. }
  8597. }
  8598. void JsonReporter::listTests( std::vector<TestCaseHandle> const& tests ) {
  8599. startListing();
  8600. auto writer = m_objectWriters.top().write( "tests"_sr ).writeArray();
  8601. for ( auto const& test : tests ) {
  8602. auto desc_writer = writer.writeObject();
  8603. auto const& info = test.getTestCaseInfo();
  8604. desc_writer.write( "name"_sr ).write( info.name );
  8605. desc_writer.write( "class-name"_sr ).write( info.className );
  8606. {
  8607. auto tag_writer = desc_writer.write( "tags"_sr ).writeArray();
  8608. for ( auto const& tag : info.tags ) {
  8609. tag_writer.write( tag.original );
  8610. }
  8611. }
  8612. writeSourceInfo( desc_writer, info.lineInfo );
  8613. }
  8614. }
  8615. void JsonReporter::listTags( std::vector<TagInfo> const& tags ) {
  8616. startListing();
  8617. auto writer = m_objectWriters.top().write( "tags"_sr ).writeArray();
  8618. for ( auto const& tag : tags ) {
  8619. auto tag_writer = writer.writeObject();
  8620. {
  8621. auto aliases_writer =
  8622. tag_writer.write( "aliases"_sr ).writeArray();
  8623. for ( auto alias : tag.spellings ) {
  8624. aliases_writer.write( alias );
  8625. }
  8626. }
  8627. tag_writer.write( "count"_sr ).write( tag.count );
  8628. }
  8629. }
  8630. } // namespace Catch
  8631. #include <cassert>
  8632. #include <ctime>
  8633. #include <algorithm>
  8634. #include <iomanip>
  8635. namespace Catch {
  8636. namespace {
  8637. std::string getCurrentTimestamp() {
  8638. time_t rawtime;
  8639. std::time(&rawtime);
  8640. std::tm timeInfo = {};
  8641. #if defined (_MSC_VER) || defined (__MINGW32__)
  8642. gmtime_s(&timeInfo, &rawtime);
  8643. #elif defined (CATCH_PLATFORM_PLAYSTATION)
  8644. gmtime_s(&rawtime, &timeInfo);
  8645. #elif defined (__IAR_SYSTEMS_ICC__)
  8646. timeInfo = *std::gmtime(&rawtime);
  8647. #else
  8648. gmtime_r(&rawtime, &timeInfo);
  8649. #endif
  8650. auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
  8651. char timeStamp[timeStampSize];
  8652. const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
  8653. std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
  8654. return std::string(timeStamp, timeStampSize - 1);
  8655. }
  8656. std::string fileNameTag(std::vector<Tag> const& tags) {
  8657. auto it = std::find_if(begin(tags),
  8658. end(tags),
  8659. [] (Tag const& tag) {
  8660. return tag.original.size() > 0
  8661. && tag.original[0] == '#'; });
  8662. if (it != tags.end()) {
  8663. return static_cast<std::string>(
  8664. it->original.substr(1, it->original.size() - 1)
  8665. );
  8666. }
  8667. return std::string();
  8668. }
  8669. // Formats the duration in seconds to 3 decimal places.
  8670. // This is done because some genius defined Maven Surefire schema
  8671. // in a way that only accepts 3 decimal places, and tools like
  8672. // Jenkins use that schema for validation JUnit reporter output.
  8673. std::string formatDuration( double seconds ) {
  8674. ReusableStringStream rss;
  8675. rss << std::fixed << std::setprecision( 3 ) << seconds;
  8676. return rss.str();
  8677. }
  8678. static void normalizeNamespaceMarkers(std::string& str) {
  8679. std::size_t pos = str.find( "::" );
  8680. while ( pos != std::string::npos ) {
  8681. str.replace( pos, 2, "." );
  8682. pos += 1;
  8683. pos = str.find( "::", pos );
  8684. }
  8685. }
  8686. } // anonymous namespace
  8687. JunitReporter::JunitReporter( ReporterConfig&& _config )
  8688. : CumulativeReporterBase( CATCH_MOVE(_config) ),
  8689. xml( m_stream )
  8690. {
  8691. m_preferences.shouldRedirectStdOut = true;
  8692. m_preferences.shouldReportAllAssertions = false;
  8693. m_shouldStoreSuccesfulAssertions = false;
  8694. }
  8695. std::string JunitReporter::getDescription() {
  8696. return "Reports test results in an XML format that looks like Ant's junitreport target";
  8697. }
  8698. void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
  8699. CumulativeReporterBase::testRunStarting( runInfo );
  8700. xml.startElement( "testsuites" );
  8701. suiteTimer.start();
  8702. stdOutForSuite.clear();
  8703. stdErrForSuite.clear();
  8704. unexpectedExceptions = 0;
  8705. }
  8706. void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
  8707. m_okToFail = testCaseInfo.okToFail();
  8708. }
  8709. void JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
  8710. if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
  8711. unexpectedExceptions++;
  8712. CumulativeReporterBase::assertionEnded( assertionStats );
  8713. }
  8714. void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
  8715. stdOutForSuite += testCaseStats.stdOut;
  8716. stdErrForSuite += testCaseStats.stdErr;
  8717. CumulativeReporterBase::testCaseEnded( testCaseStats );
  8718. }
  8719. void JunitReporter::testRunEndedCumulative() {
  8720. const auto suiteTime = suiteTimer.getElapsedSeconds();
  8721. writeRun( *m_testRun, suiteTime );
  8722. xml.endElement();
  8723. }
  8724. void JunitReporter::writeRun( TestRunNode const& testRunNode, double suiteTime ) {
  8725. XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
  8726. TestRunStats const& stats = testRunNode.value;
  8727. xml.writeAttribute( "name"_sr, stats.runInfo.name );
  8728. xml.writeAttribute( "errors"_sr, unexpectedExceptions );
  8729. xml.writeAttribute( "failures"_sr, stats.totals.assertions.failed-unexpectedExceptions );
  8730. xml.writeAttribute( "skipped"_sr, stats.totals.assertions.skipped );
  8731. xml.writeAttribute( "tests"_sr, stats.totals.assertions.total() );
  8732. xml.writeAttribute( "hostname"_sr, "tbd"_sr ); // !TBD
  8733. if( m_config->showDurations() == ShowDurations::Never )
  8734. xml.writeAttribute( "time"_sr, ""_sr );
  8735. else
  8736. xml.writeAttribute( "time"_sr, formatDuration( suiteTime ) );
  8737. xml.writeAttribute( "timestamp"_sr, getCurrentTimestamp() );
  8738. // Write properties
  8739. {
  8740. auto properties = xml.scopedElement("properties");
  8741. xml.scopedElement("property")
  8742. .writeAttribute("name"_sr, "random-seed"_sr)
  8743. .writeAttribute("value"_sr, m_config->rngSeed());
  8744. if (m_config->testSpec().hasFilters()) {
  8745. xml.scopedElement("property")
  8746. .writeAttribute("name"_sr, "filters"_sr)
  8747. .writeAttribute("value"_sr, m_config->testSpec());
  8748. }
  8749. }
  8750. // Write test cases
  8751. for( auto const& child : testRunNode.children )
  8752. writeTestCase( *child );
  8753. xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline );
  8754. xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline );
  8755. }
  8756. void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
  8757. TestCaseStats const& stats = testCaseNode.value;
  8758. // All test cases have exactly one section - which represents the
  8759. // test case itself. That section may have 0-n nested sections
  8760. assert( testCaseNode.children.size() == 1 );
  8761. SectionNode const& rootSection = *testCaseNode.children.front();
  8762. std::string className =
  8763. static_cast<std::string>( stats.testInfo->className );
  8764. if( className.empty() ) {
  8765. className = fileNameTag(stats.testInfo->tags);
  8766. if ( className.empty() ) {
  8767. className = "global";
  8768. }
  8769. }
  8770. if ( !m_config->name().empty() )
  8771. className = static_cast<std::string>(m_config->name()) + '.' + className;
  8772. normalizeNamespaceMarkers(className);
  8773. writeSection( className, "", rootSection, stats.testInfo->okToFail() );
  8774. }
  8775. void JunitReporter::writeSection( std::string const& className,
  8776. std::string const& rootName,
  8777. SectionNode const& sectionNode,
  8778. bool testOkToFail) {
  8779. std::string name = trim( sectionNode.stats.sectionInfo.name );
  8780. if( !rootName.empty() )
  8781. name = rootName + '/' + name;
  8782. if ( sectionNode.stats.assertions.total() > 0
  8783. || !sectionNode.stdOut.empty()
  8784. || !sectionNode.stdErr.empty() ) {
  8785. XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
  8786. if( className.empty() ) {
  8787. xml.writeAttribute( "classname"_sr, name );
  8788. xml.writeAttribute( "name"_sr, "root"_sr );
  8789. }
  8790. else {
  8791. xml.writeAttribute( "classname"_sr, className );
  8792. xml.writeAttribute( "name"_sr, name );
  8793. }
  8794. xml.writeAttribute( "time"_sr, formatDuration( sectionNode.stats.durationInSeconds ) );
  8795. // This is not ideal, but it should be enough to mimic gtest's
  8796. // junit output.
  8797. // Ideally the JUnit reporter would also handle `skipTest`
  8798. // events and write those out appropriately.
  8799. xml.writeAttribute( "status"_sr, "run"_sr );
  8800. if (sectionNode.stats.assertions.failedButOk) {
  8801. xml.scopedElement("skipped")
  8802. .writeAttribute("message", "TEST_CASE tagged with !mayfail");
  8803. }
  8804. writeAssertions( sectionNode );
  8805. if( !sectionNode.stdOut.empty() )
  8806. xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
  8807. if( !sectionNode.stdErr.empty() )
  8808. xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline );
  8809. }
  8810. for( auto const& childNode : sectionNode.childSections )
  8811. if( className.empty() )
  8812. writeSection( name, "", *childNode, testOkToFail );
  8813. else
  8814. writeSection( className, name, *childNode, testOkToFail );
  8815. }
  8816. void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
  8817. for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
  8818. if (assertionOrBenchmark.isAssertion()) {
  8819. writeAssertion(assertionOrBenchmark.asAssertion());
  8820. }
  8821. }
  8822. }
  8823. void JunitReporter::writeAssertion( AssertionStats const& stats ) {
  8824. AssertionResult const& result = stats.assertionResult;
  8825. if ( !result.isOk() ||
  8826. result.getResultType() == ResultWas::ExplicitSkip ) {
  8827. std::string elementName;
  8828. switch( result.getResultType() ) {
  8829. case ResultWas::ThrewException:
  8830. case ResultWas::FatalErrorCondition:
  8831. elementName = "error";
  8832. break;
  8833. case ResultWas::ExplicitFailure:
  8834. case ResultWas::ExpressionFailed:
  8835. case ResultWas::DidntThrowException:
  8836. elementName = "failure";
  8837. break;
  8838. case ResultWas::ExplicitSkip:
  8839. elementName = "skipped";
  8840. break;
  8841. // We should never see these here:
  8842. case ResultWas::Info:
  8843. case ResultWas::Warning:
  8844. case ResultWas::Ok:
  8845. case ResultWas::Unknown:
  8846. case ResultWas::FailureBit:
  8847. case ResultWas::Exception:
  8848. elementName = "internalError";
  8849. break;
  8850. }
  8851. XmlWriter::ScopedElement e = xml.scopedElement( elementName );
  8852. xml.writeAttribute( "message"_sr, result.getExpression() );
  8853. xml.writeAttribute( "type"_sr, result.getTestMacroName() );
  8854. ReusableStringStream rss;
  8855. if ( result.getResultType() == ResultWas::ExplicitSkip ) {
  8856. rss << "SKIPPED\n";
  8857. } else {
  8858. rss << "FAILED" << ":\n";
  8859. if (result.hasExpression()) {
  8860. rss << " ";
  8861. rss << result.getExpressionInMacro();
  8862. rss << '\n';
  8863. }
  8864. if (result.hasExpandedExpression()) {
  8865. rss << "with expansion:\n";
  8866. rss << TextFlow::Column(result.getExpandedExpression()).indent(2) << '\n';
  8867. }
  8868. }
  8869. if( result.hasMessage() )
  8870. rss << result.getMessage() << '\n';
  8871. for( auto const& msg : stats.infoMessages )
  8872. if( msg.type == ResultWas::Info )
  8873. rss << msg.message << '\n';
  8874. rss << "at " << result.getSourceInfo();
  8875. xml.writeText( rss.str(), XmlFormatting::Newline );
  8876. }
  8877. }
  8878. } // end namespace Catch
  8879. #include <ostream>
  8880. namespace Catch {
  8881. void MultiReporter::updatePreferences(IEventListener const& reporterish) {
  8882. m_preferences.shouldRedirectStdOut |=
  8883. reporterish.getPreferences().shouldRedirectStdOut;
  8884. m_preferences.shouldReportAllAssertions |=
  8885. reporterish.getPreferences().shouldReportAllAssertions;
  8886. }
  8887. void MultiReporter::addListener( IEventListenerPtr&& listener ) {
  8888. updatePreferences(*listener);
  8889. m_reporterLikes.insert(m_reporterLikes.begin() + m_insertedListeners, CATCH_MOVE(listener) );
  8890. ++m_insertedListeners;
  8891. }
  8892. void MultiReporter::addReporter( IEventListenerPtr&& reporter ) {
  8893. updatePreferences(*reporter);
  8894. // We will need to output the captured stdout if there are reporters
  8895. // that do not want it captured.
  8896. // We do not consider listeners, because it is generally assumed that
  8897. // listeners are output-transparent, even though they can ask for stdout
  8898. // capture to do something with it.
  8899. m_haveNoncapturingReporters |= !reporter->getPreferences().shouldRedirectStdOut;
  8900. // Reporters can always be placed to the back without breaking the
  8901. // reporting order
  8902. m_reporterLikes.push_back( CATCH_MOVE( reporter ) );
  8903. }
  8904. void MultiReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
  8905. for ( auto& reporterish : m_reporterLikes ) {
  8906. reporterish->noMatchingTestCases( unmatchedSpec );
  8907. }
  8908. }
  8909. void MultiReporter::fatalErrorEncountered( StringRef error ) {
  8910. for ( auto& reporterish : m_reporterLikes ) {
  8911. reporterish->fatalErrorEncountered( error );
  8912. }
  8913. }
  8914. void MultiReporter::reportInvalidTestSpec( StringRef arg ) {
  8915. for ( auto& reporterish : m_reporterLikes ) {
  8916. reporterish->reportInvalidTestSpec( arg );
  8917. }
  8918. }
  8919. void MultiReporter::benchmarkPreparing( StringRef name ) {
  8920. for (auto& reporterish : m_reporterLikes) {
  8921. reporterish->benchmarkPreparing(name);
  8922. }
  8923. }
  8924. void MultiReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
  8925. for ( auto& reporterish : m_reporterLikes ) {
  8926. reporterish->benchmarkStarting( benchmarkInfo );
  8927. }
  8928. }
  8929. void MultiReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) {
  8930. for ( auto& reporterish : m_reporterLikes ) {
  8931. reporterish->benchmarkEnded( benchmarkStats );
  8932. }
  8933. }
  8934. void MultiReporter::benchmarkFailed( StringRef error ) {
  8935. for (auto& reporterish : m_reporterLikes) {
  8936. reporterish->benchmarkFailed(error);
  8937. }
  8938. }
  8939. void MultiReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
  8940. for ( auto& reporterish : m_reporterLikes ) {
  8941. reporterish->testRunStarting( testRunInfo );
  8942. }
  8943. }
  8944. void MultiReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
  8945. for ( auto& reporterish : m_reporterLikes ) {
  8946. reporterish->testCaseStarting( testInfo );
  8947. }
  8948. }
  8949. void
  8950. MultiReporter::testCasePartialStarting( TestCaseInfo const& testInfo,
  8951. uint64_t partNumber ) {
  8952. for ( auto& reporterish : m_reporterLikes ) {
  8953. reporterish->testCasePartialStarting( testInfo, partNumber );
  8954. }
  8955. }
  8956. void MultiReporter::sectionStarting( SectionInfo const& sectionInfo ) {
  8957. for ( auto& reporterish : m_reporterLikes ) {
  8958. reporterish->sectionStarting( sectionInfo );
  8959. }
  8960. }
  8961. void MultiReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
  8962. for ( auto& reporterish : m_reporterLikes ) {
  8963. reporterish->assertionStarting( assertionInfo );
  8964. }
  8965. }
  8966. void MultiReporter::assertionEnded( AssertionStats const& assertionStats ) {
  8967. const bool reportByDefault =
  8968. assertionStats.assertionResult.getResultType() != ResultWas::Ok ||
  8969. m_config->includeSuccessfulResults();
  8970. for ( auto & reporterish : m_reporterLikes ) {
  8971. if ( reportByDefault ||
  8972. reporterish->getPreferences().shouldReportAllAssertions ) {
  8973. reporterish->assertionEnded( assertionStats );
  8974. }
  8975. }
  8976. }
  8977. void MultiReporter::sectionEnded( SectionStats const& sectionStats ) {
  8978. for ( auto& reporterish : m_reporterLikes ) {
  8979. reporterish->sectionEnded( sectionStats );
  8980. }
  8981. }
  8982. void MultiReporter::testCasePartialEnded( TestCaseStats const& testStats,
  8983. uint64_t partNumber ) {
  8984. if ( m_preferences.shouldRedirectStdOut &&
  8985. m_haveNoncapturingReporters ) {
  8986. if ( !testStats.stdOut.empty() ) {
  8987. Catch::cout() << testStats.stdOut << std::flush;
  8988. }
  8989. if ( !testStats.stdErr.empty() ) {
  8990. Catch::cerr() << testStats.stdErr << std::flush;
  8991. }
  8992. }
  8993. for ( auto& reporterish : m_reporterLikes ) {
  8994. reporterish->testCasePartialEnded( testStats, partNumber );
  8995. }
  8996. }
  8997. void MultiReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
  8998. for ( auto& reporterish : m_reporterLikes ) {
  8999. reporterish->testCaseEnded( testCaseStats );
  9000. }
  9001. }
  9002. void MultiReporter::testRunEnded( TestRunStats const& testRunStats ) {
  9003. for ( auto& reporterish : m_reporterLikes ) {
  9004. reporterish->testRunEnded( testRunStats );
  9005. }
  9006. }
  9007. void MultiReporter::skipTest( TestCaseInfo const& testInfo ) {
  9008. for ( auto& reporterish : m_reporterLikes ) {
  9009. reporterish->skipTest( testInfo );
  9010. }
  9011. }
  9012. void MultiReporter::listReporters(std::vector<ReporterDescription> const& descriptions) {
  9013. for (auto& reporterish : m_reporterLikes) {
  9014. reporterish->listReporters(descriptions);
  9015. }
  9016. }
  9017. void MultiReporter::listListeners(
  9018. std::vector<ListenerDescription> const& descriptions ) {
  9019. for ( auto& reporterish : m_reporterLikes ) {
  9020. reporterish->listListeners( descriptions );
  9021. }
  9022. }
  9023. void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) {
  9024. for (auto& reporterish : m_reporterLikes) {
  9025. reporterish->listTests(tests);
  9026. }
  9027. }
  9028. void MultiReporter::listTags(std::vector<TagInfo> const& tags) {
  9029. for (auto& reporterish : m_reporterLikes) {
  9030. reporterish->listTags(tags);
  9031. }
  9032. }
  9033. } // end namespace Catch
  9034. namespace Catch {
  9035. namespace Detail {
  9036. void registerReporterImpl( std::string const& name,
  9037. IReporterFactoryPtr reporterPtr ) {
  9038. CATCH_TRY {
  9039. getMutableRegistryHub().registerReporter(
  9040. name, CATCH_MOVE( reporterPtr ) );
  9041. }
  9042. CATCH_CATCH_ALL {
  9043. // Do not throw when constructing global objects, instead
  9044. // register the exception to be processed later
  9045. getMutableRegistryHub().registerStartupException();
  9046. }
  9047. }
  9048. void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory ) {
  9049. getMutableRegistryHub().registerListener( CATCH_MOVE(listenerFactory) );
  9050. }
  9051. } // namespace Detail
  9052. } // namespace Catch
  9053. #include <map>
  9054. namespace Catch {
  9055. namespace {
  9056. std::string createMetadataString(IConfig const& config) {
  9057. ReusableStringStream sstr;
  9058. if ( config.testSpec().hasFilters() ) {
  9059. sstr << "filters='"
  9060. << config.testSpec()
  9061. << "' ";
  9062. }
  9063. sstr << "rng-seed=" << config.rngSeed();
  9064. return sstr.str();
  9065. }
  9066. }
  9067. void SonarQubeReporter::testRunStarting(TestRunInfo const& testRunInfo) {
  9068. CumulativeReporterBase::testRunStarting(testRunInfo);
  9069. xml.writeComment( createMetadataString( *m_config ) );
  9070. xml.startElement("testExecutions");
  9071. xml.writeAttribute("version"_sr, '1');
  9072. }
  9073. void SonarQubeReporter::writeRun( TestRunNode const& runNode ) {
  9074. std::map<StringRef, std::vector<TestCaseNode const*>> testsPerFile;
  9075. for ( auto const& child : runNode.children ) {
  9076. testsPerFile[child->value.testInfo->lineInfo.file].push_back(
  9077. child.get() );
  9078. }
  9079. for ( auto const& kv : testsPerFile ) {
  9080. writeTestFile( kv.first, kv.second );
  9081. }
  9082. }
  9083. void SonarQubeReporter::writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
  9084. XmlWriter::ScopedElement e = xml.scopedElement("file");
  9085. xml.writeAttribute("path"_sr, filename);
  9086. for (auto const& child : testCaseNodes)
  9087. writeTestCase(*child);
  9088. }
  9089. void SonarQubeReporter::writeTestCase(TestCaseNode const& testCaseNode) {
  9090. // All test cases have exactly one section - which represents the
  9091. // test case itself. That section may have 0-n nested sections
  9092. assert(testCaseNode.children.size() == 1);
  9093. SectionNode const& rootSection = *testCaseNode.children.front();
  9094. writeSection("", rootSection, testCaseNode.value.testInfo->okToFail());
  9095. }
  9096. void SonarQubeReporter::writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
  9097. std::string name = trim(sectionNode.stats.sectionInfo.name);
  9098. if (!rootName.empty())
  9099. name = rootName + '/' + name;
  9100. if ( sectionNode.stats.assertions.total() > 0
  9101. || !sectionNode.stdOut.empty()
  9102. || !sectionNode.stdErr.empty() ) {
  9103. XmlWriter::ScopedElement e = xml.scopedElement("testCase");
  9104. xml.writeAttribute("name"_sr, name);
  9105. xml.writeAttribute("duration"_sr, static_cast<long>(sectionNode.stats.durationInSeconds * 1000));
  9106. writeAssertions(sectionNode, okToFail);
  9107. }
  9108. for (auto const& childNode : sectionNode.childSections)
  9109. writeSection(name, *childNode, okToFail);
  9110. }
  9111. void SonarQubeReporter::writeAssertions(SectionNode const& sectionNode, bool okToFail) {
  9112. for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
  9113. if (assertionOrBenchmark.isAssertion()) {
  9114. writeAssertion(assertionOrBenchmark.asAssertion(), okToFail);
  9115. }
  9116. }
  9117. }
  9118. void SonarQubeReporter::writeAssertion(AssertionStats const& stats, bool okToFail) {
  9119. AssertionResult const& result = stats.assertionResult;
  9120. if ( !result.isOk() ||
  9121. result.getResultType() == ResultWas::ExplicitSkip ) {
  9122. std::string elementName;
  9123. if (okToFail) {
  9124. elementName = "skipped";
  9125. } else {
  9126. switch (result.getResultType()) {
  9127. case ResultWas::ThrewException:
  9128. case ResultWas::FatalErrorCondition:
  9129. elementName = "error";
  9130. break;
  9131. case ResultWas::ExplicitFailure:
  9132. case ResultWas::ExpressionFailed:
  9133. case ResultWas::DidntThrowException:
  9134. elementName = "failure";
  9135. break;
  9136. case ResultWas::ExplicitSkip:
  9137. elementName = "skipped";
  9138. break;
  9139. // We should never see these here:
  9140. case ResultWas::Info:
  9141. case ResultWas::Warning:
  9142. case ResultWas::Ok:
  9143. case ResultWas::Unknown:
  9144. case ResultWas::FailureBit:
  9145. case ResultWas::Exception:
  9146. elementName = "internalError";
  9147. break;
  9148. }
  9149. }
  9150. XmlWriter::ScopedElement e = xml.scopedElement(elementName);
  9151. ReusableStringStream messageRss;
  9152. messageRss << result.getTestMacroName() << '(' << result.getExpression() << ')';
  9153. xml.writeAttribute("message"_sr, messageRss.str());
  9154. ReusableStringStream textRss;
  9155. if ( result.getResultType() == ResultWas::ExplicitSkip ) {
  9156. textRss << "SKIPPED\n";
  9157. } else {
  9158. textRss << "FAILED:\n";
  9159. if (result.hasExpression()) {
  9160. textRss << '\t' << result.getExpressionInMacro() << '\n';
  9161. }
  9162. if (result.hasExpandedExpression()) {
  9163. textRss << "with expansion:\n\t" << result.getExpandedExpression() << '\n';
  9164. }
  9165. }
  9166. if (result.hasMessage())
  9167. textRss << result.getMessage() << '\n';
  9168. for (auto const& msg : stats.infoMessages)
  9169. if (msg.type == ResultWas::Info)
  9170. textRss << msg.message << '\n';
  9171. textRss << "at " << result.getSourceInfo();
  9172. xml.writeText(textRss.str(), XmlFormatting::Newline);
  9173. }
  9174. }
  9175. } // end namespace Catch
  9176. namespace Catch {
  9177. StreamingReporterBase::~StreamingReporterBase() = default;
  9178. void
  9179. StreamingReporterBase::testRunStarting( TestRunInfo const& _testRunInfo ) {
  9180. currentTestRunInfo = _testRunInfo;
  9181. }
  9182. void StreamingReporterBase::testRunEnded( TestRunStats const& ) {
  9183. currentTestCaseInfo = nullptr;
  9184. }
  9185. } // end namespace Catch
  9186. #include <algorithm>
  9187. #include <ostream>
  9188. namespace Catch {
  9189. namespace {
  9190. // Yes, this has to be outside the class and namespaced by naming.
  9191. // Making older compiler happy is hard.
  9192. static constexpr StringRef tapFailedString = "not ok"_sr;
  9193. static constexpr StringRef tapPassedString = "ok"_sr;
  9194. static constexpr Colour::Code tapDimColour = Colour::FileName;
  9195. class TapAssertionPrinter {
  9196. public:
  9197. TapAssertionPrinter& operator= (TapAssertionPrinter const&) = delete;
  9198. TapAssertionPrinter(TapAssertionPrinter const&) = delete;
  9199. TapAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter, ColourImpl* colour_)
  9200. : stream(_stream)
  9201. , result(_stats.assertionResult)
  9202. , messages(_stats.infoMessages)
  9203. , itMessage(_stats.infoMessages.begin())
  9204. , printInfoMessages(true)
  9205. , counter(_counter)
  9206. , colourImpl( colour_ ) {}
  9207. void print() {
  9208. itMessage = messages.begin();
  9209. switch (result.getResultType()) {
  9210. case ResultWas::Ok:
  9211. printResultType(tapPassedString);
  9212. printOriginalExpression();
  9213. printReconstructedExpression();
  9214. if (!result.hasExpression())
  9215. printRemainingMessages(Colour::None);
  9216. else
  9217. printRemainingMessages();
  9218. break;
  9219. case ResultWas::ExpressionFailed:
  9220. if (result.isOk()) {
  9221. printResultType(tapPassedString);
  9222. } else {
  9223. printResultType(tapFailedString);
  9224. }
  9225. printOriginalExpression();
  9226. printReconstructedExpression();
  9227. if (result.isOk()) {
  9228. printIssue(" # TODO");
  9229. }
  9230. printRemainingMessages();
  9231. break;
  9232. case ResultWas::ThrewException:
  9233. printResultType(tapFailedString);
  9234. printIssue("unexpected exception with message:"_sr);
  9235. printMessage();
  9236. printExpressionWas();
  9237. printRemainingMessages();
  9238. break;
  9239. case ResultWas::FatalErrorCondition:
  9240. printResultType(tapFailedString);
  9241. printIssue("fatal error condition with message:"_sr);
  9242. printMessage();
  9243. printExpressionWas();
  9244. printRemainingMessages();
  9245. break;
  9246. case ResultWas::DidntThrowException:
  9247. printResultType(tapFailedString);
  9248. printIssue("expected exception, got none"_sr);
  9249. printExpressionWas();
  9250. printRemainingMessages();
  9251. break;
  9252. case ResultWas::Info:
  9253. printResultType("info"_sr);
  9254. printMessage();
  9255. printRemainingMessages();
  9256. break;
  9257. case ResultWas::Warning:
  9258. printResultType("warning"_sr);
  9259. printMessage();
  9260. printRemainingMessages();
  9261. break;
  9262. case ResultWas::ExplicitFailure:
  9263. printResultType(tapFailedString);
  9264. printIssue("explicitly"_sr);
  9265. printRemainingMessages(Colour::None);
  9266. break;
  9267. case ResultWas::ExplicitSkip:
  9268. printResultType(tapPassedString);
  9269. printIssue(" # SKIP"_sr);
  9270. printMessage();
  9271. printRemainingMessages();
  9272. break;
  9273. // These cases are here to prevent compiler warnings
  9274. case ResultWas::Unknown:
  9275. case ResultWas::FailureBit:
  9276. case ResultWas::Exception:
  9277. printResultType("** internal error **"_sr);
  9278. break;
  9279. }
  9280. }
  9281. private:
  9282. void printResultType(StringRef passOrFail) const {
  9283. if (!passOrFail.empty()) {
  9284. stream << passOrFail << ' ' << counter << " -";
  9285. }
  9286. }
  9287. void printIssue(StringRef issue) const {
  9288. stream << ' ' << issue;
  9289. }
  9290. void printExpressionWas() {
  9291. if (result.hasExpression()) {
  9292. stream << ';';
  9293. stream << colourImpl->guardColour( tapDimColour )
  9294. << " expression was:";
  9295. printOriginalExpression();
  9296. }
  9297. }
  9298. void printOriginalExpression() const {
  9299. if (result.hasExpression()) {
  9300. stream << ' ' << result.getExpression();
  9301. }
  9302. }
  9303. void printReconstructedExpression() const {
  9304. if (result.hasExpandedExpression()) {
  9305. stream << colourImpl->guardColour( tapDimColour ) << " for: ";
  9306. std::string expr = result.getExpandedExpression();
  9307. std::replace(expr.begin(), expr.end(), '\n', ' ');
  9308. stream << expr;
  9309. }
  9310. }
  9311. void printMessage() {
  9312. if (itMessage != messages.end()) {
  9313. stream << " '" << itMessage->message << '\'';
  9314. ++itMessage;
  9315. }
  9316. }
  9317. void printRemainingMessages(Colour::Code colour = tapDimColour) {
  9318. if (itMessage == messages.end()) {
  9319. return;
  9320. }
  9321. // using messages.end() directly (or auto) yields compilation error:
  9322. std::vector<MessageInfo>::const_iterator itEnd = messages.end();
  9323. const std::size_t N = static_cast<std::size_t>(itEnd - itMessage);
  9324. stream << colourImpl->guardColour( colour ) << " with "
  9325. << pluralise( N, "message"_sr ) << ':';
  9326. for (; itMessage != itEnd; ) {
  9327. // If this assertion is a warning ignore any INFO messages
  9328. if (printInfoMessages || itMessage->type != ResultWas::Info) {
  9329. stream << " '" << itMessage->message << '\'';
  9330. if (++itMessage != itEnd) {
  9331. stream << colourImpl->guardColour(tapDimColour) << " and";
  9332. }
  9333. }
  9334. }
  9335. }
  9336. private:
  9337. std::ostream& stream;
  9338. AssertionResult const& result;
  9339. std::vector<MessageInfo> const& messages;
  9340. std::vector<MessageInfo>::const_iterator itMessage;
  9341. bool printInfoMessages;
  9342. std::size_t counter;
  9343. ColourImpl* colourImpl;
  9344. };
  9345. } // End anonymous namespace
  9346. void TAPReporter::testRunStarting( TestRunInfo const& ) {
  9347. if ( m_config->testSpec().hasFilters() ) {
  9348. m_stream << "# filters: " << m_config->testSpec() << '\n';
  9349. }
  9350. m_stream << "# rng-seed: " << m_config->rngSeed() << '\n';
  9351. }
  9352. void TAPReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
  9353. m_stream << "# No test cases matched '" << unmatchedSpec << "'\n";
  9354. }
  9355. void TAPReporter::assertionEnded(AssertionStats const& _assertionStats) {
  9356. ++counter;
  9357. m_stream << "# " << currentTestCaseInfo->name << '\n';
  9358. TapAssertionPrinter printer(m_stream, _assertionStats, counter, m_colour.get());
  9359. printer.print();
  9360. m_stream << '\n' << std::flush;
  9361. }
  9362. void TAPReporter::testRunEnded(TestRunStats const& _testRunStats) {
  9363. m_stream << "1.." << _testRunStats.totals.assertions.total();
  9364. if (_testRunStats.totals.testCases.total() == 0) {
  9365. m_stream << " # Skipped: No tests ran.";
  9366. }
  9367. m_stream << "\n\n" << std::flush;
  9368. StreamingReporterBase::testRunEnded(_testRunStats);
  9369. }
  9370. } // end namespace Catch
  9371. #include <cassert>
  9372. #include <ostream>
  9373. namespace Catch {
  9374. namespace {
  9375. // if string has a : in first line will set indent to follow it on
  9376. // subsequent lines
  9377. void printHeaderString(std::ostream& os, std::string const& _string, std::size_t indent = 0) {
  9378. std::size_t i = _string.find(": ");
  9379. if (i != std::string::npos)
  9380. i += 2;
  9381. else
  9382. i = 0;
  9383. os << TextFlow::Column(_string)
  9384. .indent(indent + i)
  9385. .initialIndent(indent) << '\n';
  9386. }
  9387. std::string escape(StringRef str) {
  9388. std::string escaped = static_cast<std::string>(str);
  9389. replaceInPlace(escaped, "|", "||");
  9390. replaceInPlace(escaped, "'", "|'");
  9391. replaceInPlace(escaped, "\n", "|n");
  9392. replaceInPlace(escaped, "\r", "|r");
  9393. replaceInPlace(escaped, "[", "|[");
  9394. replaceInPlace(escaped, "]", "|]");
  9395. return escaped;
  9396. }
  9397. } // end anonymous namespace
  9398. TeamCityReporter::~TeamCityReporter() = default;
  9399. void TeamCityReporter::testRunStarting( TestRunInfo const& runInfo ) {
  9400. m_stream << "##teamcity[testSuiteStarted name='" << escape( runInfo.name )
  9401. << "']\n";
  9402. }
  9403. void TeamCityReporter::testRunEnded( TestRunStats const& runStats ) {
  9404. m_stream << "##teamcity[testSuiteFinished name='"
  9405. << escape( runStats.runInfo.name ) << "']\n";
  9406. }
  9407. void TeamCityReporter::assertionEnded(AssertionStats const& assertionStats) {
  9408. AssertionResult const& result = assertionStats.assertionResult;
  9409. if ( !result.isOk() ||
  9410. result.getResultType() == ResultWas::ExplicitSkip ) {
  9411. ReusableStringStream msg;
  9412. if (!m_headerPrintedForThisSection)
  9413. printSectionHeader(msg.get());
  9414. m_headerPrintedForThisSection = true;
  9415. msg << result.getSourceInfo() << '\n';
  9416. switch (result.getResultType()) {
  9417. case ResultWas::ExpressionFailed:
  9418. msg << "expression failed";
  9419. break;
  9420. case ResultWas::ThrewException:
  9421. msg << "unexpected exception";
  9422. break;
  9423. case ResultWas::FatalErrorCondition:
  9424. msg << "fatal error condition";
  9425. break;
  9426. case ResultWas::DidntThrowException:
  9427. msg << "no exception was thrown where one was expected";
  9428. break;
  9429. case ResultWas::ExplicitFailure:
  9430. msg << "explicit failure";
  9431. break;
  9432. case ResultWas::ExplicitSkip:
  9433. msg << "explicit skip";
  9434. break;
  9435. // We shouldn't get here because of the isOk() test
  9436. case ResultWas::Ok:
  9437. case ResultWas::Info:
  9438. case ResultWas::Warning:
  9439. CATCH_ERROR("Internal error in TeamCity reporter");
  9440. // These cases are here to prevent compiler warnings
  9441. case ResultWas::Unknown:
  9442. case ResultWas::FailureBit:
  9443. case ResultWas::Exception:
  9444. CATCH_ERROR("Not implemented");
  9445. }
  9446. if (assertionStats.infoMessages.size() == 1)
  9447. msg << " with message:";
  9448. if (assertionStats.infoMessages.size() > 1)
  9449. msg << " with messages:";
  9450. for (auto const& messageInfo : assertionStats.infoMessages)
  9451. msg << "\n \"" << messageInfo.message << '"';
  9452. if (result.hasExpression()) {
  9453. msg <<
  9454. "\n " << result.getExpressionInMacro() << "\n"
  9455. "with expansion:\n"
  9456. " " << result.getExpandedExpression() << '\n';
  9457. }
  9458. if ( result.getResultType() == ResultWas::ExplicitSkip ) {
  9459. m_stream << "##teamcity[testIgnored";
  9460. } else if ( currentTestCaseInfo->okToFail() ) {
  9461. msg << "- failure ignore as test marked as 'ok to fail'\n";
  9462. m_stream << "##teamcity[testIgnored";
  9463. } else {
  9464. m_stream << "##teamcity[testFailed";
  9465. }
  9466. m_stream << " name='" << escape( currentTestCaseInfo->name ) << '\''
  9467. << " message='" << escape( msg.str() ) << '\'' << "]\n";
  9468. }
  9469. m_stream.flush();
  9470. }
  9471. void TeamCityReporter::testCaseStarting(TestCaseInfo const& testInfo) {
  9472. m_testTimer.start();
  9473. StreamingReporterBase::testCaseStarting(testInfo);
  9474. m_stream << "##teamcity[testStarted name='"
  9475. << escape(testInfo.name) << "']\n";
  9476. m_stream.flush();
  9477. }
  9478. void TeamCityReporter::testCaseEnded(TestCaseStats const& testCaseStats) {
  9479. StreamingReporterBase::testCaseEnded(testCaseStats);
  9480. auto const& testCaseInfo = *testCaseStats.testInfo;
  9481. if (!testCaseStats.stdOut.empty())
  9482. m_stream << "##teamcity[testStdOut name='"
  9483. << escape(testCaseInfo.name)
  9484. << "' out='" << escape(testCaseStats.stdOut) << "']\n";
  9485. if (!testCaseStats.stdErr.empty())
  9486. m_stream << "##teamcity[testStdErr name='"
  9487. << escape(testCaseInfo.name)
  9488. << "' out='" << escape(testCaseStats.stdErr) << "']\n";
  9489. m_stream << "##teamcity[testFinished name='"
  9490. << escape(testCaseInfo.name) << "' duration='"
  9491. << m_testTimer.getElapsedMilliseconds() << "']\n";
  9492. m_stream.flush();
  9493. }
  9494. void TeamCityReporter::printSectionHeader(std::ostream& os) {
  9495. assert(!m_sectionStack.empty());
  9496. if (m_sectionStack.size() > 1) {
  9497. os << lineOfChars('-') << '\n';
  9498. std::vector<SectionInfo>::const_iterator
  9499. it = m_sectionStack.begin() + 1, // Skip first section (test case)
  9500. itEnd = m_sectionStack.end();
  9501. for (; it != itEnd; ++it)
  9502. printHeaderString(os, it->name);
  9503. os << lineOfChars('-') << '\n';
  9504. }
  9505. SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
  9506. os << lineInfo << '\n';
  9507. os << lineOfChars('.') << "\n\n";
  9508. }
  9509. } // end namespace Catch
  9510. #if defined(_MSC_VER)
  9511. #pragma warning(push)
  9512. #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
  9513. // Note that 4062 (not all labels are handled
  9514. // and default is missing) is enabled
  9515. #endif
  9516. namespace Catch {
  9517. XmlReporter::XmlReporter( ReporterConfig&& _config )
  9518. : StreamingReporterBase( CATCH_MOVE(_config) ),
  9519. m_xml(m_stream)
  9520. {
  9521. m_preferences.shouldRedirectStdOut = true;
  9522. m_preferences.shouldReportAllAssertions = true;
  9523. }
  9524. XmlReporter::~XmlReporter() = default;
  9525. std::string XmlReporter::getDescription() {
  9526. return "Reports test results as an XML document";
  9527. }
  9528. std::string XmlReporter::getStylesheetRef() const {
  9529. return std::string();
  9530. }
  9531. void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {
  9532. m_xml
  9533. .writeAttribute( "filename"_sr, sourceInfo.file )
  9534. .writeAttribute( "line"_sr, sourceInfo.line );
  9535. }
  9536. void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {
  9537. StreamingReporterBase::testRunStarting( testInfo );
  9538. std::string stylesheetRef = getStylesheetRef();
  9539. if( !stylesheetRef.empty() )
  9540. m_xml.writeStylesheetRef( stylesheetRef );
  9541. m_xml.startElement("Catch2TestRun")
  9542. .writeAttribute("name"_sr, m_config->name())
  9543. .writeAttribute("rng-seed"_sr, m_config->rngSeed())
  9544. .writeAttribute("xml-format-version"_sr, 3)
  9545. .writeAttribute("catch2-version"_sr, libraryVersion());
  9546. if ( m_config->testSpec().hasFilters() ) {
  9547. m_xml.writeAttribute( "filters"_sr, m_config->testSpec() );
  9548. }
  9549. }
  9550. void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
  9551. StreamingReporterBase::testCaseStarting(testInfo);
  9552. m_xml.startElement( "TestCase" )
  9553. .writeAttribute( "name"_sr, trim( StringRef(testInfo.name) ) )
  9554. .writeAttribute( "tags"_sr, testInfo.tagsAsString() );
  9555. writeSourceInfo( testInfo.lineInfo );
  9556. if ( m_config->showDurations() == ShowDurations::Always )
  9557. m_testCaseTimer.start();
  9558. m_xml.ensureTagClosed();
  9559. }
  9560. void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {
  9561. StreamingReporterBase::sectionStarting( sectionInfo );
  9562. if( m_sectionDepth++ > 0 ) {
  9563. m_xml.startElement( "Section" )
  9564. .writeAttribute( "name"_sr, trim( StringRef(sectionInfo.name) ) );
  9565. writeSourceInfo( sectionInfo.lineInfo );
  9566. m_xml.ensureTagClosed();
  9567. }
  9568. }
  9569. void XmlReporter::assertionStarting( AssertionInfo const& ) { }
  9570. void XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
  9571. AssertionResult const& result = assertionStats.assertionResult;
  9572. bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
  9573. if( includeResults || result.getResultType() == ResultWas::Warning ) {
  9574. // Print any info messages in <Info> tags.
  9575. for( auto const& msg : assertionStats.infoMessages ) {
  9576. if( msg.type == ResultWas::Info && includeResults ) {
  9577. auto t = m_xml.scopedElement( "Info" );
  9578. writeSourceInfo( msg.lineInfo );
  9579. t.writeText( msg.message );
  9580. } else if ( msg.type == ResultWas::Warning ) {
  9581. auto t = m_xml.scopedElement( "Warning" );
  9582. writeSourceInfo( msg.lineInfo );
  9583. t.writeText( msg.message );
  9584. }
  9585. }
  9586. }
  9587. // Drop out if result was successful but we're not printing them.
  9588. if ( !includeResults && result.getResultType() != ResultWas::Warning &&
  9589. result.getResultType() != ResultWas::ExplicitSkip ) {
  9590. return;
  9591. }
  9592. // Print the expression if there is one.
  9593. if( result.hasExpression() ) {
  9594. m_xml.startElement( "Expression" )
  9595. .writeAttribute( "success"_sr, result.succeeded() )
  9596. .writeAttribute( "type"_sr, result.getTestMacroName() );
  9597. writeSourceInfo( result.getSourceInfo() );
  9598. m_xml.scopedElement( "Original" )
  9599. .writeText( result.getExpression() );
  9600. m_xml.scopedElement( "Expanded" )
  9601. .writeText( result.getExpandedExpression() );
  9602. }
  9603. // And... Print a result applicable to each result type.
  9604. switch( result.getResultType() ) {
  9605. case ResultWas::ThrewException:
  9606. m_xml.startElement( "Exception" );
  9607. writeSourceInfo( result.getSourceInfo() );
  9608. m_xml.writeText( result.getMessage() );
  9609. m_xml.endElement();
  9610. break;
  9611. case ResultWas::FatalErrorCondition:
  9612. m_xml.startElement( "FatalErrorCondition" );
  9613. writeSourceInfo( result.getSourceInfo() );
  9614. m_xml.writeText( result.getMessage() );
  9615. m_xml.endElement();
  9616. break;
  9617. case ResultWas::Info:
  9618. m_xml.scopedElement( "Info" )
  9619. .writeText( result.getMessage() );
  9620. break;
  9621. case ResultWas::Warning:
  9622. // Warning will already have been written
  9623. break;
  9624. case ResultWas::ExplicitFailure:
  9625. m_xml.startElement( "Failure" );
  9626. writeSourceInfo( result.getSourceInfo() );
  9627. m_xml.writeText( result.getMessage() );
  9628. m_xml.endElement();
  9629. break;
  9630. case ResultWas::ExplicitSkip:
  9631. m_xml.startElement( "Skip" );
  9632. writeSourceInfo( result.getSourceInfo() );
  9633. m_xml.writeText( result.getMessage() );
  9634. m_xml.endElement();
  9635. break;
  9636. default:
  9637. break;
  9638. }
  9639. if( result.hasExpression() )
  9640. m_xml.endElement();
  9641. }
  9642. void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
  9643. StreamingReporterBase::sectionEnded( sectionStats );
  9644. if ( --m_sectionDepth > 0 ) {
  9645. {
  9646. XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
  9647. e.writeAttribute( "successes"_sr, sectionStats.assertions.passed );
  9648. e.writeAttribute( "failures"_sr, sectionStats.assertions.failed );
  9649. e.writeAttribute( "expectedFailures"_sr, sectionStats.assertions.failedButOk );
  9650. e.writeAttribute( "skipped"_sr, sectionStats.assertions.skipped > 0 );
  9651. if ( m_config->showDurations() == ShowDurations::Always )
  9652. e.writeAttribute( "durationInSeconds"_sr, sectionStats.durationInSeconds );
  9653. }
  9654. // Ends assertion tag
  9655. m_xml.endElement();
  9656. }
  9657. }
  9658. void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
  9659. StreamingReporterBase::testCaseEnded( testCaseStats );
  9660. XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
  9661. e.writeAttribute( "success"_sr, testCaseStats.totals.assertions.allOk() );
  9662. e.writeAttribute( "skips"_sr, testCaseStats.totals.assertions.skipped );
  9663. if ( m_config->showDurations() == ShowDurations::Always )
  9664. e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() );
  9665. if( !testCaseStats.stdOut.empty() )
  9666. m_xml.scopedElement( "StdOut" ).writeText( trim( StringRef(testCaseStats.stdOut) ), XmlFormatting::Newline );
  9667. if( !testCaseStats.stdErr.empty() )
  9668. m_xml.scopedElement( "StdErr" ).writeText( trim( StringRef(testCaseStats.stdErr) ), XmlFormatting::Newline );
  9669. m_xml.endElement();
  9670. }
  9671. void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {
  9672. StreamingReporterBase::testRunEnded( testRunStats );
  9673. m_xml.scopedElement( "OverallResults" )
  9674. .writeAttribute( "successes"_sr, testRunStats.totals.assertions.passed )
  9675. .writeAttribute( "failures"_sr, testRunStats.totals.assertions.failed )
  9676. .writeAttribute( "expectedFailures"_sr, testRunStats.totals.assertions.failedButOk )
  9677. .writeAttribute( "skips"_sr, testRunStats.totals.assertions.skipped );
  9678. m_xml.scopedElement( "OverallResultsCases")
  9679. .writeAttribute( "successes"_sr, testRunStats.totals.testCases.passed )
  9680. .writeAttribute( "failures"_sr, testRunStats.totals.testCases.failed )
  9681. .writeAttribute( "expectedFailures"_sr, testRunStats.totals.testCases.failedButOk )
  9682. .writeAttribute( "skips"_sr, testRunStats.totals.testCases.skipped );
  9683. m_xml.endElement();
  9684. }
  9685. void XmlReporter::benchmarkPreparing( StringRef name ) {
  9686. m_xml.startElement("BenchmarkResults")
  9687. .writeAttribute("name"_sr, name);
  9688. }
  9689. void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
  9690. m_xml.writeAttribute("samples"_sr, info.samples)
  9691. .writeAttribute("resamples"_sr, info.resamples)
  9692. .writeAttribute("iterations"_sr, info.iterations)
  9693. .writeAttribute("clockResolution"_sr, info.clockResolution)
  9694. .writeAttribute("estimatedDuration"_sr, info.estimatedDuration)
  9695. .writeComment("All values in nano seconds"_sr);
  9696. }
  9697. void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
  9698. m_xml.scopedElement("mean")
  9699. .writeAttribute("value"_sr, benchmarkStats.mean.point.count())
  9700. .writeAttribute("lowerBound"_sr, benchmarkStats.mean.lower_bound.count())
  9701. .writeAttribute("upperBound"_sr, benchmarkStats.mean.upper_bound.count())
  9702. .writeAttribute("ci"_sr, benchmarkStats.mean.confidence_interval);
  9703. m_xml.scopedElement("standardDeviation")
  9704. .writeAttribute("value"_sr, benchmarkStats.standardDeviation.point.count())
  9705. .writeAttribute("lowerBound"_sr, benchmarkStats.standardDeviation.lower_bound.count())
  9706. .writeAttribute("upperBound"_sr, benchmarkStats.standardDeviation.upper_bound.count())
  9707. .writeAttribute("ci"_sr, benchmarkStats.standardDeviation.confidence_interval);
  9708. m_xml.scopedElement("outliers")
  9709. .writeAttribute("variance"_sr, benchmarkStats.outlierVariance)
  9710. .writeAttribute("lowMild"_sr, benchmarkStats.outliers.low_mild)
  9711. .writeAttribute("lowSevere"_sr, benchmarkStats.outliers.low_severe)
  9712. .writeAttribute("highMild"_sr, benchmarkStats.outliers.high_mild)
  9713. .writeAttribute("highSevere"_sr, benchmarkStats.outliers.high_severe);
  9714. m_xml.endElement();
  9715. }
  9716. void XmlReporter::benchmarkFailed(StringRef error) {
  9717. m_xml.scopedElement("failed").
  9718. writeAttribute("message"_sr, error);
  9719. m_xml.endElement();
  9720. }
  9721. void XmlReporter::listReporters(std::vector<ReporterDescription> const& descriptions) {
  9722. auto outerTag = m_xml.scopedElement("AvailableReporters");
  9723. for (auto const& reporter : descriptions) {
  9724. auto inner = m_xml.scopedElement("Reporter");
  9725. m_xml.startElement("Name", XmlFormatting::Indent)
  9726. .writeText(reporter.name, XmlFormatting::None)
  9727. .endElement(XmlFormatting::Newline);
  9728. m_xml.startElement("Description", XmlFormatting::Indent)
  9729. .writeText(reporter.description, XmlFormatting::None)
  9730. .endElement(XmlFormatting::Newline);
  9731. }
  9732. }
  9733. void XmlReporter::listListeners(std::vector<ListenerDescription> const& descriptions) {
  9734. auto outerTag = m_xml.scopedElement( "RegisteredListeners" );
  9735. for ( auto const& listener : descriptions ) {
  9736. auto inner = m_xml.scopedElement( "Listener" );
  9737. m_xml.startElement( "Name", XmlFormatting::Indent )
  9738. .writeText( listener.name, XmlFormatting::None )
  9739. .endElement( XmlFormatting::Newline );
  9740. m_xml.startElement( "Description", XmlFormatting::Indent )
  9741. .writeText( listener.description, XmlFormatting::None )
  9742. .endElement( XmlFormatting::Newline );
  9743. }
  9744. }
  9745. void XmlReporter::listTests(std::vector<TestCaseHandle> const& tests) {
  9746. auto outerTag = m_xml.scopedElement("MatchingTests");
  9747. for (auto const& test : tests) {
  9748. auto innerTag = m_xml.scopedElement("TestCase");
  9749. auto const& testInfo = test.getTestCaseInfo();
  9750. m_xml.startElement("Name", XmlFormatting::Indent)
  9751. .writeText(testInfo.name, XmlFormatting::None)
  9752. .endElement(XmlFormatting::Newline);
  9753. m_xml.startElement("ClassName", XmlFormatting::Indent)
  9754. .writeText(testInfo.className, XmlFormatting::None)
  9755. .endElement(XmlFormatting::Newline);
  9756. m_xml.startElement("Tags", XmlFormatting::Indent)
  9757. .writeText(testInfo.tagsAsString(), XmlFormatting::None)
  9758. .endElement(XmlFormatting::Newline);
  9759. auto sourceTag = m_xml.scopedElement("SourceInfo");
  9760. m_xml.startElement("File", XmlFormatting::Indent)
  9761. .writeText(testInfo.lineInfo.file, XmlFormatting::None)
  9762. .endElement(XmlFormatting::Newline);
  9763. m_xml.startElement("Line", XmlFormatting::Indent)
  9764. .writeText(std::to_string(testInfo.lineInfo.line), XmlFormatting::None)
  9765. .endElement(XmlFormatting::Newline);
  9766. }
  9767. }
  9768. void XmlReporter::listTags(std::vector<TagInfo> const& tags) {
  9769. auto outerTag = m_xml.scopedElement("TagsFromMatchingTests");
  9770. for (auto const& tag : tags) {
  9771. auto innerTag = m_xml.scopedElement("Tag");
  9772. m_xml.startElement("Count", XmlFormatting::Indent)
  9773. .writeText(std::to_string(tag.count), XmlFormatting::None)
  9774. .endElement(XmlFormatting::Newline);
  9775. auto aliasTag = m_xml.scopedElement("Aliases");
  9776. for (auto const& alias : tag.spellings) {
  9777. m_xml.startElement("Alias", XmlFormatting::Indent)
  9778. .writeText(alias, XmlFormatting::None)
  9779. .endElement(XmlFormatting::Newline);
  9780. }
  9781. }
  9782. }
  9783. } // end namespace Catch
  9784. #if defined(_MSC_VER)
  9785. #pragma warning(pop)
  9786. #endif