Skip to content

Commit ad42e13

Browse files
fixes after adamw's feedback
- add PlayServerTest instead of NettyCatsServerTest - improve fs2 implementation
1 parent bc5fb84 commit ad42e13

File tree

3 files changed

+74
-103
lines changed

3 files changed

+74
-103
lines changed

server/netty-server/cats/src/test/scala/sttp/tapir/server/netty/cats/NettyCatsRequestTimeoutTest.scala

Lines changed: 0 additions & 95 deletions
This file was deleted.

server/netty-server/cats/src/test/scala/sttp/tapir/server/netty/cats/NettyCatsServerTest.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ class NettyCatsServerTest extends TestSuite with EitherValues {
4949
override def functionToPipe[A, B](f: A => B): streams.Pipe[A, B] = in => in.map(f)
5050
override def emptyPipe[A, B]: fs2.Pipe[IO, A, B] = _ => fs2.Stream.empty
5151
}
52-
.tests() ++
53-
new NettyCatsRequestTimeoutTest(dispatcher, eventLoopGroup, backend).tests()
52+
.tests()
5453

5554
IO.pure((tests, eventLoopGroup))
5655
} { case (_, eventLoopGroup) =>

server/play-server/src/test/scala/sttp/tapir/server/play/PlayServerTest.scala

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,43 @@
11
package sttp.tapir.server.play
22

3+
import scala.concurrent.duration.{DurationInt, FiniteDuration}
34
import org.apache.pekko.actor.ActorSystem
45
import org.apache.pekko.stream.scaladsl.{Flow, Sink, Source}
56
import cats.data.NonEmptyList
67
import cats.effect.{IO, Resource}
78
import cats.effect.unsafe.implicits.global
8-
import org.scalatest.matchers.should.Matchers._
9+
import com.typesafe.config.ConfigFactory
10+
import org.apache.pekko.util.ByteString
11+
import org.scalatest.matchers.should.Matchers.{fail, _}
12+
import play.api.{Configuration, Mode}
913
import play.api.http.ParserConfiguration
14+
import play.api.routing.Router
15+
import play.core.server.{DefaultPekkoHttpServerComponents, ServerConfig}
16+
import sttp.capabilities.Streams
17+
import sttp.capabilities.fs2.Fs2Streams
1018
import sttp.capabilities.pekko.PekkoStreams
1119
import sttp.client3._
12-
import sttp.model.{MediaType, Part, StatusCode}
20+
import sttp.model.{HeaderNames, MediaType, Part, StatusCode}
1321
import sttp.monad.FutureMonad
1422
import sttp.tapir._
1523
import sttp.tapir.server.tests._
1624
import sttp.tapir.tests.{Test, TestSuite}
25+
import fs2.{Chunk, Stream}
26+
import sttp.capabilities.fs2.Fs2Streams
1727

1828
import scala.concurrent.Future
29+
import scala.concurrent.duration.FiniteDuration
1930

2031
class PlayServerTest extends TestSuite {
2132

2233
def actorSystemResource: Resource[IO, ActorSystem] =
2334
Resource.make(IO.delay(ActorSystem()))(actorSystem => IO.fromFuture(IO.delay(actorSystem.terminate())).void)
2435

2536
override def tests: Resource[IO, List[Test]] = backendResource.flatMap { backend =>
26-
actorSystemResource.map { implicit actorSystem =>
27-
implicit val m: FutureMonad = new FutureMonad()(actorSystem.dispatcher)
37+
actorSystemResource.map { implicit _actorSystem =>
38+
implicit val m: FutureMonad = new FutureMonad()(_actorSystem.dispatcher)
2839

29-
val interpreter = new PlayTestServerInterpreter()(actorSystem)
40+
val interpreter = new PlayTestServerInterpreter()(_actorSystem)
3041
val createServerTest = new DefaultCreateServerTest(backend, interpreter)
3142

3243
def additionalTests(): List[Test] = List(
@@ -98,7 +109,61 @@ class PlayServerTest extends TestSuite {
98109
}
99110
}
100111
.unsafeToFuture()
101-
}
112+
},
113+
Test("chunked transmission lasts longer than given timeout") {
114+
val chunkSize = 100
115+
val beforeSendingSecondChunk: FiniteDuration = 2.second
116+
val requestTimeout: FiniteDuration = 1.second
117+
118+
val e =
119+
endpoint.post
120+
.in(header[Long](HeaderNames.ContentLength))
121+
.in(streamTextBody(PekkoStreams)(CodecFormat.TextPlain()))
122+
.out(header[Long](HeaderNames.ContentLength))
123+
.out(streamTextBody(PekkoStreams)(CodecFormat.TextPlain()))
124+
.serverLogicSuccess[Future] { case (length, stream) =>
125+
Future.successful(length, stream)
126+
}
127+
128+
val components: DefaultPekkoHttpServerComponents = new DefaultPekkoHttpServerComponents {
129+
val initialServerConfig: ServerConfig = ServerConfig(port = Some(0), address = "127.0.0.1", mode = Mode.Test)
130+
131+
val customConf: Configuration =
132+
Configuration(
133+
ConfigFactory.parseString(s"play { server.pekko.requestTimeout=${requestTimeout.toString} }")
134+
)
135+
override lazy val serverConfig: ServerConfig =
136+
initialServerConfig.copy(configuration = customConf.withFallback(initialServerConfig.configuration))
137+
override lazy val actorSystem: ActorSystem = ActorSystem("tapir", defaultExecutionContext = Some(_actorSystem.dispatcher))
138+
override lazy val router: Router = Router.from(PlayServerInterpreter().toRoutes(e)).withPrefix("/chunks")
139+
}
140+
141+
def createStream(chunkSize: Int, beforeSendingSecondChunk: FiniteDuration): Stream[IO, Byte] = {
142+
val chunk = Chunk.array(Array.fill(chunkSize)('A'.toByte))
143+
val initialChunks = Stream.chunk(chunk)
144+
val delayedChunk = Stream.sleep[IO](beforeSendingSecondChunk) >> Stream.chunk(chunk)
145+
initialChunks ++ delayedChunk
146+
}
147+
148+
val inputStream = createStream(chunkSize, beforeSendingSecondChunk)
149+
150+
val bind = IO.blocking(components.server)
151+
Resource.make(bind)(s => IO.blocking(s.stop()))
152+
.map(_.mainAddress.getPort)
153+
.use { port =>
154+
basicRequest
155+
.post(uri"http://localhost:$port/chunks")
156+
.contentLength(2 * chunkSize)
157+
.streamBody(Fs2Streams[IO])(inputStream)
158+
.send(backend)
159+
.map{ response =>
160+
response.code shouldBe StatusCode.Ok
161+
response.contentLength shouldBe Some(2 * chunkSize)
162+
response.body shouldBe Right("A" * 2 * chunkSize)
163+
}
164+
}
165+
.unsafeToFuture()
166+
},
102167
)
103168

104169
def drainPekko(stream: PekkoStreams.BinaryStream): Future[Unit] =
@@ -135,4 +200,6 @@ class PlayServerTest extends TestSuite {
135200
additionalTests()
136201
}
137202
}
203+
204+
override def testNameFilter: Option[String] = Some("chunked transmission lasts longer than given timeout")
138205
}

0 commit comments

Comments
 (0)