/* Ċ Ġ* ĠCopyright Ġ 2 0 1 6 - 2 0 1 9 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense . Ċ Ġ*/ Ċ Ċ package Ġkotlinx . coroutines . select s Ċ Ċ import Ġkotlinx . atomic fu .* Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . channels .* Ċ import Ġorg . junit .* Ċ import Ġorg . junit . Ignore Ċ import Ġorg . junit . Test Ċ import Ġkotlin . math .* Ċ import Ġkotlin . test .* Ċ Ċ /** Ċ Ġ* ĠA Ġstress - test Ġon Ġlock - fre ed om Ġof Ġselect Ġsending / re ceiving Ġinto Ġopposite Ġchannels . Ċ Ġ*/ Ċ class ĠSelect Dead lock LF St ress Test Ġ: ĠTest Base () Ġ{ ĊĠĠĠ Ġprivate Ġval Ġenv Ġ= ĠLock F reed om Test Environment (" Select Dead lock LF St ress Test ", Ġallow Sus pended Threads Ġ= Ġ 1 ) ĊĠĠĠ Ġprivate Ġval Ġn Seconds Ġ= Ġ 5 Ġ* Ġstress Test Multiplier ĊĊĠĠĠ Ġprivate Ġval Ġc 1 Ġ= ĠChannel < Long >() ĊĠĠĠ Ġprivate Ġval Ġc 2 Ġ= ĠChannel < Long >() ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Lock F reed om () Ġ= Ġtest Sc enarios ( ĊĠĠĠĠĠĠĠ Ġ" s 1 r 2 ", ĊĠĠĠĠĠĠĠ Ġ" s 2 r 1 ", ĊĠĠĠĠĠĠĠ Ġ" r 1 s 2 ", ĊĠĠĠĠĠĠĠ Ġ" r 2 s 1 " ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġprivate Ġfun Ġtest Sc enarios ( var arg Ġscenarios : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġenv . on Completion Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġc 1 . cancel ( Test Completed ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġc 2 . cancel ( Test Completed ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġt Ġ= Ġscenarios . map Indexed Ġ{ Ġi , Ġscenario Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġidx Ġ= Ġi Ġ+ Ġ 1 L ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTest Def ( idx , Ġ"$ idx Ġ[$ scenario ]", Ġscenario ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġt . forEach Ġ{ Ġit . test () Ġ} ĊĠĠĠĠĠĠĠ Ġenv . perform Test ( n Seconds ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġt . forEach Ġ{ Ġprintln ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġinner Ġclass ĠTest Def ( ĊĠĠĠĠĠĠĠ Ġvar Ġsend Index : ĠLong Ġ= Ġ 0 L , ĊĠĠĠĠĠĠĠ Ġval Ġname : ĠString , ĊĠĠĠĠĠĠĠ Ġscenario : ĠString ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġreceive Index Ġ= Ġ 0 L ĊĊĠĠĠĠĠĠĠ Ġval Ġclauses : ĠList < Select Builder < Unit >. () Ġ-> ĠUnit > Ġ= ĠArrayList < Select Builder < Unit >. () Ġ-> ĠUnit >(). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequire ( scenario . length Ġ% Ġ 2 Ġ== Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġscenario . indices Ġstep Ġ 2 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġch Ġ= Ġwhen Ġ( val Ġc Ġ= Ġscenario [ i Ġ+ Ġ 1 ]) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ' 1 ' Ġ-> Ġc 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ' 2 ' Ġ-> Ġc 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġerror (" Channel Ġ'$ c '") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclause Ġ= Ġwhen Ġ( val Ġop Ġ= Ġscenario [ i ]) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ' s ' Ġ-> Ġfun ĠSelect Builder < Unit >. () Ġ{ Ġsend Clause ( ch ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ' r ' Ġ-> Ġfun ĠSelect Builder < Unit >. () Ġ{ Ġreceive Clause ( ch ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġerror (" Operation Ġ'$ op '") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd ( clause ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġtest () Ġ= Ġenv . test Thread ( name ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdo Send Receive () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġsuspend Ġfun Ġdo Send Receive () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselect < Unit > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( clause Ġin Ġclauses ) Ġclause () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠTest Completed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( env . is Completed ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠSelect Builder < Unit >. send Clause ( c : ĠChannel < Long >) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġc . on Send ( send Index ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend Index Ġ+= Ġ 4 L ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠSelect Builder < Unit >. receive Clause ( c : ĠChannel < Long >) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġc . on Receive Ġ{ Ġi Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreceive Index Ġ= Ġmax ( i , Ġreceive Index ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun ĠtoString (): ĠString Ġ= Ġ"$ name : Ġsend =$ send Index , Ġreceived =$ receive Index " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠTest Completed Ġ: ĠC ancellation Exception () Ċ }