/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 0 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* Ġ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 . android . tools . idea . rendering Ċ Ċ import Ġcom . android . test utils . Virtual Time Scheduler Ċ import Ġcom . android . test utils . concurrency . On Demand ExecutorService Ċ import Ġcom . google . common . util . concurrent . More Executors Ċ import Ġkotlinx . coroutines . Global Scope Ċ import Ġkotlinx . coroutines . delay Ċ import Ġkotlinx . coroutines . launch Ċ import Ġorg . junit . Assert . assertEquals Ċ import Ġorg . junit . Assert . assertFalse Ċ import Ġorg . junit . Assert . assertTrue Ċ import Ġorg . junit . Assert . fail Ċ import Ġorg . junit . Test Ċ import Ġjava . util . concurrent . Callable Ċ import Ġjava . util . concurrent . Comp letableFuture Ċ import Ġjava . util . concurrent . Completion Exception Ċ import Ġjava . util . concurrent . Count DownLatch Ċ import Ġjava . util . concurrent . ExecutionException Ċ import Ġjava . util . concurrent . Executors Ċ import Ġjava . util . concurrent . Scheduled ThreadPoolExecutor Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġjava . util . concurrent . TimeoutException Ċ import Ġjava . util . concurrent . atomic . Atomic Integer Ċ Ċ private Ġfun ĠRender Executor . run Async Action With Test Default ( queue ing Timeout : ĠLong Ġ= Ġ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġqueue ing Timeout Unit : ĠTimeUnit Ġ= ĠTimeUnit . SECONDS , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaction Timeout : ĠLong Ġ= Ġ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaction Timeout Unit : ĠTimeUnit Ġ= ĠTimeUnit . SECONDS , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrunnable : Ġ() Ġ-> ĠUnit ): ĠCompletableFuture < Void > Ġ= ĊĠ Ġrun Async Action WithTimeout ( queue ing Timeout , Ġqueue ing Timeout Unit , Ġaction Timeout , Ġaction Timeout Unit , ĠCallable < Void > Ġ{ ĊĠĠĠ Ġrunnable () ĊĠĠĠ Ġnull ĊĠ Ġ}) Ċ Ċ class ĠRender Executor Test Ġ{ ĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Timeout () Ġ{ ĊĠĠĠ Ġval Ġaction Executor Ġ= ĠOn Demand ExecutorService () ĊĠĠĠ Ġval Ġtimeout Executor Provider Ġ= ĠVirtual Time Scheduler () ĊĠĠĠ Ġval Ġexecutor Ġ= ĠRender Executor . create For Tests ( executor Provider Ġ= Ġ{ Ġaction Executor Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Executor Provider Ġ= Ġ{ Ġtimeout Executor Provider Ġ}) ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġval Ġresult Ġ= Ġexecutor . run Async Action With Test Default Ġ{ ĊĠĠĠĠĠĠĠ Ġfail (" This Ġshould Ġhave Ġnot Ġbeen Ġexecuted .") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ// ĠCalling Ġget Now Ġshould Ġnot Ġthrow Ġan Ġexception Ġsince Ġthe Ġtask Ġhas Ġnot Ġtimeout Ġyet ĊĠĠĠĠĠ Ġresult . get Now ( null ) ĊĠĠĠĠĠ Ġtimeout Executor Provider . advance By ( 5 0 0 , ĠTimeUnit . MILLISECONDS ) ĊĠĠĠĠĠ Ġresult . get Now ( null ) ĊĠĠĠĠĠ Ġtimeout Executor Provider . advance By ( 1 5 0 0 , ĠTimeUnit . MILLISECONDS ) ĊĠĠĠĠĠ Ġ// ĠNow Ġthe ĠTimeout Exception Ġshould Ġbe Ġthrown ĊĠĠĠĠĠ Ġresult . get Now ( null ) ĊĠĠĠĠĠ Ġfail (" No Ġtimeout Ġtriggered ") ĊĠĠĠ Ġ} ĊĠĠĠ Ġcatch Ġ( e : ĠCompletion Exception ) Ġ{ ĊĠĠĠĠĠ Ġ// ĠThe Ġthrown Ġtimeout Ġwill Ġhave Ġas Ġcause Ġthe Ġtimeout ĊĠĠĠĠĠ ĠassertTrue ( e . cause Ġis ĠTimeout Exception ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Execute All () Ġ{ ĊĠĠĠ Ġval Ġexecutor Ġ= ĠRender Executor . create For Tests ( executor Provider Ġ= Ġ{ ĠMore Executors . new Direct ExecutorService () Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Executor Provider Ġ= Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠScheduled ThreadPoolExecutor ( 1 ). also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . remove On Cancel Policy Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġval Ġcounter Ġ= ĠAtomicInteger ( 0 ) ĊĠĠĠĠĠ Ġval Ġlast To Execute Ġ= ĠAtomicInteger ( 0 ) ĊĊĠĠĠĠĠ Ġrepeat ( 1 0 0 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġexecutor . run Async Action With Test Default Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġcounter . increment AndGet () ĊĠĠĠĠĠĠĠĠĠ Ġlast To Execute . set ( it ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠassertEquals ( 1 0 0 0 , Ġcounter . get ()) ĊĠĠĠĠĠ ĠassertEquals ( 9 9 9 , Ġlast To Execute . get ()) ĊĠĠĠ Ġ} ĊĠĠĠ Ġfinally Ġ{ ĊĠĠĠĠĠ Ġexecutor . shutdown () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Queue Limit () Ġ{ ĊĠĠĠ Ġval Ġaction Executor Ġ= ĠOn Demand ExecutorService () ĊĠĠĠ Ġval Ġtimeout Executor Provider Ġ= ĠVirtual Time Scheduler () ĊĠĠĠ Ġval Ġexecutor Ġ= ĠRender Executor . create For Tests ( executor Provider Ġ= Ġ{ Ġaction Executor Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Executor Provider Ġ= Ġ{ Ġtimeout Executor Provider Ġ}) ĊĠĠĠ Ġval Ġcounter Ġ= ĠAtomicInteger ( 0 ) ĊĠĠĠ Ġval Ġlast To Execute Ġ= ĠAtomicInteger ( 0 ) ĊĊĠĠĠ Ġrepeat ( 1 0 0 ) Ġ{ ĊĠĠĠĠĠ Ġexecutor . run Async Action With Test Default Ġ{ ĊĠĠĠĠĠĠĠ Ġcounter . increment AndGet () ĊĠĠĠĠĠĠĠ Ġlast To Execute . set ( it ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġaction Executor . run All () ĊĠĠĠ Ġ// ĠOnly Ġa Ġmaximum Ġof Ġ 5 0 Ġtasks Ġwill Ġbe Ġqueued ĊĠĠĠ ĠassertEquals ( 5 0 , Ġcounter . get ()) ĊĠĠĠ Ġ// ĠBut Ġwe Ġhave Ġev ict ed Ġthe Ġones Ġthat Ġwere Ġwaiting , Ġso Ġthe Ġlast Ġone Ġshould Ġhave Ġexecuted Ġ( 9 9 ) ĊĠĠĠ ĠassertEquals ( 9 9 , Ġlast To Execute . get ()) ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Sync Render Action Timeout () Ġ{ ĊĠĠĠ Ġval Ġaction Executor Ġ= ĠOn Demand ExecutorService () ĊĠĠĠ Ġval Ġtimeout Executor Provider Ġ= ĠVirtual Time Scheduler () ĊĠĠĠ Ġval Ġexecutor Ġ= ĠRender Executor . create For Tests ( executor Provider Ġ= Ġ{ Ġaction Executor Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Executor Provider Ġ= Ġ{ Ġtimeout Executor Provider Ġ}) ĊĊĠĠĠ Ġ// ĠForce Ġthree Ġtimeouts Ġto Ġexceed Ġthe Ġcounter Ġfor Ġthe Ġsync Ġcall ĊĠĠĠ Ġexecutor . run Async Action With Test Default ( queue ing Timeout Ġ= Ġ 1 ) Ġ{ ĊĠĠĠ Ġ} ĊĠĠĠ Ġexecutor . run Async Action With Test Default ( queue ing Timeout Ġ= Ġ 3 ) Ġ{ ĊĠĠĠ Ġ} ĊĠĠĠ Ġexecutor . run Async Action With Test Default ( queue ing Timeout Ġ= Ġ 5 ) Ġ{ ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠThis Ġwill Ġnever Ġcomplete ĊĠĠĠ Ġexecutor . run Async Action With Test Default ( queue ing Timeout Ġ= Ġ 1 0 0 ) Ġ{ ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġtimeout Executor Provider . advance By ( 2 , ĠTimeUnit . SECONDS ) ĊĠĠĠ ĠassertEquals ( 1 , Ġexecutor . acc umulated Timeout s ) ĊĠĠĠ Ġtimeout Executor Provider . advance By ( 2 , ĠTimeUnit . SECONDS ) ĊĠĠĠ ĠassertEquals ( 2 , Ġexecutor . acc umulated Timeout s ) ĊĠĠĠ Ġtimeout Executor Provider . advance By ( 2 , ĠTimeUnit . SECONDS ) ĊĠĠĠ ĠassertEquals ( 3 , Ġexecutor . acc umulated Timeout s ) ĊĠĠĠ Ġtimeout Executor Provider . advance By ( 2 , ĠTimeUnit . SECONDS ) ĊĊĠĠĠ Ġval Ġjob Ġ= ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠ Ġ// ĠKeep Ġadv ancing Ġthe Ġtimeout Ġtimer ĊĠĠĠĠĠ Ġwhile Ġ(! timeout Executor Provider . is Shutdown ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtimeout Executor Provider . advance By ( 1 0 , ĠTimeUnit . SECONDS ) ĊĠĠĠĠĠĠĠ Ġdelay ( 5 0 0 L ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġexecutor . run Action ( Callable < Void > Ġ{ ĊĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠ Ġfail (" run Action Ġshould Ġnot Ġhave Ġaccepted Ġthe Ġrequest Ġand Ġshould Ġhave Ġthrown ĠTimeout Exception ") ĊĠĠĠ Ġ} ĊĠĠĠ Ġcatch Ġ( t : ĠExecution Exception ) Ġ{ ĊĠĠĠĠĠ ĠassertTrue ( t . cause Ġis ĠTimeout Exception ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġfinally Ġ{ ĊĠĠĠĠĠ Ġjob . cancel () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Action Timeout () Ġ{ ĊĠĠĠ Ġval Ġaction Executor Ġ= ĠExec utors . new Single Thread Executor () ĊĠĠĠ Ġval Ġtimeout Executor Provider Ġ= ĠVirtual Time Scheduler () ĊĠĠĠ Ġval Ġexecutor Ġ= ĠRender Executor . create For Tests ( executor Provider Ġ= Ġ{ Ġaction Executor Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeout Executor Provider Ġ= Ġ{ Ġtimeout Executor Provider Ġ}) ĊĊĠĠĠ Ġval Ġaction Is Running Latch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠ Ġval Ġcomplete Action Latch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġval Ġfuture Ġ= Ġexecutor . run Async Action WithTimeout ( ĊĠĠĠĠĠĠĠ Ġqueue ing Timeout Ġ= Ġ 0 , Ġqueue ing Timeout Unit Ġ= ĠTimeUnit . SECONDS , ĊĠĠĠĠĠĠĠ Ġaction Timeout Ġ= Ġ 1 0 , Ġaction Timeout Unit Ġ= ĠTimeUnit . SECONDS ) Ġ{ ĊĠĠĠĠĠĠĠ Ġaction Is Running Latch . count Down () ĊĠĠĠĠĠĠĠ Ġcomplete Action Latch . await () ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġ// ĠWait Ġuntil Ġthe Ġaction Ġhas Ġstarted Ġrunning ĊĠĠĠĠĠ Ġaction Is Running Latch . await () ĊĠĠĠĠĠ ĠassertFalse ( future . is Done ) ĊĠĠĠĠĠ Ġtimeout Executor Provider . advance By ( 5 , ĠTimeUnit . SECONDS ) ĊĠĠĠĠĠ ĠassertFalse ( future . is Done ) ĊĠĠĠĠĠ Ġtimeout Executor Provider . advance By ( 6 , ĠTimeUnit . SECONDS ) ĊĠĠĠĠĠ ĠassertTrue ( future . is Completed Exception ally ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġfinally Ġ{ ĊĠĠĠĠĠ Ġcomplete Action Latch . count Down () ĊĠĠĠĠĠ Ġaction Executor . shutdown () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Test ĊĠ Ġfun Ġtest Interrupt () Ġ{ ĊĠĠĠ Ġval Ġexecutor Ġ= ĠRender Executor . create () ĊĊĠĠĠ Ġvar Ġforce Shutdown Ġ= Ġfalse ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġrun Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠCheck Ġmanual Ġinter ruption ĊĠĠĠĠĠĠĠ Ġval Ġaction Is Running Latch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠĠĠĠĠ Ġval Ġcomplete Action Latch Ġ= ĠCount DownLatch ( 1 ) ĊĊĠĠĠĠĠĠĠ Ġexecutor . run Async Action Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġaction Is Running Latch . count Down () ĊĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! force Shutdown ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Thread . inter rupted ()) Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( 2 5 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcomplete Action Latch . count Down () ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠassertTrue ( action Is Running Latch . await ( 5 , ĠTimeUnit . SECONDS )) ĊĠĠĠĠĠĠĠ Ġexecutor . interrupt () ĊĠĠĠĠĠĠĠ ĠassertTrue ( complete Action Latch . await ( 5 , ĠTimeUnit . SECONDS )) ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġrun Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠCheck Ġinter ruption Ġvia Ġtimeout ĊĠĠĠĠĠĠĠ Ġval Ġaction Is Running Latch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠĠĠĠĠ Ġval Ġcomplete Action Latch Ġ= ĠCount DownLatch ( 1 ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠRun Ġaction Ġtiming Ġout Ġafter Ġ 1 Ġsecond ĊĠĠĠĠĠĠĠ Ġexecutor . run Async Action WithTimeout ( ĊĠĠĠĠĠĠĠĠĠĠ 1 , ĠTimeUnit . SECONDS ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġaction Is Running Latch . count Down () ĊĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! force Shutdown ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( 2 5 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcomplete Action Latch . count Down () ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠassertTrue ( action Is Running Latch . await ( 5 , ĠTimeUnit . SECONDS )) ĊĠĠĠĠĠĠĠ ĠassertTrue ( complete Action Latch . await ( 5 , ĠTimeUnit . SECONDS )) ĊĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠ Ġrun Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġaction Is Running Latch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠĠĠĠĠ Ġval Ġcomplete Action Latch Ġ= ĠCount DownLatch ( 1 ) ĊĠĠĠĠĠĠĠ Ġ// ĠCheck Ġthe Ġthread Ġis Ġstill Ġalive Ġand Ġworking ĊĠĠĠĠĠĠĠ Ġexecutor . run Async Action Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġaction Is Running Latch . count Down () ĊĠĠĠĠĠĠĠĠĠ ĠassertFalse (" The Ġinterrupted Ġstate Ġshould Ġclear Ġon Ġevery Ġnew Ġaction ", ĠThread . currentThread (). is Inter rupted ) ĊĠĠĠĠĠĠĠĠĠ Ġcomplete Action Latch . count Down () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠassertTrue ( action Is Running Latch . await ( 5 , ĠTimeUnit . SECONDS )) ĊĠĠĠĠĠĠĠ ĠassertTrue ( complete Action Latch . await ( 5 , ĠTimeUnit . SECONDS )) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠ Ġforce Shutdown Ġ= Ġtrue ĊĠĠĠĠĠ Ġexecutor . shutdown () ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ }