catch_amalgamated.cpp 357 KB

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