|
@@ -1,172 +0,0 @@
|
|
|
-package com.hexagonkt
|
|
|
-
|
|
|
-import com.hexagonkt.serialization.parse
|
|
|
-import com.hexagonkt.http.client.Client
|
|
|
-import com.hexagonkt.serialization.Json
|
|
|
-import com.hexagonkt.http.Method.GET
|
|
|
-import com.hexagonkt.http.client.Response
|
|
|
-import com.hexagonkt.http.client.ahc.AhcAdapter
|
|
|
-import com.hexagonkt.http.server.jetty.JettyServletAdapter
|
|
|
-import com.hexagonkt.serialization.parseObjects
|
|
|
-import io.kotest.assertions.throwables.shouldThrow
|
|
|
-import io.kotest.core.spec.style.StringSpec
|
|
|
-import java.lang.IllegalStateException
|
|
|
-import java.lang.System.setProperty
|
|
|
-
|
|
|
-class BenchmarkJettyMongoDbTest : BenchmarkTestBase("jetty", "mongodb")
|
|
|
-
|
|
|
-class BenchmarkJettyPostgreSqlTest : BenchmarkTestBase("jetty", "postgresql")
|
|
|
-
|
|
|
-abstract class BenchmarkTestBase(
|
|
|
- private val webEngine: String,
|
|
|
- private val databaseEngine: String,
|
|
|
- private val templateEngine: String = "pebble"
|
|
|
-): StringSpec({
|
|
|
-
|
|
|
- val endpoint = System.getProperty("verify.endpoint")
|
|
|
- val users = (System.getProperty("users") ?: "8").toInt()
|
|
|
- val count = (System.getProperty("count") ?: "2").toInt() * users
|
|
|
-
|
|
|
- lateinit var client: Client
|
|
|
-
|
|
|
- fun checkResponse(res: Response, contentType: String) {
|
|
|
- assert(res.headers["Date"] != null)
|
|
|
- assert(res.headers["Server"] != null)
|
|
|
- assert(res.headers["Transfer-Encoding"] != null)
|
|
|
- assert(res.headers["Content-Type"]?.first() == contentType)
|
|
|
- }
|
|
|
-
|
|
|
- fun checkDbRequest(path: String, itemsCount: Int) {
|
|
|
- val response = client.get(path)
|
|
|
- val content = response.body
|
|
|
-
|
|
|
- checkResponse(response, Json.contentType)
|
|
|
-
|
|
|
- val resultsList = content?.parse(List::class) ?: error("")
|
|
|
- assert(itemsCount == resultsList.size)
|
|
|
-
|
|
|
- (1..itemsCount).forEach {
|
|
|
- val r = resultsList[it - 1] as Map<*, *>
|
|
|
- assert(r.containsKey(World::id.name) && r.containsKey(World::randomNumber.name))
|
|
|
- assert(!r.containsKey(World::_id.name))
|
|
|
- assert((r[World::id.name] as Int) in 1..10000)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- beforeSpec {
|
|
|
- setProperty("WEBENGINE", webEngine)
|
|
|
- client = if (endpoint == null) {
|
|
|
- main()
|
|
|
- Client(AhcAdapter(), "http://localhost:${benchmarkServer.runtimePort}")
|
|
|
- }
|
|
|
- else {
|
|
|
- Client(AhcAdapter(), endpoint)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- afterSpec {
|
|
|
- benchmarkStores[databaseEngine]?.close()
|
|
|
- benchmarkServer.stop()
|
|
|
- }
|
|
|
-
|
|
|
- "Empty server code creates a Jetty Servlet Adapter" {
|
|
|
- System.clearProperty("WEBENGINE")
|
|
|
- createEngine()
|
|
|
- assert(engine is JettyServletAdapter)
|
|
|
- }
|
|
|
-
|
|
|
- "Invalid server code throws an exception" {
|
|
|
- shouldThrow<IllegalStateException> {
|
|
|
- setProperty("WEBENGINE", "invalid")
|
|
|
- createEngine()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- "Web" {
|
|
|
- val web = Web()
|
|
|
-
|
|
|
- val webRoutes = web.serverRouter.requestHandlers
|
|
|
- .map { it.route.methods.first() to it.route.path.pattern }
|
|
|
-
|
|
|
- val benchmarkRoutes = listOf(
|
|
|
- GET to "/plaintext",
|
|
|
- GET to "/json",
|
|
|
- GET to "/$databaseEngine/$templateEngine/fortunes",
|
|
|
- GET to "/$databaseEngine/db",
|
|
|
- GET to "/$databaseEngine/query",
|
|
|
- GET to "/$databaseEngine/update"
|
|
|
- )
|
|
|
-
|
|
|
- assert(webRoutes.containsAll(benchmarkRoutes))
|
|
|
- }
|
|
|
-
|
|
|
- "JSON".config(invocations = count, threads = users) {
|
|
|
- val response = client.get("/json")
|
|
|
- val content = response.body
|
|
|
-
|
|
|
- checkResponse(response, Json.contentType)
|
|
|
- assert("Hello, World!" == content?.parse<Message>()?.message)
|
|
|
- }
|
|
|
-
|
|
|
- "Plaintext".config(invocations = count, threads = users) {
|
|
|
- val response = client.get("/plaintext")
|
|
|
- val content = response.body
|
|
|
-
|
|
|
- checkResponse(response, "text/plain")
|
|
|
- assert("Hello, World!" == content)
|
|
|
- }
|
|
|
-
|
|
|
- "Fortunes".config(invocations = count, threads = users) {
|
|
|
- val response = client.get("/$databaseEngine/$templateEngine/fortunes")
|
|
|
- val content = response.body ?: error("body is required")
|
|
|
-
|
|
|
- checkResponse(response, "text/html;charset=utf-8")
|
|
|
- assert(content.contains("<td><script>alert("This should not be"))
|
|
|
- assert(content.contains(" displayed in a browser alert box.");</script></td>"))
|
|
|
- assert(content.contains("<td>フレームワークのベンチマーク</td>"))
|
|
|
- }
|
|
|
-
|
|
|
- "No query parameter".config(invocations = count, threads = users) {
|
|
|
- val response = client.get("/$databaseEngine/db")
|
|
|
- val body = response.body ?: error("body is required")
|
|
|
-
|
|
|
- checkResponse(response, Json.contentType)
|
|
|
- val bodyMap = body.parse(Map::class)
|
|
|
- assert(bodyMap.containsKey(World::id.name))
|
|
|
- assert(bodyMap.containsKey(World::randomNumber.name))
|
|
|
- }
|
|
|
-
|
|
|
- "No updates parameter".config(invocations = count, threads = users) {
|
|
|
- val response = client.get("/$databaseEngine/update")
|
|
|
- val body = response.body ?: error("body is required")
|
|
|
-
|
|
|
- checkResponse(response, Json.contentType)
|
|
|
- val bodyMap = body.parseObjects(Map::class).first()
|
|
|
- assert(bodyMap.containsKey(World::id.name))
|
|
|
- assert(bodyMap.containsKey(World::randomNumber.name))
|
|
|
- }
|
|
|
-
|
|
|
- fun testDb(test: String, path: String, itemsCount: Int) {
|
|
|
- test.config(invocations = count, threads = users) {
|
|
|
- checkDbRequest("/$databaseEngine/$path", itemsCount)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- testDb("Empty query parameter", "query?queries", 1)
|
|
|
- testDb("Text query parameter", "query?queries=text", 1)
|
|
|
- testDb("Zero queries", "query?queries=0", 1)
|
|
|
- testDb("One thousand queries", "query?queries=1000", 500)
|
|
|
- testDb("One query", "query?queries=1", 1)
|
|
|
- testDb("Ten queries", "query?queries=10", 10)
|
|
|
- testDb("One hundred queries", "query?queries=100", 100)
|
|
|
- testDb("Five hundred queries", "query?queries=500", 500)
|
|
|
-
|
|
|
- testDb("Empty updates parameter", "update?queries", 1)
|
|
|
- testDb("Text updates parameter", "update?queries=text", 1)
|
|
|
- testDb("Zero updates", "update?queries=0", 1)
|
|
|
- testDb("One thousand updates", "update?queries=1000", 500)
|
|
|
- testDb("One update", "update?queries=1", 1)
|
|
|
- testDb("Ten updates", "update?queries=10", 10)
|
|
|
- testDb("One hundred updates", "update?queries=100", 100)
|
|
|
- testDb("Five hundred updates", "update?queries=500", 500)
|
|
|
-})
|