NOISSUE - Update load tests (#287)
This commit is contained in:
parent
38a107919a
commit
9c6904d9b3
|
@ -4,9 +4,9 @@ Testing environment to be determined.
|
|||
|
||||
### Message publishing
|
||||
|
||||
In this scenario, large number of requests are sent to HTTP adapter service
|
||||
every second. This test checks how much time HTTP adapter took to response to
|
||||
each request.
|
||||
In this scenario, large number of requests are sent to HTTP adapter service
|
||||
every second. This test checks how much time HTTP adapter needs to respond
|
||||
to each request.
|
||||
|
||||
#### Results
|
||||
|
||||
|
@ -14,10 +14,10 @@ TBD
|
|||
|
||||
### Create and get client
|
||||
|
||||
In this scenario, large number of requests are sent to manager service to create
|
||||
client, and than to retrieve its data. This test checks how much time manager
|
||||
service took to response to each request.
|
||||
In this scenario, large number of requests are sent to things service to create
|
||||
things, and than to retrieve their data. This test checks how much time things
|
||||
service needs to respond to each request.
|
||||
|
||||
#### Results
|
||||
|
||||
TBD
|
||||
TBD
|
||||
|
|
|
@ -1,8 +1,2 @@
|
|||
.idea/
|
||||
target/
|
||||
.classpath
|
||||
.cache-tests
|
||||
.cache-main
|
||||
.settings/
|
||||
.project
|
||||
*.class
|
||||
bin/
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
# Load Test
|
||||
|
||||
This SBT project contains load tests written for mainflux platform.
|
||||
This project contains platform's load tests.
|
||||
|
||||
## Setup
|
||||
## Prerequisites
|
||||
|
||||
In order to run load tests you must have [openjdk8](http://openjdk.java.net/install/) and [sbt](https://www.scala-sbt.org/1.0/docs/Setup.html) installed on your machine.
|
||||
To run the tests you must have [OpenJDK8](http://openjdk.java.net/install/) and
|
||||
[SBT](https://www.scala-sbt.org/1.0/docs/Setup.html) installed on your machine.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -15,7 +16,7 @@ default values.
|
|||
| Variable | Description | Default |
|
||||
|----------|------------------------------------------|-----------------------|
|
||||
| users | Users service URL | http://localhost:8180 |
|
||||
| clients | Clients service URL | http://localhost:8182 |
|
||||
| things | Things service URL | http://localhost:8182 |
|
||||
| http | HTTP adapter service URL | http://localhost:8185 |
|
||||
| requests | Number of requests to be sent per second | 100 |
|
||||
|
||||
|
@ -23,8 +24,8 @@ default values.
|
|||
|
||||
This project contains two simulations:
|
||||
|
||||
- `PublishSimulation`
|
||||
- `CreateAndRetrieveClientSimulation`
|
||||
- `CreateAndRetrieveThings`
|
||||
- `PublishMessages`
|
||||
|
||||
To run all tests you will have to run following commands:
|
||||
|
||||
|
@ -33,18 +34,20 @@ cd <path_to_mainflux_project>/load-test
|
|||
sbt gatling:test
|
||||
```
|
||||
|
||||
### Publish Simulation
|
||||
### Things creation and retrieval
|
||||
|
||||
`PublishSimulation` contains load tests for publishing messages. To run this test use following command:
|
||||
`CreateAndRetrieveThings` contains load tests for creating and retrieving things.
|
||||
Execute the following command to run the suite:
|
||||
|
||||
```bash
|
||||
sbt "gatling:testOnly com.mainflux.loadtest.simulations.PublishSimulation"
|
||||
sbt "gatling:testOnly com.mainflux.loadtest.CreateAndRetrieveThings"
|
||||
```
|
||||
|
||||
### Create And Retrieve Client Simulation
|
||||
### Message publishing
|
||||
|
||||
`CreateAndRetrieveClientSimulation` contains load tests for creating and retrieving clients. To run this test use following command:
|
||||
`PublishMessages` contains load tests for publishing messages. Execute the following
|
||||
command to run the suite:
|
||||
|
||||
```bash
|
||||
sbt "gatling:testOnly com.mainflux.loadtest.simulations.CreateAndRetrieveClientSimulation"
|
||||
sbt "gatling:testOnly com.mainflux.loadtest.PublishMessages"
|
||||
```
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.mainflux.loadtest
|
||||
|
||||
object Constants {
|
||||
val UsersURL: String = System.getProperty("users", "http://localhost:8180")
|
||||
val ThingsURL: String = System.getProperty("things", "http://localhost:8182")
|
||||
val HttpAdapterURL: String = System.getProperty("http", "http://localhost:8185")
|
||||
val RequestsPerSecond: Double = Integer.getInteger("requests", 100).toDouble
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.mainflux.loadtest
|
||||
|
||||
import io.gatling.core.Predef._
|
||||
import io.gatling.http.Predef._
|
||||
import io.gatling.http.request.builder.HttpRequestBuilder.toActionBuilder
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
final class CreateAndRetrieveThings extends TestCase {
|
||||
override def prepareAndExecute(): SetUp = {
|
||||
val token = authenticate()
|
||||
val thing = """{"type":"device", "name":"weio"}"""
|
||||
|
||||
val scn = scenario("create and retrieve things")
|
||||
.exec(http("create thing")
|
||||
.post("/clients")
|
||||
.header(HttpHeaderNames.ContentType, jsonType)
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.body(StringBody(thing))
|
||||
.check(status.is(201))
|
||||
.check(headerRegex(HttpHeaderNames.Location, "(.*)").saveAs("location")))
|
||||
.exec(http("retrieve thing")
|
||||
.get("${location}")
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.check(status.is(200)))
|
||||
|
||||
setUp(scn.inject(constantUsersPerSec(RequestsPerSecond) during 15.seconds)).protocols(httpProtocol(ThingsURL))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package com.mainflux.loadtest
|
||||
|
||||
import io.circe._
|
||||
import io.circe.parser._
|
||||
import io.gatling.core.Predef._
|
||||
import io.gatling.http.Predef._
|
||||
import io.gatling.http.request.builder.HttpRequestBuilder.toActionBuilder
|
||||
import scalaj.http.Http
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
final class PublishMessages extends TestCase {
|
||||
override def prepareAndExecute(): SetUp = {
|
||||
def makeThing(token: String): (String, String) = {
|
||||
val thing = """{"type":"device", "name":"weio"}"""
|
||||
|
||||
val id = Http(s"$ThingsURL/clients")
|
||||
.postData(thing)
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.header(HttpHeaderNames.ContentType, jsonType)
|
||||
.asString
|
||||
.headers(HttpHeaderNames.Location)(0).split("/")(2)
|
||||
|
||||
val res = Http(s"$ThingsURL/things/$id")
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.header(HttpHeaderNames.ContentType, jsonType)
|
||||
.asString
|
||||
.body
|
||||
|
||||
val key = parse(res).getOrElse(Json.Null).hcursor.downField("key").as[String].getOrElse("")
|
||||
|
||||
(id, key)
|
||||
}
|
||||
|
||||
def makeChannel(token: String): String = {
|
||||
val channel = """{"name":"mychan"}"""
|
||||
|
||||
Http(s"$ThingsURL/channels")
|
||||
.postData(channel)
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.header(HttpHeaderNames.ContentType, jsonType)
|
||||
.asString
|
||||
.headers(HttpHeaderNames.Location)(0)
|
||||
.split("/")(2)
|
||||
}
|
||||
|
||||
def connect(channel: String, thing: String, token: String): Unit = {
|
||||
Http(s"$ThingsURL/channels/$channel/things/$thing")
|
||||
.method("PUT")
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.asString
|
||||
}
|
||||
|
||||
val message =
|
||||
"""
|
||||
|[
|
||||
| {"bn":"some-base-name:","bt":1.276020076001e+09,"bu":"A","bver":5,"n":"voltage","u":"V","v":120.1},
|
||||
| {"n":"current","t":-5,"v":1.2},
|
||||
| {"n":"current","t":-4,"v":1.3}
|
||||
|]""".stripMargin
|
||||
|
||||
val token = authenticate()
|
||||
val (thingID, thingKey) = makeThing(token)
|
||||
val channelID = makeChannel(token)
|
||||
|
||||
connect(channelID, thingID, thingKey)
|
||||
|
||||
val scn = scenario("publish message")
|
||||
.exec(http("publish message request")
|
||||
.post(s"/channels/$channelID/messages")
|
||||
.header(HttpHeaderNames.ContentType, "application/senml+json")
|
||||
.header(HttpHeaderNames.Authorization, thingKey)
|
||||
.body(StringBody(message))
|
||||
.check(status.is(202)))
|
||||
|
||||
setUp(scn.inject(constantUsersPerSec(RequestsPerSecond) during 15.seconds)).protocols(httpProtocol(url()))
|
||||
}
|
||||
|
||||
private def url(): String = System.getProperty("http", "http://localhost:8185")
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.mainflux.loadtest
|
||||
|
||||
import io.circe._
|
||||
import io.circe.parser._
|
||||
import io.gatling.core.Predef._
|
||||
import io.gatling.http.Predef._
|
||||
import io.gatling.http.protocol.HttpProtocol
|
||||
import scalaj.http.Http
|
||||
|
||||
trait TestCase extends Simulation {
|
||||
protected lazy val UsersURL: String = System.getProperty("users", "http://localhost:8180")
|
||||
protected lazy val ThingsURL: String = System.getProperty("things", "http://localhost:8182")
|
||||
protected lazy val RequestsPerSecond: Double = Integer.getInteger("requests", 100).toDouble
|
||||
|
||||
protected val jsonType: String = "application/jsonType"
|
||||
|
||||
def authenticate(): String = {
|
||||
val user = """{"email":"john.doe@email.com", "password":"123"}"""
|
||||
val headerName = HttpHeaderNames.ContentType
|
||||
val contentType = jsonType
|
||||
|
||||
Http(s"$UsersURL/users")
|
||||
.postData(user)
|
||||
.header(headerName, contentType)
|
||||
.asString
|
||||
|
||||
val res = Http(s"$UsersURL/tokens")
|
||||
.postData(user)
|
||||
.header(headerName, contentType)
|
||||
.asString
|
||||
.body
|
||||
|
||||
val cursor = parse(res).getOrElse(Json.Null).hcursor
|
||||
cursor.downField("token").as[String].getOrElse("")
|
||||
}
|
||||
|
||||
def httpProtocol(url: String): HttpProtocol = http
|
||||
.baseURL(url)
|
||||
.inferHtmlResources()
|
||||
.acceptHeader("*/*")
|
||||
.contentTypeHeader(jsonType)
|
||||
.userAgentHeader("curl/7.54.0")
|
||||
.build
|
||||
|
||||
def prepareAndExecute(): SetUp
|
||||
|
||||
prepareAndExecute()
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.mainflux.loadtest.simulations
|
||||
|
||||
object Constants {
|
||||
val UsersUrl = System.getProperty("users", "http://localhost:8180")
|
||||
val ClientsUrl = System.getProperty("clients", "http://localhost:8182")
|
||||
val HttpAdapterUrl = System.getProperty("http", "http://localhost:8185")
|
||||
val RequestsPerSecond = Integer.getInteger("requests", 100)
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package com.mainflux.loadtest.simulations
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scalaj.http.Http
|
||||
import io.gatling.core.Predef._
|
||||
import io.gatling.http.Predef._
|
||||
import io.gatling.jdbc.Predef._
|
||||
import io.circe._
|
||||
import io.circe.generic.auto._
|
||||
import io.circe.parser._
|
||||
import io.circe.syntax._
|
||||
import CreateAndRetrieveClientSimulation._
|
||||
import io.gatling.http.protocol.HttpProtocolBuilder.toHttpProtocol
|
||||
import io.gatling.http.request.builder.HttpRequestBuilder.toActionBuilder
|
||||
import com.mainflux.loadtest.simulations.Constants._
|
||||
|
||||
class CreateAndRetrieveClientSimulation extends Simulation {
|
||||
|
||||
// Register user
|
||||
Http(s"${UsersUrl}/users")
|
||||
.postData(User)
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.asString
|
||||
|
||||
// Login user
|
||||
val tokenRes = Http(s"${UsersUrl}/tokens")
|
||||
.postData(User)
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.asString
|
||||
.body
|
||||
|
||||
val tokenCursor = parse(tokenRes).getOrElse(Json.Null).hcursor
|
||||
val token = tokenCursor.downField("token").as[String].getOrElse("")
|
||||
|
||||
// Prepare testing scenario
|
||||
val httpProtocol = http
|
||||
.baseURL(ClientsUrl)
|
||||
.inferHtmlResources()
|
||||
.acceptHeader("*/*")
|
||||
.contentTypeHeader(ContentType)
|
||||
.userAgentHeader("curl/7.54.0")
|
||||
|
||||
val scn = scenario("CreateAndGetClient")
|
||||
.exec(http("CreateClientRequest")
|
||||
.post("/clients")
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.body(StringBody(Client))
|
||||
.check(status.is(201))
|
||||
.check(headerRegex(HttpHeaderNames.Location, "(.*)").saveAs("location")))
|
||||
.exec(http("GetClientRequest")
|
||||
.get("${location}")
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.check(status.is(200)))
|
||||
|
||||
setUp(
|
||||
scn.inject(
|
||||
constantUsersPerSec(RequestsPerSecond.toDouble) during (15 second))).protocols(httpProtocol)
|
||||
}
|
||||
|
||||
object CreateAndRetrieveClientSimulation {
|
||||
val ContentType = "application/json"
|
||||
val User = """{"email":"john.doe@email.com", "password":"123"}"""
|
||||
val Client = """{"type":"device", "name":"weio"}"""
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package com.mainflux.loadtest.simulations
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scalaj.http.Http
|
||||
import io.gatling.core.Predef._
|
||||
import io.gatling.http.Predef._
|
||||
import io.gatling.jdbc.Predef._
|
||||
import io.circe._
|
||||
import io.circe.generic.auto._
|
||||
import io.circe.parser._
|
||||
import io.circe.syntax._
|
||||
import PublishSimulation._
|
||||
import io.gatling.http.protocol.HttpProtocolBuilder.toHttpProtocol
|
||||
import io.gatling.http.request.builder.HttpRequestBuilder.toActionBuilder
|
||||
import com.mainflux.loadtest.simulations.Constants._
|
||||
|
||||
class PublishSimulation extends Simulation {
|
||||
|
||||
// Register user
|
||||
Http(s"${UsersUrl}/users")
|
||||
.postData(User)
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.asString
|
||||
|
||||
// Login user
|
||||
val tokenRes = Http(s"${UsersUrl}/tokens")
|
||||
.postData(User)
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.asString
|
||||
.body
|
||||
|
||||
val tokenCursor = parse(tokenRes).getOrElse(Json.Null).hcursor
|
||||
val token = tokenCursor.downField("token").as[String].getOrElse("")
|
||||
|
||||
// Register client
|
||||
val clientLocation = Http(s"${ClientsUrl}/clients")
|
||||
.postData(Client)
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.asString
|
||||
.headers.get("Location").get(0)
|
||||
|
||||
val clientId = clientLocation.split("/")(2)
|
||||
|
||||
// Get client key
|
||||
val clientRes = Http(s"${ClientsUrl}/clients/${clientId}")
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.asString
|
||||
.body
|
||||
|
||||
val clientCursor = parse(clientRes).getOrElse(Json.Null).hcursor
|
||||
val clientKey = clientCursor.downField("key").as[String].getOrElse("")
|
||||
|
||||
// Register channel
|
||||
val chanLocation = Http(s"${ClientsUrl}/channels")
|
||||
.postData(Channel)
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.header(HttpHeaderNames.ContentType, ContentType)
|
||||
.asString
|
||||
.headers.get("Location").get(0)
|
||||
|
||||
val chanId = chanLocation.split("/")(2)
|
||||
|
||||
// Connect client to channel
|
||||
Http(s"${ClientsUrl}/channels/${chanId}/clients/${clientId}")
|
||||
.method("PUT")
|
||||
.header(HttpHeaderNames.Authorization, token)
|
||||
.asString
|
||||
|
||||
// Prepare testing scenario
|
||||
val httpProtocol = http
|
||||
.baseURL(HttpAdapterUrl)
|
||||
.inferHtmlResources()
|
||||
.acceptHeader("*/*")
|
||||
.contentTypeHeader("application/json; charset=utf-8")
|
||||
.userAgentHeader("curl/7.54.0")
|
||||
|
||||
val scn = scenario("PublishMessage")
|
||||
.exec(http("PublishMessageRequest")
|
||||
.post(s"/channels/${chanId}/messages")
|
||||
.header(HttpHeaderNames.ContentType, "application/senml+json")
|
||||
.header(HttpHeaderNames.Authorization, clientKey)
|
||||
.body(StringBody(Message))
|
||||
.check(status.is(202)))
|
||||
|
||||
setUp(
|
||||
scn.inject(
|
||||
constantUsersPerSec(RequestsPerSecond.toDouble) during (15 second))).protocols(httpProtocol)
|
||||
}
|
||||
|
||||
object PublishSimulation {
|
||||
val ContentType = "application/json"
|
||||
val User = """{"email":"john.doe@email.com", "password":"123"}"""
|
||||
val Client = """{"type":"device", "name":"weio"}"""
|
||||
val Channel = """{"name":"mychan"}"""
|
||||
val Message = """[{"bn":"some-base-name:","bt":1.276020076001e+09, "bu":"A","bver":5, "n":"voltage","u":"V","v":120.1}, {"n":"current","t":-5,"v":1.2}, {"n":"current","t":-4,"v":1.3}]"""
|
||||
}
|
Loading…
Reference in New Issue