package Ġcom . free let ics . co redux Ċ Ċ import Ġkotlinx . coroutines . Experimental Cor outines Api Ċ import Ġkotlinx . coroutines . channels . Channel Ċ import Ġkotlinx . coroutines . delay Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . test . Test Coroutine Scope Ċ import Ġkotlinx . coroutines . test . run Blocking Test Ċ import Ġorg . junit . Assert . assertEquals Ċ import Ġorg . junit . Assert . assertTrue Ċ import Ġorg . spe k framework . spe k 2 . Spe k Ċ import Ġorg . spe k framework . spe k 2 . style . specification . describe Ċ Ċ private Ġconst Ġval ĠDEFAULT _ DELAY _ MS Ġ= Ġ 1 0 L Ċ Ċ @ Experimental Cor outines Api Ċ object ĠC ancellable Side Effect Test Ġ: ĠSpe k ({ ĊĠĠĠ Ġdescribe (" A Ġ${ C ancellable Side Effect :: class . simple Name }") Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtest Scope Ġby Ġmemoized Ġ{ ĠTest Coroutine Scope () Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġside Effect Ġby Ġmemoized Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠC ancellable Side Effect < String , ĠInt >(" test ") Ġ{ Ġstate , Ġaction , Ġ_, Ġhandler Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcurrent State Ġ= Ġstate () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaction Ġ== Ġ 1 Ġ&& Ġcurrent State Ġ== Ġ"" Ġ-> Ġhandler Ġ{ Ġ_, Ġoutput Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdelay ( DEFAULT _ DELAY _ MS ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( 2 .. 4 ). forEach Ġ{ Ġoutput . send ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġinput Channel Ġby Ġmemoized Ġ{ ĠChannel < Int >() Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġoutput Channel Ġby Ġmemoized Ġ{ ĠChannel < Int >() Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġstate Accessor Ġby Ġmemoized Ġ{ ĠTest State Accessor ("") Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġlogger Ġby Ġmemoized Ġ{ ĠStub Side Effect Logger () Ġ} ĊĊĠĠĠĠĠĠĠ ĠbeforeEach Test Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwith ( side Effect ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstart ( input Channel , Ġstate Accessor , Ġoutput Channel , Ġlogger ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠafterEach Test Ġ{ Ġtest Scope . cleanup Test Cor outines () Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġcurrent Ġstate Ġis Ġnot Ġ\" \" ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Test Ġ{ Ġstate Accessor . setCurrent State (" some - other - state ") Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext (" and Ġon Ġnew Ġ 1 Ġaction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Test Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . launch Ġ{ Ġinput Channel . send ( 1 ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . advance Time By ( DEFAULT _ DELAY _ MS Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġnot Ġcall Ġhandler Ġfunction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( output Channel . isEmpty ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" when Ġcurrent Ġstate Ġis Ġ\" \" ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext (" and Ġon Ġnew Ġ 2 Ġaction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Test Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . launch Ġ{ Ġinput Channel . send ( 2 ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . advance Time By ( DEFAULT _ DELAY _ MS Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġnot Ġcall Ġhandler Ġfunction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( output Channel . isEmpty ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext (" and Ġon Ġnew Ġ 1 Ġaction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Test Ġ{ Ġtest Scope . launch Ġ{ Ġinput Channel . send ( 1 ) Ġ} Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġsend Ġ 2 , Ġ 3 , Ġ 4 Ġactions Ġto Ġoutput Ġchannel ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġitems Ġ= Ġmutable ListOf < Int >() ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrepeat ( 3 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . advance Time By ( DEFAULT _ DELAY _ MS ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . run Blocking Test Ġ{ Ġitems . add ( output Channel . receive ()) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( 2 , Ġ 3 , Ġ 4 ), Ġitems . toList ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext (" and Ġon Ġsecond Ġimmediate Ġ 1 Ġaction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Test Ġ{ Ġtest Scope . launch Ġ{ Ġinput Channel . send ( 1 ) Ġ} Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġsend Ġ 2 , Ġ 3 , Ġ 4 Ġactions Ġto Ġoutput Ġchannel ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġitems Ġ= Ġmutable ListOf < Int >() ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrepeat ( 3 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . advance Time By ( DEFAULT _ DELAY _ MS ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . run Blocking Test Ġ{ Ġitems . add ( output Channel . receive ()) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( listOf ( 2 , Ġ 3 , Ġ 4 ), Ġitems . toList ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġcancel Ġprevious Ġcall Ġto Ġhandler Ġfunction ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġitems Ġ= Ġmutable ListOf < Int >() ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrepeat ( 5 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Scope . advance Time By ( DEFAULT _ DELAY _ MS ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Channel . poll ()?. let Ġ{ Ġitems . add ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġitems . size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( output Channel . isEmpty ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }) Ċ