package Ġintegration Ċ Ċ import Ġcom . nat pr y ce . ham k rest . all Elements Ċ import Ġcom . nat pr y ce . ham k rest . and Ċ import Ġcom . nat pr y ce . ham k rest . assertion . assertThat Ċ import Ġcom . nat pr y ce . ham k rest . contains Substring Ċ import Ġcom . nat pr y ce . ham k rest . equalTo Ċ import Ġcom . nat pr y ce . ham k rest . has Size Ċ import Ġorg . http 4 k . client . to Client Status Ċ import Ġorg . http 4 k . core . Http Handler Ċ import Ġorg . http 4 k . core . Method . GET Ċ import Ġorg . http 4 k . core . Method . POST Ċ import Ġorg . http 4 k . core . Request Ċ import Ġorg . http 4 k . core . Response Ċ import Ġorg . http 4 k . core . Status Ċ import Ġorg . http 4 k . ham k rest . has Body Ċ import Ġorg . http 4 k . ham k rest . has Status Ċ import Ġorg . http 4 k . server . Http 4 k Server Ċ import Ġorg . http 4 k . server . Server Config . Stop Mode Ċ import Ġorg . http 4 k . server . Server Config . Stop Mode . Grace ful Ċ import Ġorg . http 4 k . server . Server Config . Stop Mode . Immediate Ċ import Ġorg . http 4 k . server . Server Config . Unsupported Stop Mode Ċ import Ġorg . http 4 k . testing . Server Backend Ċ import Ġorg . http 4 k . testing . Server In Docker Ċ import Ġorg . junit . jupiter . api . Test Ċ import Ġorg . junit . jupiter . api . assert All Ċ import Ġorg . junit . jupiter . api . assert Throws Ċ import Ġorg . junit . jupiter . api . assert Timeout Ċ import Ġorg . opent est 4 j . Test Abort ed Exception Ċ import Ġjava . io . IOException Ċ import Ġjava . time . Duration . of Millis Ċ import Ġjava . time . Duration . of Seconds Ċ import Ġjava . util . concurrent . Concurrent Linked Queue Ċ import Ġjava . util . concurrent . Count DownLatch Ċ import Ġjava . util . concurrent . TimeUnit . SECONDS Ċ import Ġkotlin . concurrent . thread Ċ Ċ abstract Ġclass ĠServer Stop Contract ( ĊĠĠĠ Ġprivate Ġval Ġbackend : ĠServer Backend , ĊĠĠĠ Ġprotected Ġval Ġclient : ĠHttp Handler , ĊĠĠĠ Ġenable Stop Modes : ĠConfigure Server Stop Contract . () Ġ-> ĠUnit Ċ ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġdefault Grace ful Stop Mode Ġ= ĠGr ace ful ( of Seconds ( 1 0 )) ĊĠĠĠ Ġprivate Ġval Ġtimeout Tolerance Ġ= Ġof Millis ( 1 0 0 0 ) ĊĠĠĠ Ġprivate Ġval Ġsupported Stop Modes : ĠSet < Stop Mode > ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġsupported Stop Modes Ġ= ĠConfigure Server Stop Contract () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. also ( enable Stop Modes ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. enabled Modes ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinner Ġclass ĠConfigure Server Stop Contract ( val Ġenabled Modes : ĠMutable Set < Stop Mode > Ġ= Ġmutable Set Of ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġenable Immediate Stop () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġenabled Modes . add ( Immediate ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġenable Grace ful Stop () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġenabled Modes . add ( default Grace ful Stop Mode ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval ĠHttp 4 k Server . baseUrl : ĠString Ġget () Ġ= Ġ" http :// localhost :${ port () }" ĊĊĠĠĠ Ġprivate Ġfun ĠHttp 4 k Server . wait Until Health y (): ĠHttp 4 k Server Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠstartTime Ġ= ĠSystem . currentTimeMillis () ĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertThat ( client ( Request ( GET , Ġ"${ this . baseUrl }/ health ")), Ġhas Status ( Status . OK )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ; ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠAssertionError ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( System . currentTimeMillis () Ġ- ĠstartTime Ġ>= Ġ 2 0 0 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġserver In Docker ( stop Mode : ĠStop Mode ) Ġ= Ġobject Ġ: ĠHttp 4 k Server Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġserver In Docker Ġ= ĠServer In Docker () ĊĠĠĠĠĠĠĠ Ġval Ġport Ġ= Ġ 8 0 0 0 ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġstart (): ĠHttp 4 k Server Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcontainer Id Ġ= Ġserver In Docker . start ( backend , Ġstop Mode ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġobject Ġ: ĠHttp 4 k Server Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġstart (): ĠHttp 4 k Server Ġ= Ġerror (" already Ġstarted ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġstop (): ĠHttp 4 k Server Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserver In Docker . stop ( container Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġobject Ġ: ĠHttp 4 k Server Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġstart (): ĠHttp 4 k Server Ġ= Ġerror (" already Ġstopped ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġstop (): ĠHttp 4 k Server Ġ= Ġerror (" already Ġstopped ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġport (): ĠInt Ġ= Ġport ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġport (): ĠInt Ġ= Ġport ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġstop (): ĠHttp 4 k Server Ġ= Ġerror (" server Ġnot Ġstarted ") ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġport () Ġ= Ġ 8 0 0 0 ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprepare Server ( stop Mode : ĠStop Mode ) Ġ= Ġserver In Docker ( stop Mode ). start () ĊĊĠĠĠ Ġprivate Ġfun Ġstart Server Or Skip ( stop Mode : ĠStop Mode ): ĠHttp 4 k Server Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! supported Stop Modes . contains ( stop Mode )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠTest Abort ed Exception ("$ stop Mode Ġis Ġnot Ġsupported ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġprepare Server ( stop Mode ). wait Until Health y () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠHttp 4 k Server . test Blocking Stop () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= ĠRequest ( GET , Ġ"${ baseUrl }/ health ") ĊĠĠĠĠĠĠĠ Ġstop () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġclient ( request ) ĊĊĠĠĠĠĠĠĠ ĠassertThat ( response , Ġhas Status ( Status . CONNECTION _ REF USED )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` immediate Ġstop Ġmode Ġis Ġblocking Ġon Ġstop `() Ġ{ ĊĠĠĠĠĠĠĠ Ġstart Server Or Skip ( Immediate ). test Blocking Stop () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` grace ful Ġstop Ġmode Ġis Ġblocking Ġon Ġstop `() Ġ{ ĊĠĠĠĠĠĠĠ Ġstart Server Or Skip ( default Grace ful Stop Mode ). test Blocking Stop () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` immediate Ġstop Ġmode Ġis Ġquick `() Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġserver Ġ= Ġstart Server Or Skip ( Immediate ) ĊĊĠĠĠĠĠĠĠ Ġassert Timeout ( timeout Tolerance ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġserver . stop () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` grace ful Ġstop Ġmode Ġtakes Ġat Ġmost Ġthe Ġspecified Ġtimeout Ġto Ġstop `() Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmode In Test Ġ= Ġdefault Grace ful Stop Mode ĊĠĠĠĠĠĠĠ Ġval Ġserver Ġ= Ġstart Server Or Skip ( mode In Test ) ĊĊĠĠĠĠĠĠĠ Ġassert Timeout ( mode In Test . timeout Ġ+ Ġtimeout Tolerance ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġserver . stop () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` immediate Ġstop Ġmode Ġis Ġcancell ing Ġin flight Ġrequests `() Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġserver Ġ= Ġstart Server Or Skip ( Immediate ) ĊĊĠĠĠĠĠĠĠ Ġval Ġassertion Ġ= ĠassertThrows < AssertionError > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġserver . test In flight Requests Complete During Server Stop () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠassertThat ( assertion . message !! , Ġcontains Substring (" Connection ĠRef used ")) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` grace ful Ġstop Ġmode Ġis Ġwaiting Ġfor Ġin flight Ġrequests Ġto Ġsucceed `() Ġ{ ĊĠĠĠĠĠĠĠ Ġstart Server Or Skip ( default Grace ful Stop Mode ). test In flight Requests Complete During Server Stop () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` server Ġconfig Ġthrows Ġwhen Ġinvoked Ġwith Ġunsupported Ġstop Ġmode `() Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġillegal Configuration Attempts : ĠArray < () Ġ-> ĠUnit > Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( Immediate , Ġdefault Grace ful Stop Mode ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subtract ( supported Stop Modes ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġstop Mode Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfun () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertThrows < Unsupported Stop Mode >(" should Ġthrow Ġwhen Ġinvoked Ġwith Ġ$ stop Mode ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbackend ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstop Mode ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. to Typed Array () ĊĊĠĠĠĠĠĠĠ Ġassert All (* il legal Configuration Attempts ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠHttp 4 k Server . test In flight Requests Complete During Server Stop () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresponses Ġ= ĠConcurrent Linked Queue < Response >() ĊĠĠĠĠĠĠĠ Ġval ĠnumberOf In flight Requests Ġ= Ġ 5 ĊĠĠĠĠĠĠĠ Ġval Ġcount Down In flight Requests Started Ġ= ĠCount DownLatch ( numberOf In flight Requests ) ĊĠĠĠĠĠĠĠ Ġval Ġin flight Request Threads Ġ= Ġ( 1 .. numberOf In flight Requests ). map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthread Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcount Down In flight Requests Started . count Down () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponses . add ( client ( Request ( POST , Ġ"$ baseUrl / slow - echo "). body (" Hello ")). also Ġ{ Ġit . body String () Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponses . add ( Response ( Status . CONNECTION _ REF USED . to Client Status ( e ))) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġcount Down In flight Requests Started . await ( 1 , ĠSE CON DS ) ĊĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 ) ĊĊĠĠĠĠĠĠĠ ĠassertThat ( responses . size , ĠequalTo ( 0 )) ĊĠĠĠĠĠĠĠ Ġstop () ĊĠĠĠĠĠĠĠ Ġin flight Request Threads . forEach Ġ{ Ġit . join () Ġ} ĊĊĠĠĠĠĠĠĠ ĠassertThat ( responses , Ġhas Size ( equalTo ( numberOf In flight Requests ))) ĊĠĠĠĠĠĠĠ ĠassertThat ( responses , Ġall Elements ( has Status ( Status . OK ). and ( has Body (" Hello ")) )) ĊĠĠĠ Ġ} Ċ } Ċ