aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorSam Guymer <sam@guymer.me>2018-05-21 20:54:10 +1000
committerSam Guymer <sam@guymer.me>2018-05-21 21:02:24 +1000
commitccb1afe90e938fc2b8619dd960a1df1937f212be (patch)
tree0d7a6b1c653393de8422e9704b9e68bb5cf7ed91 /core
parentbcb94e252a96c78b1db29aebe47b18bfd337e764 (diff)
downloadsttp-ccb1afe90e938fc2b8619dd960a1df1937f212be.tar.gz
sttp-ccb1afe90e938fc2b8619dd960a1df1937f212be.tar.bz2
sttp-ccb1afe90e938fc2b8619dd960a1df1937f212be.zip
Code review updates
Start the test server before each backend test
Diffstat (limited to 'core')
-rw-r--r--core/src/test/resources/binaryfile.jpgbin0 -> 42010 bytes
-rw-r--r--core/src/test/resources/textfile.txt100
-rw-r--r--core/src/test/scala/com/softwaremill/sttp/testing/HttpTest.scala40
-rw-r--r--core/src/test/scala/com/softwaremill/sttp/testing/TestHttpServer.scala236
-rw-r--r--core/src/test/scala/com/softwaremill/sttp/testing/streaming/StreamingTest.scala9
5 files changed, 362 insertions, 23 deletions
diff --git a/core/src/test/resources/binaryfile.jpg b/core/src/test/resources/binaryfile.jpg
new file mode 100644
index 0000000..b9f5c5a
--- /dev/null
+++ b/core/src/test/resources/binaryfile.jpg
Binary files differ
diff --git a/core/src/test/resources/textfile.txt b/core/src/test/resources/textfile.txt
new file mode 100644
index 0000000..9904f90
--- /dev/null
+++ b/core/src/test/resources/textfile.txt
@@ -0,0 +1,100 @@
+- Lorem ipsum dolor sit amet
+- Vivamus sem ipsum.
+- Ut molestie.
+- Donec.
+- Fusce non porta.
+- Nulla ac metus. Morbi mattis.
+- Etiam varius.
+- Nulla.
+- Phasellus id mollis.
+- Suspendisse at.
+- Quisque nec leo velit.
+- Fusce.
+- Maecenas nec tristique senectus et.
+- Integer vestibulum lorem fermentum.
+- Vestibulum consectetuer dolor.
+- Lorem ipsum in.
+- Fusce condimentum auctor scelerisque, wisi.
+- Quisque.
+- Curae.
+- Curae, Nullam.
+- Curae, Integer.
+- Vestibulum dignissim massa. Donec.
+- Pellentesque sed sem.
+- Vivamus est.
+- Maecenas elit sed est.
+- Quisque sed tellus.
+- Cum sociis natoque penatibus et.
+- Fusce aliquam.
+- Donec.
+- Sed elementum, sapien accumsan odio.
+- Nam mattis, magna lectus, tincidunt.
+- Pellentesque scelerisque a, sodales.
+- Sed sed condimentum.
+- Curae, In nonummy. Phasellus adipiscing.
+- Vestibulum quis diam mollis.
+- Sed eros. Duis ipsum.
+- Aenean pellentesque at, mollis tempus.
+- Cras ornare facilisis sodales. Aenean.
+- Cum sociis natoque penatibus.
+- Donec id nulla.
+- Quisque ut sapien.
+- Phasellus purus. Proin ultricies.
+- Aliquam auctor neque. Nunc.
+- Nam nunc fringilla non, vehicula.
+- Morbi molestie, felis ut lobortis.
+- Nulla quis.
+- In.
+- Phasellus laoreet urna.
+- Lorem ipsum.
+- Phasellus.
+- Class aptent taciti sociosqu ad.
+- Sed lacinia.
+- Pellentesque dapibus diam. Duis.
+- Suspendisse est. Curabitur.
+- Fusce condimentum justo.
+- Aenean congue quis, faucibus.
+- Ut pharetra leo. Donec.
+- Fusce.
+- Donec porta.
+- Pellentesque orci.
+- Sed.
+- Quisque rutrum, wisi vulputate wisi.
+- Cum sociis.
+- Cras.
+- Sed eros. Curabitur.
+- Proin in velit wisi, tempor.
+- Quisque eu.
+- Proin.
+- Nam pellentesque sed, imperdiet aliquam.
+- Mauris euismod. Sed euismod orci.
+- Etiam.
+- Donec.
+- Fusce wisi a metus. Proin.
+- Phasellus quis.
+- Donec non imperdiet.
+- Aenean vel bibendum a, laoreet.
+- Fusce non enim. Phasellus vulputate.
+- Donec urna elit, sit.
+- Pellentesque habitant morbi.
+- Nulla ante. Curabitur elit. Donec.
+- Cum sociis natoque penatibus.
+- Maecenas eget leo at.
+- Cum sociis natoque penatibus et.
+- Vivamus lacus.
+- Integer.
+- Curae.
+- Maecenas rhoncus. Morbi.
+- Aenean posuere.
+- Duis.
+- Suspendisse a odio fermentum libero.
+- Nam enim. Fusce enim. In.
+- Maecenas.
+- Lorem ipsum primis.
+- Curabitur ac turpis semper sed.
+- Quisque condimentum. Donec sit.
+- Integer convallis non, posuere.
+- Etiam vulputate, odio.
+- Proin id lorem. Donec quis.
+- Curae, Sed nec augue.
+- Aliquam ut turpis. \ No newline at end of file
diff --git a/core/src/test/scala/com/softwaremill/sttp/testing/HttpTest.scala b/core/src/test/scala/com/softwaremill/sttp/testing/HttpTest.scala
index f1fa002..5598aa2 100644
--- a/core/src/test/scala/com/softwaremill/sttp/testing/HttpTest.scala
+++ b/core/src/test/scala/com/softwaremill/sttp/testing/HttpTest.scala
@@ -22,26 +22,23 @@ trait HttpTest[R[_]]
with OptionValues
with IntegrationPatience
with BeforeAndAfterEach
- with BeforeAndAfterAll {
-
- private val endpoint = "localhost:51823"
+ with BeforeAndAfterAll
+ with TestHttpServer {
override def afterEach() {
val file = File(outPath)
if (file.exists) file.delete()
}
- private val textFile =
- new java.io.File("test-server/src/main/resources/textfile.txt")
- private val binaryFile =
- new java.io.File("test-server/src/main/resources/binaryfile.jpg")
+ private val textFile = new java.io.File(getClass.getResource("/textfile.txt").getFile)
+ private val binaryFile = new java.io.File(getClass.getResource("/binaryfile.jpg").getFile)
private val outPath = File.newTemporaryDirectory().path
private val textWithSpecialCharacters = "Żółć!"
implicit val backend: SttpBackend[R, Nothing]
implicit val convertToFuture: ConvertToFuture[R]
- private val postEcho = sttp.post(uri"$endpoint/echo")
+ private def postEcho = sttp.post(uri"$endpoint/echo")
private val testBody = "this is the body"
private val testBodyBytes = testBody.getBytes("UTF-8")
private val expectedPostEchoResponse = "POST /echo this is the body"
@@ -172,7 +169,7 @@ trait HttpTest[R[_]]
}
"headers" - {
- val getHeaders = sttp.get(uri"$endpoint/set_headers")
+ def getHeaders = sttp.get(uri"$endpoint/set_headers")
"read response headers" in {
val response = getHeaders.response(sttpIgnore).send().force()
@@ -187,7 +184,7 @@ trait HttpTest[R[_]]
}
"errors" - {
- val getHeaders = sttp.post(uri"$endpoint/set_headers")
+ def getHeaders = sttp.post(uri"$endpoint/set_headers")
"return 405 when method not allowed" in {
val response = getHeaders.response(sttpIgnore).send().force()
@@ -236,7 +233,7 @@ trait HttpTest[R[_]]
}
"auth" - {
- val secureBasic = sttp.get(uri"$endpoint/secure_basic")
+ def secureBasic = sttp.get(uri"$endpoint/secure_basic")
"return a 401 when authorization fails" in {
val req = secureBasic
@@ -254,7 +251,7 @@ trait HttpTest[R[_]]
}
"compression" - {
- val compress = sttp.get(uri"$endpoint/compress")
+ def compress = sttp.get(uri"$endpoint/compress")
val decompressedBody = "I'm compressed!"
"decompress using the default accept encoding header" in {
@@ -374,7 +371,7 @@ trait HttpTest[R[_]]
}
"multipart" - {
- val mp = sttp.post(uri"$endpoint/multipart")
+ def mp = sttp.post(uri"$endpoint/multipart")
"send a multipart message" in {
val req = mp.multipartBody(multipart("p1", "v1"), multipart("p2", "v2"))
@@ -400,11 +397,11 @@ trait HttpTest[R[_]]
}
"redirect" - {
- val r1 = sttp.post(uri"$endpoint/redirect/r1")
- val r2 = sttp.post(uri"$endpoint/redirect/r2")
- val r3 = sttp.post(uri"$endpoint/redirect/r3")
+ def r1 = sttp.post(uri"$endpoint/redirect/r1")
+ def r2 = sttp.post(uri"$endpoint/redirect/r2")
+ def r3 = sttp.post(uri"$endpoint/redirect/r3")
val r4response = "819"
- val loop = sttp.post(uri"$endpoint/redirect/loop")
+ def loop = sttp.post(uri"$endpoint/redirect/loop")
"not redirect when redirects shouldn't be followed (temporary)" in {
val resp = r1.followRedirects(false).send().force()
@@ -499,10 +496,11 @@ trait HttpTest[R[_]]
}
"empty response" - {
- val postEmptyResponse = sttp
- .post(uri"$endpoint/empty_unauthorized_response")
- .body("{}")
- .contentType("application/json")
+ def postEmptyResponse =
+ sttp
+ .post(uri"$endpoint/empty_unauthorized_response")
+ .body("{}")
+ .contentType("application/json")
"parse an empty error response as empty string" in {
val response = postEmptyResponse.send().force()
diff --git a/core/src/test/scala/com/softwaremill/sttp/testing/TestHttpServer.scala b/core/src/test/scala/com/softwaremill/sttp/testing/TestHttpServer.scala
new file mode 100644
index 0000000..11fc692
--- /dev/null
+++ b/core/src/test/scala/com/softwaremill/sttp/testing/TestHttpServer.scala
@@ -0,0 +1,236 @@
+package com.softwaremill.sttp.testing
+
+import akka.Done
+import akka.actor.ActorSystem
+import akka.http.scaladsl.Http
+import akka.http.scaladsl.coding.{Deflate, Gzip, NoCoding}
+import akka.http.scaladsl.model._
+import akka.http.scaladsl.model.headers.CacheDirectives._
+import akka.http.scaladsl.model.headers._
+import akka.http.scaladsl.server.Directives.{entity, path, _}
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.server.directives.Credentials
+import akka.stream.ActorMaterializer
+import akka.util.ByteString
+import scala.concurrent.duration._
+import scala.concurrent.{Await, Future}
+
+import org.scalatest.BeforeAndAfterAll
+import org.scalatest.Suite
+
+trait TestHttpServer extends BeforeAndAfterAll { this: Suite =>
+
+ private val server = new HttpServer(0)
+ protected var endpoint = "localhost:51823"
+
+ override protected def beforeAll(): Unit = {
+ import scala.concurrent.ExecutionContext.Implicits.global
+
+ super.beforeAll()
+ Await.result(
+ server.start().map { binding =>
+ endpoint = s"localhost:${binding.localAddress.getPort}"
+ },
+ 10.seconds
+ )
+ }
+
+ override protected def afterAll(): Unit = {
+ server.close()
+ super.afterAll()
+ }
+
+}
+
+object HttpServer {
+
+ def main(args: Array[String]): Unit = {
+ val port = args.headOption.map(_.toInt).getOrElse(51823)
+
+ Await.result(new HttpServer(port).start(), 10.seconds)
+ }
+}
+
+private class HttpServer(port: Int) extends AutoCloseable {
+
+ import scala.concurrent.ExecutionContext.Implicits.global
+
+ private var server: Option[Future[Http.ServerBinding]] = None
+
+ private implicit val actorSystem: ActorSystem = ActorSystem("sttp-test-server")
+ private implicit val materializer: ActorMaterializer = ActorMaterializer()
+
+ private def paramsToString(m: Map[String, String]): String =
+ m.toList.sortBy(_._1).map(p => s"${p._1}=${p._2}").mkString(" ")
+
+ private val textFile = new java.io.File(getClass.getResource("/textfile.txt").getFile)
+ private val binaryFile = new java.io.File(getClass.getResource("/binaryfile.jpg").getFile)
+ private val textWithSpecialCharacters = "Żółć!"
+
+ val serverRoutes: Route =
+ pathPrefix("echo") {
+ pathPrefix("form_params") {
+ formFieldMap { params =>
+ path("as_string") {
+ complete(paramsToString(params))
+ } ~
+ path("as_params") {
+ complete(FormData(params))
+ }
+ }
+ } ~ get {
+ parameterMap { params =>
+ complete(List("GET", "/echo", paramsToString(params))
+ .filter(_.nonEmpty)
+ .mkString(" "))
+ }
+ } ~
+ post {
+ parameterMap { params =>
+ entity(as[String]) { body: String =>
+ complete(List("POST", "/echo", paramsToString(params), body)
+ .filter(_.nonEmpty)
+ .mkString(" "))
+ }
+ }
+ }
+ } ~ pathPrefix("streaming") {
+ path("echo") {
+ post {
+ parameterMap { _ =>
+ entity(as[String]) { body: String =>
+ complete(body)
+ }
+ }
+ }
+ }
+ } ~ path("set_headers") {
+ get {
+ respondWithHeader(`Cache-Control`(`max-age`(1000L))) {
+ respondWithHeader(`Cache-Control`(`no-cache`)) {
+ complete("ok")
+ }
+ }
+ }
+ } ~ pathPrefix("set_cookies") {
+ path("with_expires") {
+ setCookie(HttpCookie("c", "v", expires = Some(DateTime(1997, 12, 8, 12, 49, 12)))) {
+ complete("ok")
+ }
+ } ~ get {
+ setCookie(
+ HttpCookie(
+ "cookie1",
+ "value1",
+ secure = true,
+ httpOnly = true,
+ maxAge = Some(123L)
+ )
+ ) {
+ setCookie(HttpCookie("cookie2", "value2")) {
+ setCookie(
+ HttpCookie(
+ "cookie3",
+ "",
+ domain = Some("xyz"),
+ path = Some("a/b/c")
+ )
+ ) {
+ complete("ok")
+ }
+ }
+ }
+ }
+ } ~ path("secure_basic") {
+ authenticateBasic("test realm", {
+ case c @ Credentials.Provided(un) if un == "adam" && c.verify("1234") =>
+ Some(un)
+ case _ => None
+ }) { userName =>
+ complete(s"Hello, $userName!")
+ }
+ } ~ path("compress") {
+ encodeResponseWith(Gzip, Deflate, NoCoding) {
+ complete("I'm compressed!")
+ }
+ } ~ pathPrefix("download") {
+ path("binary") {
+ getFromFile(binaryFile)
+ } ~ path("text") {
+ getFromFile(textFile)
+ }
+ } ~ pathPrefix("multipart") {
+ entity(as[akka.http.scaladsl.model.Multipart.FormData]) { fd =>
+ complete {
+ fd.parts
+ .mapAsync(1) { p =>
+ val fv = p.entity.dataBytes.runFold(ByteString())(_ ++ _)
+ fv.map(_.utf8String)
+ .map(v => p.name + "=" + v + p.filename.fold("")(fn => s" ($fn)"))
+ }
+ .runFold(Vector.empty[String])(_ :+ _)
+ .map(v => v.mkString(", "))
+ }
+ }
+ } ~ pathPrefix("redirect") {
+ path("r1") {
+ redirect("/redirect/r2", StatusCodes.TemporaryRedirect)
+ } ~
+ path("r2") {
+ redirect("/redirect/r3", StatusCodes.PermanentRedirect)
+ } ~
+ path("r3") {
+ redirect("/redirect/r4", StatusCodes.Found)
+ } ~
+ path("r4") {
+ complete("819")
+ } ~
+ path("loop") {
+ redirect("/redirect/loop", StatusCodes.Found)
+ }
+ } ~ pathPrefix("timeout") {
+ complete {
+ akka.pattern.after(1.second, using = actorSystem.scheduler)(
+ Future.successful("Done")
+ )
+ }
+ } ~ path("empty_unauthorized_response") {
+ post {
+ import akka.http.scaladsl.model._
+ complete(
+ HttpResponse(
+ status = StatusCodes.Unauthorized,
+ headers = Nil,
+ entity = HttpEntity.Empty,
+ protocol = HttpProtocols.`HTTP/1.1`
+ ))
+ }
+ } ~ path("respond_with_iso_8859_2") {
+ get { ctx =>
+ val entity =
+ HttpEntity(MediaTypes.`text/plain`.withCharset(HttpCharset.custom("ISO-8859-2")), textWithSpecialCharacters)
+ ctx.complete(HttpResponse(200, entity = entity))
+ }
+ }
+
+ def start(): Future[Http.ServerBinding] = {
+ unbindServer().flatMap { _ =>
+ val server = Http().bindAndHandle(serverRoutes, "localhost", port)
+ this.server = Some(server)
+ server
+ }
+ }
+
+ def close(): Unit = {
+ val unbind = unbindServer()
+ unbind.onComplete(_ => actorSystem.terminate())
+ Await.result(
+ unbind,
+ 10.seconds
+ )
+ }
+
+ private def unbindServer(): Future[Done] = {
+ server.map(_.flatMap(_.unbind())).getOrElse(Future.successful(Done))
+ }
+}
diff --git a/core/src/test/scala/com/softwaremill/sttp/testing/streaming/StreamingTest.scala b/core/src/test/scala/com/softwaremill/sttp/testing/streaming/StreamingTest.scala
index 27a6eda..40aaf82 100644
--- a/core/src/test/scala/com/softwaremill/sttp/testing/streaming/StreamingTest.scala
+++ b/core/src/test/scala/com/softwaremill/sttp/testing/streaming/StreamingTest.scala
@@ -6,10 +6,15 @@ import org.scalatest.{AsyncFreeSpec, BeforeAndAfterAll, Matchers}
import scala.language.higherKinds
import com.softwaremill.sttp.testing.ConvertToFuture
+import com.softwaremill.sttp.testing.TestHttpServer
-trait StreamingTest[R[_], S] extends AsyncFreeSpec with Matchers with BeforeAndAfterAll with ForceWrapped {
+trait StreamingTest[R[_], S]
+ extends AsyncFreeSpec
+ with Matchers
+ with ForceWrapped
+ with BeforeAndAfterAll
+ with TestHttpServer {
- private val endpoint = "localhost:51823"
private val body = "streaming test"
implicit def backend: SttpBackend[R, S]