NOISSUE - Update load tests (#287)

This commit is contained in:
Dejan Mijić 2018-05-17 14:21:08 +02:00 committed by GitHub
parent 38a107919a
commit 9c6904d9b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 189 additions and 197 deletions

View File

@ -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

View File

@ -1,8 +1,2 @@
.idea/
target/
.classpath
.cache-tests
.cache-main
.settings/
.project
*.class
bin/

View File

@ -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"
```

View File

@ -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
}

View File

@ -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))
}
}

View File

@ -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")
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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"}"""
}

View File

@ -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}]"""
}