Skip to content

Commit 192e73d

Browse files
committed
Endpoints integration tests
1 parent 47a6024 commit 192e73d

File tree

3 files changed

+157
-11
lines changed

3 files changed

+157
-11
lines changed

src/main/scala/services.scala

+8-6
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ import scala.concurrent.duration._
1111
import scalaz.concurrent.Task
1212
import scalaz._
1313

14+
1415
object services {
1516

1617
import codecs._
1718
import io.circe.generic.auto._
19+
import EvalResponse.messages._
1820

1921
private val logger = getLogger
2022

@@ -33,12 +35,12 @@ object services {
3335
) flatMap { result =>
3436
val response = result match {
3537
case EvalSuccess(cis, result, out) =>
36-
EvalResponse("ok", Option(result.toString), Option(result.asInstanceOf[AnyRef].getClass.getName), cis)
37-
case Timeout(_) => EvalResponse("Timeout", None, None, Map.empty)
38-
case UnresolvedDependency(msg) => EvalResponse(s"Unresolved Dependency : $msg", None, None, Map.empty)
39-
case EvalRuntimeError(cis, _) => EvalResponse("Runtime error", None, None, cis)
40-
case CompilationError(cis) => EvalResponse("Compilation Error", None, None, cis)
41-
case GeneralError(err) => EvalResponse("Unforeseen Exception", None, None, Map.empty)
38+
EvalResponse(`ok`, Option(result.toString), Option(result.asInstanceOf[AnyRef].getClass.getName), cis)
39+
case Timeout(_) => EvalResponse(`Timeout Exceded`, None, None, Map.empty)
40+
case UnresolvedDependency(msg) => EvalResponse(`Unresolved Dependency` + " : " + msg, None, None, Map.empty)
41+
case EvalRuntimeError(cis, _) => EvalResponse(`Runtime Error`, None, None, cis)
42+
case CompilationError(cis) => EvalResponse(`Compilation Error`, None, None, cis)
43+
case GeneralError(err) => EvalResponse(`Unforeseen Exception`, None, None, Map.empty)
4244
}
4345
Ok(response.asJson)
4446
}

src/main/scala/types.scala

+20-5
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,28 @@ final case class Dependency(
4747
version: String)
4848

4949
final case class EvalRequest(
50-
resolvers: List[String],
51-
dependencies: List[Dependency],
50+
resolvers: List[String] = Nil,
51+
dependencies: List[Dependency] = Nil,
5252
code: String)
5353

5454
final case class EvalResponse(
5555
msg: String,
56-
value: Option[String],
57-
valueType: Option[String],
58-
compilationInfos: CI)
56+
value: Option[String] = None,
57+
valueType: Option[String] = None,
58+
compilationInfos: CI = Map.empty)
59+
60+
object EvalResponse {
61+
62+
object messages {
63+
64+
val `ok` = "Ok"
65+
val `Timeout Exceded` = "Timeout"
66+
val `Unresolved Dependency` = "Unresolved Dependency"
67+
val `Runtime Error` = "Runtime Error"
68+
val `Compilation Error` = "Compilation Error"
69+
val `Unforeseen Exception` = "Unforeseen Exception"
70+
71+
}
72+
73+
}
5974

