2
0

catch_amalgamated.cpp 405 KB

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