11package io .udash
22package rest
33
4- import com .avsystem .commons ._
4+ import com .avsystem .commons .*
5+ import com .avsystem .commons .misc .ScalaDurationExtensions .durationIntOps
56import io .udash .rest .raw .RawRest
67import io .udash .rest .raw .RawRest .HandleRequest
8+ import monix .eval .Task
79import monix .execution .Scheduler
810import org .scalactic .source .Position
11+ import org .scalatest .concurrent .PatienceConfiguration .Timeout
912import org .scalatest .concurrent .ScalaFutures
1013import org .scalatest .funsuite .AnyFunSuite
1114
15+ import scala .concurrent .duration .FiniteDuration
16+
1217abstract class RestApiTest extends AnyFunSuite with ScalaFutures {
18+
19+ protected final val MaxConnections : Int = 1 // to timeout quickly
20+ protected final val Connections : Int = 10 // > MaxConnections
21+ protected final val CallTimeout : FiniteDuration = 300 .millis // << idle timeout
22+
1323 implicit def scheduler : Scheduler = Scheduler .global
1424
1525 final val serverHandle : RawRest .HandleRequest =
@@ -30,6 +40,9 @@ abstract class RestApiTest extends AnyFunSuite with ScalaFutures {
3040 case arr : Array [_] => IArraySeq .empty[AnyRef ] ++ arr.iterator.map(mkDeep)
3141 case _ => value
3242 }
43+
44+ def getNeverGetCounter (): Int = RestTestApi .Impl .neverGetCounter.get()
45+ def resetNeverGetCounter (): Unit = RestTestApi .Impl .neverGetCounter.set(0 )
3346}
3447
3548trait RestApiTestScenarios extends RestApiTest {
@@ -89,6 +102,29 @@ trait RestApiTestScenarios extends RestApiTest {
89102 test(" body using third party type" ) {
90103 testCall(_.thirdPartyBody(HasThirdParty (ThirdParty (5 ))))
91104 }
105+
106+ test(" close connection on monix task timeout" ) {
107+ resetNeverGetCounter()
108+ Task
109+ .traverse(List .range(0 , Connections ))(_ => Task .deferFuture(proxy.neverGet).timeout(CallTimeout ).failed)
110+ .map(_ => assertResult(expected = Connections )(actual = getNeverGetCounter())) // neverGet should be called Connections times
111+ .runToFuture
112+ .futureValue(Timeout (30 .seconds))
113+ }
114+
115+ test(" close connection on monix task cancellation" ) {
116+ resetNeverGetCounter()
117+ Task
118+ .traverse(List .range(0 , Connections )) { i =>
119+ val cancelable = Task .deferFuture(proxy.neverGet).runAsync(_ => ())
120+ Task .sleep(100 .millis)
121+ .restartUntil(_ => getNeverGetCounter() >= i)
122+ .map(_ => cancelable.cancel())
123+ }
124+ .map(_ => assertResult(expected = Connections )(actual = getNeverGetCounter())) // neverGet should be called Connections times
125+ .runToFuture
126+ .futureValue(Timeout (30 .seconds))
127+ }
92128}
93129
94130class DirectRestApiTest extends RestApiTestScenarios {
0 commit comments