src/test/scala/EvalEndpointSpec.scala

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* scala-exercises-evaluator
3+
* Copyright (C) 2015-2016 47 Degrees, LLC. <http://www.47deg.com>
4+
*/
5+
package org.scalaexercises.evaluator
6+
7+
import org.scalatest._
8+
import org.http4s._, org.http4s.dsl._, org.http4s.server._
9+
10+
import io.circe.syntax._
11+
import io.circe.generic.auto._
12+
import scalaz.stream.Process.emit
13+
import java.nio.charset.StandardCharsets
14+
import scodec.bits.ByteVector
15+
16+
import org.http4s.{Status => HttpStatus}
17+
18+
class EvalEndpointSpec extends FunSpec with Matchers {
19+
20+
import services._
21+
import codecs._
22+
import EvalResponse.messages._
23+
24+
val sonatypeReleases = "https://oss.sonatype.org/content/repositories/releases/" :: Nil
25+
26+
def serve(evalRequest: EvalRequest) =
27+
service.run(Request(
28+
POST,
29+
Uri(path = "/eval"),
30+
body = emit(
31+
ByteVector.view(
32+
evalRequest.asJson.noSpaces.getBytes(StandardCharsets.UTF_8)
33+
)
34+
)
35+
)).run
36+
37+
def verifyEvalResponse(
38+
response: Response,
39+
expectedStatus: HttpStatus,
40+
expectedValue: Option[String] = None,
41+
expectedMessage: String
42+
) = {
43+
44+
response.status should be(expectedStatus)
45+
val evalResponse = response.as[EvalResponse].run
46+
evalResponse.value should be(expectedValue)
47+
evalResponse.msg should be(expectedMessage)
48+
}
49+
50+
describe("evaluation") {
51+
it("can evaluate simple expressions") {
52+
verifyEvalResponse(
53+
response = serve(EvalRequest(code = "{ 41 + 1 }")),
54+
expectedStatus = HttpStatus.Ok,
55+
expectedValue = Some("42"),
56+
expectedMessage = `ok`
57+
)
58+
}
59+
60+
it("fails with a timeout when takes longer than the configured timeout") {
61+
verifyEvalResponse(
62+
response = serve(EvalRequest(code = "{ while(true) {}; 123 }")),
63+
expectedStatus = HttpStatus.Ok,
64+
expectedValue = None,
65+
expectedMessage = `Timeout Exceded`
66+
)
67+
}
68+
69+
it("can load dependencies for an evaluation") {
70+
verifyEvalResponse(
71+
response = serve(EvalRequest(
72+
code = "{import cats._; Eval.now(42).value}",
73+
resolvers = sonatypeReleases,
74+
dependencies = Dependency("org.typelevel", "cats_2.11", "0.6.0") :: Nil
75+
)),
76+
expectedStatus = HttpStatus.Ok,
77+
expectedValue = Some("42"),
78+
expectedMessage = `ok`
79+
)
80+
}
81+
82+
it("can load different versions of a dependency across evaluations") {
83+
val code = "{import cats._; Eval.now(42).value}"
84+
val resolvers = sonatypeReleases
85+
86+
List("0.6.0", "0.4.1") foreach { version =>
87+
verifyEvalResponse(
88+
response = serve(EvalRequest(
89+
code = code,
90+
resolvers = resolvers,
91+
dependencies = Dependency("org.typelevel", "cats_2.11", version) :: Nil
92+
)),
93+
expectedStatus = HttpStatus.Ok,
94+
expectedValue = Some("42"),
95+
expectedMessage = `ok`
96+
)
97+
}
98+
99+
}
100+
101+
it("can run code from the exercises content") {
102+
verifyEvalResponse(
103+
response = serve(EvalRequest(
104+
code = "{import stdlib._; Asserts.scalaTestAsserts(true)}",
105+
resolvers = sonatypeReleases,
106+
dependencies = Dependency("org.scala-exercises", "exercises-stdlib_2.11", "0.2.0") :: Nil
107+
)),
108+
expectedStatus = HttpStatus.Ok,
109+
expectedValue = Some("()"),
110+
expectedMessage = `ok`
111+
)
112+
}
113+
114+
it("captures exceptions when running the exercises content") {
115+
verifyEvalResponse(
116+
response = serve(EvalRequest(
117+
code = "{import stdlib._; Asserts.scalaTestAsserts(false)}",
118+
resolvers = sonatypeReleases,
119+
dependencies = Dependency("org.scala-exercises", "exercises-stdlib_2.11", "0.2.0") :: Nil
120+
)),
121+
expectedStatus = HttpStatus.Ok,
122+
expectedValue = None,
123+
expectedMessage = `Runtime Error`
124+
)
125+
}
126+
127+
}
128+
}
129+

0 commit comments

Comments
 (0)