package Ġu y . ko hes ive . solr . under tow Ċ Ċ import Ġcom . google . common . base . Stop watch Ċ import Ġio . under tow . Under tow Ċ import Ġio . under tow . server . Http Handler Ċ import Ġio . under tow . server . HttpServer Exchange Ċ import Ġio . under tow . server . handlers . Response Code Handler Ċ import Ġnl . k omp onent s . kov enant . K ov enant Ċ import Ġnl . k omp onent s . kov enant . all Ċ import Ġnl . k omp onent s . kov enant . build Dispatcher Ċ import Ġnl . k omp onent s . kov enant . task Ċ import Ġorg . junit . Ignore Ċ import Ġorg . junit . Test Ċ import Ġjava . io . IOException Ċ import Ġjava . net . Http URLConnection Ċ import Ġjava . net . URL Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġjava . util . concurrent . atomic . Atomic Integer Ċ import Ġkotlin . test . assertEquals Ċ import Ġkotlin . test . assertTrue Ċ Ċ class ĠTest Request PerSecond Rate Limiter Ġ{ ĊĠĠĠ Ġclass ĠPause Handler ( val Ġpause Time : ĠLong ) Ġ: ĠHttp Handler Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcomplete Ġ= ĠResponse Code Handler ( 2 0 0 ) ĊĠĠĠĠĠĠĠ Ġvar Ġreq Count : ĠAtomicInteger Ġ= ĠAtomicInteger ( 0 ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġreset Req Count () Ġ= Ġreq Count . set ( 0 ) ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġhandle Request ( exchange : ĠHttp Server Exchange ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( exchange . isIn Io Thread ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexchange . dispatch ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreq Count . increment AndGet () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pause Time Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" SI MUL ATING ĠS LOW ĠSERVER Ġ... Ġpause Ġfor Ġ$ pause Time ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( pause Time ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomplete . handle Request ( exchange ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġ@ Ignore (" This Ġfeels Ġlike Ġa Ġfrag ile Ġway Ġto Ġtest Ġthis , Ġwould Ġbe Ġbetter Ġif ĠGu ava Ġlet Ġus Ġtest Ġthe Ġrate Ġlimit er Ġthe Ġsame Ġway Ġthey Ġdo Ġwith Ġa Ġfake Ġsystem Ġtimer ") ĊĠĠĠ Ġfun Ġtest RateLimit ing Handler () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmax R ps Ġ= Ġ 1 0 L ĊĠĠĠĠĠĠĠ Ġval Ġms Per Request Ġ= Ġ( 1 0 0 0 L Ġ/ Ġmax R ps ). coerce At Least ( 1 L ). coerce At Most ( 1 0 0 0 L ) ĊĠĠĠĠĠĠĠ Ġval Ġmin Pause On Busy Millis Ġ= Ġ 1 0 L ĊĠĠĠĠĠĠĠ Ġval Ġnum Slots To Hope For In Future Ġ= Ġ 2 ĊĠĠĠĠĠĠĠ Ġval Ġmax Pause On Busy Millis Ġ= Ġ 2 5 L Ġ// Ġ( ms Per Request Ġ* Ġnum Slots To Hope For In Future ). minimum ( min Pause On Busy Millis ). maximum ( 5 0 0 L ) ĊĊĠĠĠĠĠĠĠ Ġval Ġdelay Multiple Ġ= Ġ 3 ĊĠĠĠĠĠĠĠ Ġval Ġms Sim Pause Ġ= Ġms Per Request Ġ* Ġdelay Multiple Ġ// Ġ( ms Per Request Ġ/ Ġ 2 ). to Long () ĊĊĠĠĠĠĠĠĠ Ġprintln (" max R ps : ĠĠĠĠĠĠĠ Ġ$ max R ps ") ĊĠĠĠĠĠĠĠ Ġprintln (" ms Per Request : Ġ Ġ$ ms Per Request ") ĊĠĠĠĠĠĠĠ Ġprintln (" ms Sim Pause : ĠĠĠ Ġ$ ms Sim Pause ") ĊĠĠĠĠĠĠĠ Ġprintln (" min Pause : ĠĠĠĠĠ Ġ$ min Pause On Busy Millis ") ĊĠĠĠĠĠĠĠ Ġprintln (" max Pause : ĠĠĠĠĠ Ġ$ max Pause On Busy Millis ") ĊĠĠĠĠĠĠĠ Ġval Ġtest Port Ġ= Ġ 1 1 0 2 2 ĊĠĠĠĠĠĠĠ Ġval Ġpause Handler Ġ= ĠPause Handler ( ms Sim Pause ) ĊĠĠĠĠĠĠĠ Ġval Ġserver Ġ= ĠUnder tow . builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Worker Threads ( 2 0 0 ) Ġ// Ġhigher Ġthan ĠR PS Ġ* Ġ 3 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Http Listener ( test Port , Ġ" 0 . 0 . 0 . 0 ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠRequest PerSecond Rate Limiter ( max R ps , Ġpause Handler , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmin Pause On Busy Millis Ġ= Ġmin Pause On Busy Millis , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmax Pause On Busy Millis Ġ= Ġmax Pause On Busy Millis )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġserver . start () ĊĊĠĠĠĠĠĠĠ Ġval Ġreq Count Ġ= ĠAtomicInteger ( 0 ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġreset Req Count () Ġ= Ġreq Count . set ( 0 ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġhit Server (): ĠInt Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠURL (" http :// localhost :${ test Port } "). open Connection (). let Ġ{ Ġit Ġas ĠHttp URLConnection Ġ}. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . request Method Ġ= Ġ" GET " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreq Count . increment AndGet () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . connect () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . inputStream . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(" Ġ 5 0 3 Ġ" Ġ! in Ġex . message Ġ?: Ġ"") Ġthrow Ġex ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . response Code ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġrange Ġ= Ġ 1 .. max R ps ĊĊĊĠĠĠĠĠĠĠ Ġpause Handler . reset Req Count () ĊĠĠĠĠĠĠĠ Ġval Ġstop Watch Ġ= ĠStop watch . create Un started () ĊĊĠĠĠĠĠĠĠ Ġfun Ġreset All () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstop Watch . reset () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstop Watch . start () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpause Handler . reset Req Count () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreset Req Count () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġprint All () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġelapsed Ġ= Ġstop Watch . elapsed ( TimeUnit . SECONDS ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsent Req s Ġ= Ġreq Count . get () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġreceived Req s Ġ= Ġpause Handler . req Count . get () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" :: > Ġ[$ elapsed Ġsecs ] ĠReq Ġsent Ġ= Ġ$ sent Req s Ġat Ġ${ sent Req s . toDouble () Ġ/ Ġelapsed }/ s , Ġpassed Ġ= Ġ$ received Req s Ġat Ġ${ received Req s . toDouble () Ġ/ Ġelapsed }/ s ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġ< T Ġ: ĠAny > Ġwith Time Stats ( block : Ġ() Ġ-> ĠT ): ĠT Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreset All () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġt Ġ= Ġblock () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprint All () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġt ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġwith Time Stats Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Running Ġend Ġto Ġend Ġsafely :") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsafe Run Ġ= Ġ( 1 .. max R ps ). map Ġ{ Ġhit Server () Ġ}. map Ġ{ Ġprintln (" ĠĠ Ġ${ it }"); Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( range . map Ġ{ Ġ 2 0 0 Ġ}, Ġsafe Run ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprintln (" Waiting ...") ĊĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 0 L ) ĊĊĠĠĠĠĠĠĠ Ġval Ġat The Limit Context Ġ= ĠK ov enant . create Context Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġworker Context . dispatcher Ġ= Ġbuild Dispatcher Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconcurrent Tasks Ġ= Ġdelay Multiple ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġbigger Range Ġ= Ġ 1 .. range . last Ġ* Ġdelay Multiple Ġ* Ġ 3 ĊĊĠĠĠĠĠĠĠ Ġval Ġresult 2 Ġ= Ġwith Time Stats Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Running ĠS AF ELY Ġ$ delay Multiple Ġat Ġtime Ġconcurrent ly :") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrunning 2 Ġ= Ġall ( big ger Range . map Ġ{ Ġtask ( context Ġ= Ġat The Limit Context ) Ġ{ Ġhit Server () Ġ} Ġ}, Ġcancel Others OnError Ġ= Ġtrue , Ġcontext Ġ= Ġat The Limit Context ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrunning 2 . get () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠassertEquals ( big ger Range . map Ġ{ Ġ 2 0 0 Ġ}, Ġresult 2 ) ĊĊĠĠĠĠĠĠĠ Ġprintln (" Waiting ...") ĊĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 0 L ) ĊĊĠĠĠĠĠĠĠ Ġval Ġoverload Delay Multiple Ġ= Ġdelay Multiple Ġ+ Ġ 2 ĊĠĠĠĠĠĠĠ Ġval Ġoverload Context Ġ= ĠK ov enant . create Context Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġworker Context . dispatcher Ġ= Ġbuild Dispatcher Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconcurrent Tasks Ġ= Ġoverload Delay Multiple ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġbiggest Range Ġ= Ġ 1 .. range . last Ġ* Ġdelay Multiple Ġ* Ġ 1 5 ĊĊĠĠĠĠĠĠĠ Ġval Ġresult 3 Ġ= Ġwith Time Stats Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Running ĠD ANG ERO US LY Ġ$ overload Delay Multiple Ġat Ġtime Ġconcurrent ly :") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrunning 3 Ġ= Ġall ( big gest Range . map Ġ{ Ġtask ( context Ġ= Ġoverload Context ) Ġ{ Ġhit Server () Ġ} Ġ}, Ġcancel Others OnError Ġ= Ġtrue , Ġcontext Ġ= Ġoverload Context ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrunning 3 . get () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġwe Ġshould ĠNOT Ġhave Ġall Ġ 2 0 0 's ĊĠĠĠĠĠĠĠ ĠassertTrue ( result 3 . count Ġ{ Ġit Ġ!= Ġ 2 0 0 Ġ} Ġ> Ġ 0 , Ġ" We Ġshould Ġhave Ġat Ġleast Ġa Ġfew Ġ 5 0 3 's ") ĊĊĠĠĠĠĠĠĠ Ġprintln () ĊĠĠĠĠĠĠĠ Ġprintln (" Final Ġover loaded Ġth rott les Ġ= Ġ${ result 3 . count Ġ{ Ġit Ġ!= Ġ 2 0 0 Ġ}} Ġout Ġof Ġ${ result 3 . size }") ĊĠĠĠ Ġ} Ċ }