summaryrefslogtreecommitdiff
path: root/cask/test
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-08-08 15:53:37 +0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-08-08 18:24:18 +0800
commitd85fd093539bdd7d8d432b058c2e2225eaa1ee2b (patch)
tree1b10e0cdcea08a51255152e259e446a75ec57ead /cask/test
parenta5320694193fd86b639c53a91fa24fb7f8ea914e (diff)
downloadcask-d85fd093539bdd7d8d432b058c2e2225eaa1ee2b.tar.gz
cask-d85fd093539bdd7d8d432b058c2e2225eaa1ee2b.tar.bz2
cask-d85fd093539bdd7d8d432b058c2e2225eaa1ee2b.zip
Properly roll back transactions when endpoints fail in TodoMvcDb
Diffstat (limited to 'cask/test')
-rw-r--r--cask/test/src/test/cask/Decorated.scala9
-rw-r--r--cask/test/src/test/cask/ExampleTests.scala86
-rw-r--r--cask/test/src/test/cask/FailureTests.scala3
-rw-r--r--cask/test/src/test/cask/MinimalApplication2.scala16
-rw-r--r--cask/test/src/test/cask/TodoMvcDb.scala42
5 files changed, 93 insertions, 63 deletions
diff --git a/cask/test/src/test/cask/Decorated.scala b/cask/test/src/test/cask/Decorated.scala
index 9fac78a..d7cb6b8 100644
--- a/cask/test/src/test/cask/Decorated.scala
+++ b/cask/test/src/test/cask/Decorated.scala
@@ -1,21 +1,16 @@
package test.cask
-import cask.internal.Router
-import cask.model.{ParamContext, Response}
-
object Decorated extends cask.MainRoutes{
class User{
override def toString = "[haoyi]"
}
class loggedIn extends cask.Decorator {
- def wrapMethodOutput(ctx: ParamContext,
- delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = {
+ def wrapFunction(ctx: cask.ParamContext, delegate: Delegate): Returned = {
delegate(Map("user" -> new User()))
}
}
class withExtra extends cask.Decorator {
- def wrapMethodOutput(ctx: ParamContext,
- delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = {
+ def wrapFunction(ctx: cask.ParamContext, delegate: Delegate): Returned = {
delegate(Map("extra" -> 31337))
}
}
diff --git a/cask/test/src/test/cask/ExampleTests.scala b/cask/test/src/test/cask/ExampleTests.scala
index 6858051..36e0387 100644
--- a/cask/test/src/test/cask/ExampleTests.scala
+++ b/cask/test/src/test/cask/ExampleTests.scala
@@ -4,7 +4,7 @@ import io.undertow.server.handlers.BlockingHandler
import utest._
object ExampleTests extends TestSuite{
- def test[T](example: cask.main.MainRoutes)(f: String => T): T = {
+ def test[T](example: cask.main.BaseMain)(f: String => T): T = {
val server = Undertow.builder
.addHttpListener(8080, "localhost")
.setHandler(new BlockingHandler(example.defaultHandler))
@@ -23,25 +23,37 @@ object ExampleTests extends TestSuite{
success.text() ==> "Hello World!"
success.statusCode ==> 200
- requests.get(host + "/doesnt-exist").statusCode ==> 404
+ requests.get(s"$host/doesnt-exist").statusCode ==> 404
- requests.post(host + "/do-thing", data = "hello").text() ==> "olleh"
+ requests.post(s"$host/do-thing", data = "hello").text() ==> "olleh"
- requests.get(host + "/do-thing").statusCode ==> 404
+ requests.get(s"$host/do-thing").statusCode ==> 404
+ }
+ 'MinimalApplication2 - test(MinimalMain){ host =>
+ val success = requests.get(host)
+
+ success.text() ==> "Hello World!"
+ success.statusCode ==> 200
+
+ requests.get(s"$host/doesnt-exist").statusCode ==> 404
+
+ requests.post(s"$host/do-thing", data = "hello").text() ==> "olleh"
+
+ requests.get(s"$host/do-thing").statusCode ==> 404
}
'VariableRoutes - test(VariableRoutes){ host =>
val noIndexPage = requests.get(host)
noIndexPage.statusCode ==> 404
- requests.get(host + "/user/lihaoyi").text() ==> "User lihaoyi"
+ requests.get(s"$host/user/lihaoyi").text() ==> "User lihaoyi"
- requests.get(host + "/user").statusCode ==> 404
+ requests.get(s"$host/user").statusCode ==> 404
- requests.get(host + "/post/123?param=xyz&param=abc").text() ==>
+ requests.get(s"$host/post/123?param=xyz&param=abc").text() ==>
"Post 123 ArrayBuffer(xyz, abc)"
- requests.get(host + "/post/123").text() ==>
+ requests.get(s"$host/post/123").text() ==>
"""Missing argument: (param: Seq[String])
|
|Arguments provided did not match expected signature:
@@ -52,33 +64,33 @@ object ExampleTests extends TestSuite{
|
|""".stripMargin
- requests.get(host + "/path/one/two/three").text() ==>
+ requests.get(s"$host/path/one/two/three").text() ==>
"Subpath List(one, two, three)"
}
'StaticFiles - test(StaticFiles){ host =>
- requests.get(host + "/static/example.txt").text() ==>
+ requests.get(s"$host/static/example.txt").text() ==>
"the quick brown fox jumps over the lazy dog"
}
'RedirectAbort - test(RedirectAbort){ host =>
- val resp = requests.get(host + "/")
+ val resp = requests.get(s"$host/")
resp.statusCode ==> 401
resp.history.get.statusCode ==> 301
}
'FormJsonPost - test(FormJsonPost){ host =>
- requests.post(host + "/json", data = """{"value1": true, "value2": [3]}""").text() ==>
+ requests.post(s"$host/json", data = """{"value1": true, "value2": [3]}""").text() ==>
"OK true Vector(3)"
requests.post(
- host + "/form",
+ s"$host/form",
data = Seq("value1" -> "hello", "value2" -> "1", "value2" -> "2")
).text() ==>
"OK FormValue(hello,null) List(1, 2)"
val resp = requests.post(
- host + "/upload",
+ s"$host/upload",
data = requests.MultiPart(
requests.MultiItem("image", "...", "my-best-image.txt")
)
@@ -86,61 +98,61 @@ object ExampleTests extends TestSuite{
resp.text() ==> "my-best-image.txt"
}
'Decorated - test(Decorated){ host =>
- requests.get(host + "/hello/woo").text() ==> "woo31337"
- requests.get(host + "/internal/boo").text() ==> "boo[haoyi]"
- requests.get(host + "/internal-extra/goo").text() ==> "goo[haoyi]31337"
+ requests.get(s"$host/hello/woo").text() ==> "woo31337"
+ requests.get(s"$host/internal/boo").text() ==> "boo[haoyi]"
+ requests.get(s"$host/internal-extra/goo").text() ==> "goo[haoyi]31337"
}
'TodoMvcApi - test(TodoMvcApi){ host =>
- requests.get(host + "/list/all").text() ==>
+ requests.get(s"$host/list/all").text() ==>
"""[{"checked":true,"text":"Get started with Cask"},{"checked":false,"text":"Profit!"}]"""
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[{"checked":false,"text":"Profit!"}]"""
- requests.get(host + "/list/completed").text() ==>
+ requests.get(s"$host/list/completed").text() ==>
"""[{"checked":true,"text":"Get started with Cask"}]"""
- requests.post(host + "/toggle/1")
+ requests.post(s"$host/toggle/1")
- requests.get(host + "/list/all").text() ==>
+ requests.get(s"$host/list/all").text() ==>
"""[{"checked":true,"text":"Get started with Cask"},{"checked":true,"text":"Profit!"}]"""
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[]"""
- requests.post(host + "/add", data = "new Task")
+ requests.post(s"$host/add", data = "new Task")
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[{"checked":false,"text":"new Task"}]"""
- requests.post(host + "/delete/0")
+ requests.post(s"$host/delete/0")
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[]"""
}
'TodoMvcDb - test(TodoMvcDb){ host =>
- requests.get(host + "/list/all").text() ==>
+ requests.get(s"$host/list/all").text() ==>
"""[{"id":1,"checked":true,"text":"Get started with Cask"},{"id":2,"checked":false,"text":"Profit!"}]"""
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[{"id":2,"checked":false,"text":"Profit!"}]"""
- requests.get(host + "/list/completed").text() ==>
+ requests.get(s"$host/list/completed").text() ==>
"""[{"id":1,"checked":true,"text":"Get started with Cask"}]"""
- requests.post(host + "/toggle/2")
+ requests.post(s"$host/toggle/2")
- requests.get(host + "/list/all").text() ==>
+ requests.get(s"$host/list/all").text() ==>
"""[{"id":1,"checked":true,"text":"Get started with Cask"},{"id":2,"checked":true,"text":"Profit!"}]"""
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[]"""
- requests.post(host + "/add", data = "new Task")
+ requests.post(s"$host/add", data = "new Task")
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[{"id":3,"checked":false,"text":"new Task"}]"""
- requests.post(host + "/delete/3")
+ requests.post(s"$host/delete/3")
- requests.get(host + "/list/active").text() ==>
+ requests.get(s"$host/list/active").text() ==>
"""[]"""
}
}
diff --git a/cask/test/src/test/cask/FailureTests.scala b/cask/test/src/test/cask/FailureTests.scala
index de3b438..9e28c0b 100644
--- a/cask/test/src/test/cask/FailureTests.scala
+++ b/cask/test/src/test/cask/FailureTests.scala
@@ -6,8 +6,7 @@ import utest._
object FailureTests extends TestSuite {
class myDecorator extends cask.Decorator {
- def wrapMethodOutput(ctx: ParamContext,
- delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = {
+ def wrapFunction(ctx: ParamContext, delegate: Delegate): Returned = {
delegate(Map("extra" -> 31337))
}
}
diff --git a/cask/test/src/test/cask/MinimalApplication2.scala b/cask/test/src/test/cask/MinimalApplication2.scala
new file mode 100644
index 0000000..924b00f
--- /dev/null
+++ b/cask/test/src/test/cask/MinimalApplication2.scala
@@ -0,0 +1,16 @@
+package test.cask
+
+object MinimalRoutes extends cask.Routes{
+ @cask.get("/")
+ def hello() = {
+ "Hello World!"
+ }
+
+ @cask.post("/do-thing")
+ def doThing(request: cask.Request) = {
+ new String(request.data.readAllBytes()).reverse
+ }
+
+ initialize()
+}
+object MinimalMain extends cask.Main(MinimalRoutes) \ No newline at end of file
diff --git a/cask/test/src/test/cask/TodoMvcDb.scala b/cask/test/src/test/cask/TodoMvcDb.scala
index c6f8191..b352d1a 100644
--- a/cask/test/src/test/cask/TodoMvcDb.scala
+++ b/cask/test/src/test/cask/TodoMvcDb.scala
@@ -1,32 +1,39 @@
package test.cask
+
import cask.internal.Router
-import cask.model.{ParamContext, Response}
import com.typesafe.config.ConfigFactory
-import io.getquill._
+import io.getquill.{SqliteJdbcContext, SnakeCase}
object TodoMvcDb extends cask.MainRoutes{
- case class Todo(id: Int, checked: Boolean, text: String)
- object Todo{
- implicit def todoRW = upickle.default.macroRW[Todo]
- }
+ val tmpDb = java.nio.file.Files.createTempDirectory("todo-cask-sqlite")
+
object ctx extends SqliteJdbcContext(
SnakeCase,
ConfigFactory.parseString(
s"""{"driverClassName":"org.sqlite.JDBC","jdbcUrl":"jdbc:sqlite:$tmpDb/file.db"}"""
)
)
- val tmpDb = java.nio.file.Files.createTempDirectory("todo-cask-sqlite")
-
- import ctx._
class transactional extends cask.Decorator{
- def wrapMethodOutput(pctx: ParamContext,
- delegate: Map[String, Input] => Router.Result[Response]): Router.Result[Response] = {
- ctx.transaction(delegate(Map("ctx" -> ctx)))
+ class TransactionFailed(val value: Router.Result.Error) extends Exception
+ def wrapFunction(pctx: cask.ParamContext, delegate: Delegate): Returned = {
+ try ctx.transaction(
+ delegate(Map()) match{
+ case Router.Result.Success(t) => Router.Result.Success(t)
+ case e: Router.Result.Error => throw new TransactionFailed(e)
+ }
+ )
+ catch{case e: TransactionFailed => e.value}
+
}
}
+ case class Todo(id: Int, checked: Boolean, text: String)
+ object Todo{
+ implicit def todoRW = upickle.default.macroRW[Todo]
+ }
+
ctx.executeAction(
"""CREATE TABLE todo (
| id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -42,9 +49,11 @@ object TodoMvcDb extends cask.MainRoutes{
|""".stripMargin
)
+ import ctx._
+
@transactional
@cask.get("/list/:state")
- def list(state: String)(ctx: SqliteJdbcContext[_]) = {
+ def list(state: String) = {
val filteredTodos = state match{
case "all" => run(query[Todo])
case "active" => run(query[Todo].filter(!_.checked))
@@ -55,22 +64,21 @@ object TodoMvcDb extends cask.MainRoutes{
@transactional
@cask.post("/add")
- def add(request: cask.Request)(ctx: SqliteJdbcContext[_]) = {
+ def add(request: cask.Request) = {
val body = new String(request.data.readAllBytes())
run(query[Todo].insert(_.checked -> lift(false), _.text -> lift(body)).returning(_.id))
}
@transactional
@cask.post("/toggle/:index")
- def toggle(index: Int)(ctx: SqliteJdbcContext[_]) = {
+ def toggle(index: Int) = {
run(query[Todo].filter(_.id == lift(index)).update(p => p.checked -> !p.checked))
}
@transactional
@cask.post("/delete/:index")
- def delete(index: Int)(ctx: SqliteJdbcContext[_]) = {
+ def delete(index: Int) = {
run(query[Todo].filter(_.id == lift(index)).delete)
-
}
initialize()