/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 9 ĠJetBrains Ġs . r . o . Ġand ĠKotlin ĠProgramming ĠLanguage Ġcontributors . Ċ Ġ* ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe Ġlicense / LICENSE . txt Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . codegen . debug Information Ċ Ċ import Ġcom . intellij . openapi . util . System Info Ċ import Ġcom . intellij . util . Path Util Ċ import Ġcom . intellij . util . System Properties Ċ import Ġcom . sun . j di . VirtualMachine Ċ import Ġcom . sun . j di . event .* Ċ import Ġcom . sun . j di . request . Event Request . SUS PEND _ ALL Ċ import Ġcom . sun . j di . request . Event Request . SUS PEND _ NONE Ċ import Ġcom . sun . j di . request . Step Request Ċ import Ġcom . sun . tools . j di . Socket Att aching Connector Ċ import Ġjunit . framework . TestCase Ċ import Ġorg . jetbrains . kotlin . backend . common . output . OutputFile Ċ import Ġorg . jetbrains . kotlin . backend . common . output . Simple OutputFile Collection Ċ import Ġorg . jetbrains . kotlin . cli . common . output . write All To Ċ import Ġorg . jetbrains . kotlin . codegen .* Ċ import Ġorg . jetbrains . kotlin . codegen . for Test Compile . For Test Compile Runtime Ċ import Ġorg . jetbrains . kotlin . codegen . state . Generation State Ċ import Ġorg . jetbrains . kotlin . test . Configuration Kind Ċ import Ġorg . jetbrains . kotlin . test . Kotlin TestUtils Ċ import Ġorg . jetbrains . kotlin . test . client server . get Generated Class Ċ import Ġorg . jetbrains . kotlin . test . client server . Test Process Server Ċ import Ġorg . jetbrains . kotlin . test . client server . Test Proxy Ċ import Ġorg . junit . After Ċ import Ġorg . junit . After Class Ċ import Ġorg . junit . Before Ċ import Ġorg . junit . BeforeClass Ċ import Ġjava . io . File Ċ import Ġjava . lang . IllegalStateException Ċ import Ġjava . net . URL ClassLoader Ċ import Ġkotlin . properties . Deleg ates Ċ Ċ abstract Ġclass ĠAbstract Ste pping Test Ġ: ĠCode gen TestCase () Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDEBUG _ ADDRESS Ġ= Ġ" 1 2 7 . 0 . 0 . 1 " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMAIN _ CLASS Ġ= Ġ" org . jetbrains . kotlin . test . client server . Test Process Server " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠTEST _ CLASS Ġ= Ġ" Test Kt " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠBO X _ METHOD Ġ= Ġ" box " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠLIN ENUM BER _ PREFIX Ġ= Ġ"// ĠLIN ENUM BER S " ĊĠĠĠĠĠĠĠ Ġvar Ġproxy Port Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġlateinit Ġvar Ġprocess : ĠProcess ĊĠĠĠĠĠĠĠ Ġlateinit Ġvar Ġvirtual Machine : ĠVirtual Machine ĊĊĠĠĠĠĠĠĠ Ġ@ BeforeClass ĊĠĠĠĠĠĠĠ Ġ@ Jvm Static ĊĠĠĠĠĠĠĠ Ġfun ĠsetUp Test () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdebug Port Ġ= Ġstart Debug gee Process () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvirtual Machine Ġ= Ġattach Debugger ( debug Port ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠsetUp VM ( virtual Machine ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġreader Ġ= Ġprocess . inputStream . buffered Reader () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreader . readLine () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġproxy Port Ġ= Ġreader . readLine () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. split (" port Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. last () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. trim () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. toInt () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreader . close () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠsetUp VM ( virtual Machine : ĠVirtual Machine ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmanager Ġ= Ġvirtual Machine . event Request Manager () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmethod Entry Req Ġ= Ġmanager . create Method Entry Request () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Entry Req . addClass Filter ( TEST _ CLASS ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Entry Req . set Suspend Policy ( SUS PEND _ ALL ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Entry Req . enable () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmethod Exit Req Ġ= Ġmanager . create Method Exit Request () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Exit Req . addClass Filter ( TEST _ CLASS ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Exit Req . set Suspend Policy ( SUS PEND _ NONE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Exit Req . enable () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġstart Debug gee Process (): ĠInt Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclasspath Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPath Util . get Jar Path For Class ( Test Process Server :: class . java ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPath Util . get Jar Path For Class ( Deleg ates :: class . java ) Ġ// ĠAdd ĠKotlin Ġruntime ĠJ AR ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjava Executable Path Ġ= Ġfind Java Executable (). absolute Path ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcommand Ġ= ĠarrayOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( System Info . is Windows ) Ġ"\" $ java Executable Path \"" Ġelse Ġjava Executable Path , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- agent lib : jd wp = transport = dt _ socket , server = y , suspend = n , address = 1 2 7 . 0 . 0 . 1 : 0 ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- ea ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- classpath ", Ġclasspath . join ToString ( File . path Separator ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMAIN _ CLASS , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTest Process Server . DEBUG _ TEST ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Ġ= ĠProcess Builder (* command ). start () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġprocess . inputStream . buffered Reader (). readLine () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. split (" address :") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. last () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. trim () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. toInt () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġattach Debugger ( port : ĠInt ): ĠVirtual Machine Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġconnector Ġ= ĠSocket Att aching Connector () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġconnector . attach ( connector . default Arguments (). to Mutable Map (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetValue (" port "). setValue ("$ port ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetValue (" hostname "). setValue ( DEBUG _ ADDRESS ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġfind Java Executable (): ĠFile Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjava Bin Ġ= ĠFile ( System Properties . get Java Home (), Ġ" bin ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠFile ( java Bin , Ġ" java . exe "). take If Ġ{ Ġit . exists () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: ĠFile ( java Bin , Ġ" java "). also Ġ{ Ġassert ( it . exists ()) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ After Class ĊĠĠĠĠĠĠĠ Ġ@ Jvm Static ĊĠĠĠĠĠĠĠ Ġfun ĠtearDown Test () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess . destroy () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Before ĊĠĠĠ Ġpublic Ġoverride Ġfun ĠsetUp () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . setUp () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ After ĊĠĠĠ Ġpublic Ġoverride Ġfun ĠtearDown () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . te ar Down () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġdo Multi File Test ( whole File : ĠFile , Ġfiles : ĠList < Test File >) Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate Environment With Mock J dk And Ide a Annotations ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠConfiguration Kind . ALL , Ġ* listOf NotNull ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Java Files ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfiles ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ). to Typed Array () ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġval Ġline Numbers Ġ= Ġwhole File ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. read Lines () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. drop While Ġ{ Ġ! it . startsWith ( LIN ENUM BER _ PREFIX ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. drop ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . drop ( 3 ). trim () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. join ToString (" Ġ") ĊĊĠĠĠĠĠĠĠ Ġload Multi Files ( files ) ĊĠĠĠĠĠĠĠ Ġval Ġclass BuilderFactory Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠOrigin Collect ing Class BuilderFactory ( Class Builder Mode . FULL ) ĊĠĠĠĠĠĠĠ Ġval Ġgeneration State Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠGeneration Utils . compile Files ( my Files . psi Files , Ġmy Environment , Ġclass BuilderFactory ) ĊĠĠĠĠĠĠĠ Ġclass File Factory Ġ= Ġgeneration State . factory ĊĊĠĠĠĠĠĠĠ Ġval Ġtemp Dir For Test Ġ= ĠKotlin TestUtils . tmp Dir (" debugger Test ") ĊĠĠĠĠĠĠĠ Ġval Ġclasses Dir Ġ= ĠFile ( temp Dir For Test , Ġ" classes ") ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclass File Factory . write All To ( classes Dir ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdo Test ( line Numbers , Ġclasses Dir , Ġvirtual Machine , Ġclass BuilderFactory , Ġclass File Factory , Ġgeneration State ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtemp Dir For Test . delete Re cursively () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġinvoke Box In Separ ate Process ( class Loader : ĠURL ClassLoader , Ġa Class : ĠClass <* >, Ġport : ĠInt ): ĠString Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġclass Path Ġ= Ġclass Loader . extract Urls (). to Mutable List () ĊĠĠĠĠĠĠĠ Ġif Ġ( class Loader Ġis ĠGenerated ClassLoader ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġout Dir Ġ= ĠKotlin TestUtils . tmp Dir For Test ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcurrent Output Ġ= ĠSimple OutputFile Collection ( class Loader . all Generated Files ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Output . write All To ( out Dir ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclass Path . add ( 0 , Ġout Dir . to URI (). to URL ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠTest Proxy ( Integer . valueOf ( port ), Ġa Class . canonical Name , Ġclass Path ). run Test No Output () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Generated ClassLoader ( classes Dir : ĠFile ): ĠURL ClassLoader Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠURL ClassLoader ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( classes Dir . to URI (). to URL ()). to Typed Array (), ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFor Test Compile Runtime . runtime Jar ClassLoader () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprotected Ġopen Ġfun Ġdo Test ( ĊĠĠĠĠĠĠĠ Ġexpected Line Numbers : ĠString , ĊĠĠĠĠĠĠĠ Ġclasses Dir : ĠFile , ĊĠĠĠĠĠĠĠ Ġvirtual Machine : ĠVirtual Machine , ĊĠĠĠĠĠĠĠ Ġfactory : ĠOrigin Collect ing Class BuilderFactory , ĊĠĠĠĠĠĠĠ Ġclass File Factory : ĠClass File Factory , ĊĠĠĠĠĠĠĠ Ġstate : ĠGeneration State ĊĠĠĠ Ġ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġclass Loader Ġ= Ġcreate Generated ClassLoader ( classes Dir ) ĊĠĠĠĠĠĠĠ Ġval Ġa Class Ġ= Ġget Generated Class ( class Loader , ĠTEST _ CLASS ) ĊĊĠĠĠĠĠĠĠ Ġval Ġmanager Ġ= Ġvirtual Machine . event Request Manager () ĊĊĠĠĠĠĠĠĠ Ġinvoke Box In Separ ate Process ( class Loader , Ġa Class , Ġproxy Port ) ĊĠĠĠĠĠĠĠ Ġval Ġlogged Events Ġ= ĠArrayList < Event >() ĊĠĠĠĠĠĠĠ Ġvar Ġshould Record Steps Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġvm Loop @ ĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġevent Set Ġ= Ġvirtual Machine . event Queue (). remove () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( event Ġin Ġevent Set ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( event ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠVM Death Event , Ġis ĠVM Disconnect Event Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak @ vm Loop ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġstart ĠVM Ġwith Ġoption Ġ' suspend = n ', Ġin Ġcase ĠVM Start Event Ġis Ġstill Ġreceived , Ġdiscard . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠVM Start Event Ġ-> Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠMethod Entry Event Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! should Record Steps Ġ&& Ġevent . location (). method (). name () Ġ== ĠBO X _ METHOD ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( manager . step Requests (). isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstep Req Ġ= Ġmanager . create Step Request ( event . thread (), ĠStep Request . STEP _ LINE , ĠStep Request . STEP _ IN TO ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstep Req . set Suspend Policy ( SUS PEND _ NONE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstep Req . addClass Ex clusion Filter (" java .* ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstep Req . addClass Ex clusion Filter (" sun .* ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstep Req . addClass Ex clusion Filter (" kotlin .* ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmanager . step Requests (). map Ġ{ Ġit . enable () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġshould Record Steps Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogged Events . add ( event ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvirtual Machine . resume () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠStep Event Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( should Record Steps Ġ&& Ġevent . location (). method (). name () Ġ== Ġ" run ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak @ vm Loop ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( should Record Steps ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogged Events . add ( event ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠMethod Exit Event Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( event . location (). method (). name () Ġ== ĠBO X _ METHOD ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmanager . step Requests (). map Ġ{ Ġit . disable () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak @ vm Loop ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" event Ġnot Ġhandled : Ġ$ event ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġactual Line Numbers Ġ= Ġlogged Events ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġevent Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ ( event Ġas ĠLoc atable Event ). location (). method ()} :${ event . location (). line Number () }" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠTestCase . assertEquals ( expected Line Numbers , Ġactual Line Numbers . join ToString (" Ġ")) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġval ĠOutput File . internal Name ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġrelative Path . substring Before Last (". class ") ĊĊĠĠĠ Ġinternal Ġval ĠOutput File . qualified Name ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġinternal Name . replace ('/', Ġ'.') Ċ } ĊĊ