// ĠCopyright Ġ 2 0 2 1 ĠCode ĠIntelligence ĠGmbH Ċ // Ċ // ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ // Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ // ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ // Ċ // ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ // Ċ // ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ // Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ // ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ // ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ // Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ċ package Ġcom . code _ int elligence . j az zer . instrument or Ċ Ċ import Ġcom . code _ int elligence . j az zer . runtime . Coverage Map Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . analysis . Coverage Builder Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . data . Execution Data Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . data . Execution DataReader Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . data . Execution DataStore Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . data . Execution Data Writer Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . data . Session Info Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . data . Session Info Store Ċ import Ġcom . code _ int elligence . j az zer . third _ party . jac oco . core . internal . data . CRC 6 4 Ċ import Ġjava . io . ByteArray InputStream Ċ import Ġjava . io . ByteArray OutputStream Ċ import Ġjava . time . Instant Ċ import Ġjava . util . UUID Ċ Ċ private Ġdata Ġclass ĠInstrument ed Class Info ( ĊĠĠĠ Ġval Ġclass Id : ĠLong , ĊĠĠĠ Ġval Ġinitial Edge Id : ĠInt , ĊĠĠĠ Ġval Ġnext Edge Id : ĠInt , ĊĠĠĠ Ġval Ġbytecode : ĠByteArray Ċ ) Ċ Ċ object ĠCoverage Recorder Ġ{ ĊĠĠĠ Ġprivate Ġval Ġinstrument ed Class Info Ġ= Ġmutable Map Of < String , ĠInstrument ed Class Info >() ĊĠĠĠ Ġprivate Ġvar Ġstart Timestamp : ĠInstant ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġval Ġadditional Coverage Ġ= Ġmutable Set Of < Int >() ĊĊĠĠĠ Ġfun Ġrecord Instrument ed Class ( internal ClassName : ĠString , Ġbytecode : ĠByteArray , Ġfirst Id : ĠInt , Ġnum Ids : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( start Timestamp Ġ== Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Timestamp Ġ= ĠInstant . now () ĊĠĠĠĠĠĠĠ Ġinstrument ed Class Info [ internal ClassName ] Ġ= ĠInstrument ed Class Info ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCRC 6 4 . class Id ( byte code ), Ġfirst Id , Ġfirst Id Ġ+ Ġnum Ids , Ġbytecode ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠMan ually Ġrecords Ġcoverage ĠIDs Ġbased Ġon Ġthe Ġcurrent Ġstate Ġof Ġ[ Coverage Map . mem ]. ĊĠĠĠĠ Ġ* ĠShould Ġbe Ġcalled Ġafter Ġstatic Ġinitial izers Ġhave Ġrun . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Jvm Static ĊĠĠĠ Ġfun Ġupdate Cover ed Ids With Coverage Map () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmem Ġ= ĠCoverage Map . mem ĊĠĠĠĠĠĠĠ Ġval Ġsize Ġ= Ġmem . capacity () ĊĠĠĠĠĠĠĠ Ġadditional Coverage . addAll (( 0 Ġuntil Ġsize ). filter Ġ{ Ġmem [ it ] Ġ> Ġ 0 Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Jvm Static ĊĠĠĠ Ġfun Ġcompute File Coverage ( covered Ids : ĠInt Array ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcoverage Ġ= Ġanalyze Coverage ( covered Ids . toSet ()) Ġ?: Ġreturn Ġ" No Ġclasses Ġwere Ġinstrument ed " ĊĠĠĠĠĠĠĠ Ġreturn Ġcoverage . source Files . join ToString ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"\ n ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprefix Ġ= Ġ" Branch Ġcoverage :\ n ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpostfix Ġ= Ġ"\ n \ n " ĊĠĠĠĠĠĠĠ Ġ) Ġ{ Ġfile Coverage Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcounter Ġ= Ġfile Coverage . branch Counter ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpercentage Ġ= Ġ 1 0 0 Ġ* Ġcounter . covered Ratio ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ file Coverage . name }: Ġ${ counter . covered Count }/${ counter . total Count } Ġ(${ percentage . format ( 2 )} % )" ĊĠĠĠĠĠĠĠ Ġ} Ġ+ Ġcoverage . source Files . join ToString ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"\ n ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprefix Ġ= Ġ" Line Ġcoverage :\ n ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpostfix Ġ= Ġ"\ n \ n " ĊĠĠĠĠĠĠĠ Ġ) Ġ{ Ġfile Coverage Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcounter Ġ= Ġfile Coverage . line Counter ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpercentage Ġ= Ġ 1 0 0 Ġ* Ġcounter . covered Ratio ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ file Coverage . name }: Ġ${ counter . covered Count }/${ counter . total Count } Ġ(${ percentage . format ( 2 )} % )" ĊĠĠĠĠĠĠĠ Ġ} Ġ+ Ġcoverage . source Files . join ToString ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"\ n ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprefix Ġ= Ġ" In comp let ely Ġcovered Ġlines :\ n ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpostfix Ġ= Ġ"\ n \ n " ĊĠĠĠĠĠĠĠ Ġ) Ġ{ Ġfile Coverage Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ file Coverage . name }: Ġ" Ġ+ Ġ( file Coverage . first Line .. file Coverage . last Line ). filter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinstructions Ġ= Ġfile Coverage . getLine ( it ). instruction Counter ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinstructions . covered Count Ġin Ġ 1 Ġuntil Ġinstructions . total Count ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toString () ĊĠĠĠĠĠĠĠ Ġ} Ġ+ Ġcoverage . source Files . join ToString ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"\ n ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprefix Ġ= Ġ" Mis sed Ġlines :\ n ", ĊĠĠĠĠĠĠĠ Ġ) Ġ{ Ġfile Coverage Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ file Coverage . name }: Ġ" Ġ+ Ġ( file Coverage . first Line .. file Coverage . last Line ). filter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinstructions Ġ= Ġfile Coverage . getLine ( it ). instruction Counter ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinstructions . covered Count Ġ== Ġ 0 Ġ&& Ġinstructions . total Count Ġ> Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. toString () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠDouble . format ( digits : ĠInt ) Ġ= Ġ"% .${ digits } f ". format ( this ) ĊĊĠĠĠ Ġprivate Ġfun Ġdump J aco co Coverage ( covered Ids : ĠSet < Int >): ĠByteArray ? Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠUpdate Ġthe Ġlist Ġof Ġcovered ĠIDs Ġwith Ġthe Ġcoverage Ġinformation Ġfor Ġthe Ġcurrent Ġrun . ĊĠĠĠĠĠĠĠ Ġupdate Cover ed Ids With Coverage Map () ĊĊĠĠĠĠĠĠĠ Ġval Ġdump Timestamp Ġ= ĠInstant . now () ĊĠĠĠĠĠĠĠ Ġval Ġout Stream Ġ= ĠByteArrayOutputStream () ĊĠĠĠĠĠĠĠ Ġval Ġout Writer Ġ= ĠExecution Data Writer ( out Stream ) ĊĠĠĠĠĠĠĠ Ġ// ĠReturn Ġnull Ġif Ġno Ġclass Ġhas Ġbeen Ġinstrument ed . ĊĠĠĠĠĠĠĠ Ġval Ġstart Timestamp Ġ= Ġstart Timestamp Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġout Writer . visit Session Info ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSession Info ( UUID . randomUUID (). toString (), Ġstart Timestamp . epoch Second , Ġdump Timestamp . epoch Second ) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġval Ġsorted Cover ed Ids Ġ= Ġ( additional Coverage Ġ+ Ġcovered Ids ). sorted (). to IntArray () ĊĠĠĠĠĠĠĠ Ġfor Ġ(( internal ClassName , Ġinfo ) Ġin Ġinstrument ed Class Info ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠDetermine Ġthe Ġsub array Ġof Ġcoverage ĠIDs Ġin Ġsorted Cover ed Ids Ġthat Ġcontains Ġthe ĠIDs Ġgenerated Ġwhile ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġinstrument ing Ġthe Ġcurrent Ġclass . ĠSince Ġthe ĠID Ġarray Ġis Ġsorted , Ġuse Ġbinary Ġsearch . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcovered Ids Start Ġ= Ġsorted Cover ed Ids . binary Search ( info . initial Edge Id ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( covered Ids Start Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcovered Ids Start Ġ= Ġ-( covered Ids Start Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcovered Ids End Ġ= Ġsorted Cover ed Ids . binary Search ( info . next Edge Id ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( covered Ids End Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcovered Ids End Ġ= Ġ-( covered Ids End Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( covered Ids Start Ġ== Ġcovered Ids End ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠNo Ġcoverage Ġdata Ġfor Ġthe Ġclass . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( covered Ids Start Ġin Ġ 0 Ġuntil Ġcovered Ids End Ġ&& Ġcovered Ids End Ġ<= Ġsorted Cover ed Ids . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Invalid Ġrange Ġ[$ covered Ids Start , Ġ$ covered Ids End ) Ġwith Ġcovered Ids . size =${ sorted Cover ed Ids . size }" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠGenerate Ġa Ġprob es Ġarray Ġfor Ġthe Ġcurrent Ġclass Ġonly , Ġi . e ., Ġmapping Ġinfo . initial Edge Id Ġto Ġ 0 . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprob es Ġ= ĠBoolean Array ( info . next Edge Id Ġ- Ġinfo . initial Edge Id ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( covered Ids Start Ġuntil Ġcovered Ids End ). as Sequence () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġglobal Edge Id Ġ= Ġsorted Cover ed Ids [ it ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġglobal Edge Id Ġ- Ġinfo . initial Edge Id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġclass Local Edge Id Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprob es [ class Local Edge Id ] Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġout Writer . visit Class Execution ( Execution Data ( info . class Id , Ġinternal ClassName , Ġprob es )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġout Stream . toByteArray () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġanalyze Coverage ( covered Ids : ĠSet < Int >): ĠCoverage Builder ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcoverage Ġ= ĠCoverage Builder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġraw Execution Data Ġ= Ġdump J aco co Coverage ( covered Ids ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexecution DataStore Ġ= ĠExecution DataStore () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsession Info Store Ġ= ĠSession Info Store () ĊĠĠĠĠĠĠĠĠĠĠĠ ĠByteArrayInputStream ( raw Execution Data ). use Ġ{ Ġstream Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExecution DataReader ( stream ). run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Execution Data Visitor ( execution DataStore ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Session Info Visitor ( session Info Store ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġread () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( internal ClassName , Ġinfo ) Ġin Ġinstrument ed Class Info ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠEdge Coverage Instrument or ( 0 ). analyze ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexecution DataStore , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcoverage , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinfo . byte code , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinternal ClassName ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcoverage ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . printStackTrace () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