NOISSUE - Add test suite for WebSocket adapter (#299)

* Add load test for WebSocket adapter

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add new test suite to README file

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
This commit is contained in:
Aleksandar Novaković 2018-05-25 11:53:45 +02:00 committed by Drasko DRASKOVIC
parent 808ac50792
commit ef3627f4ee
6 changed files with 135 additions and 76 deletions

View File

@ -18,14 +18,16 @@ default values.
| users | Users service URL | http://localhost:8180 |
| things | Things service URL | http://localhost:8182 |
| http | HTTP adapter service URL | http://localhost:8185 |
| ws | WebSocket adapter service URL | localhost:8186 |
| requests | Number of requests to be sent per second | 100 |
## Usage
This project contains two simulations:
This project contains three simulations:
- `CreateAndRetrieveThings`
- `PublishMessages`
- `PublishHttpMessages`
- `PublishWsMessages`
To run all tests you will have to run following commands:
@ -43,11 +45,20 @@ Execute the following command to run the suite:
sbt "gatling:testOnly com.mainflux.loadtest.CreateAndRetrieveThings"
```
### Message publishing
### Message publishing over HTTP adapter
`PublishMessages` contains load tests for publishing messages. Execute the following
command to run the suite:
`PublishHttpMessages` contains load tests for publishing messages over HTTP.
Execute the following command to run the suite:
```bash
sbt "gatling:testOnly com.mainflux.loadtest.PublishMessages"
sbt "gatling:testOnly com.mainflux.loadtest.PublishHttpMessages"
```
### Message publishing over WebSocket adapter
`PublishWsMessages` contains load tests for publishing messages over WebSocket.
Execute the following command to run the suite:
```bash
sbt "gatling:testOnly com.mainflux.loadtest.PublishWsMessages"
```

View File

@ -1,11 +1,11 @@
package com.mainflux.loadtest
import scala.concurrent.duration._
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()
@ -27,4 +27,3 @@ final class CreateAndRetrieveThings extends TestCase {
setUp(scn.inject(constantUsersPerSec(RequestsPerSecond) during 15.seconds)).protocols(httpProtocol(ThingsURL))
}
}

View File

@ -0,0 +1,37 @@
package com.mainflux.loadtest
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.http.request.builder.HttpRequestBuilder.toActionBuilder
final class PublishHttpMessages extends PublishMessages {
override def prepareAndExecute(): SetUp = {
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, token)
val scn = scenario("publish message over HTTP")
.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

@ -2,79 +2,47 @@ 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._
abstract class PublishMessages extends TestCase {
def makeThing(token: String): (String, String) = {
val thing = """{"type":"device", "name":"weio"}"""
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/things")
.postData(thing)
.header(HttpHeaderNames.Authorization, token)
.header(HttpHeaderNames.ContentType, jsonType)
.asString
.headers(HttpHeaderNames.Location)(0).split("/")(2)
val id = Http(s"$ThingsURL/things")
.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 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("")
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()))
(id, key)
}
private def url(): String = System.getProperty("http", "http://localhost:8185")
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
}
}

View File

@ -0,0 +1,36 @@
package com.mainflux.loadtest
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
final class PublishWsMessages extends PublishMessages {
override def prepareAndExecute(): SetUp = {
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, token)
val scn = scenario("publish message over WebSocket")
.exec(ws("Connect WS")
.open(s"/channels/$channelID/messages?authorization=$thingKey"))
.exec(ws("Send message")
.sendText(message)
.check(wsAwait.within(30).until(1)))
.exec(ws("Close WS").close)
setUp(scn.inject(constantUsersPerSec(RequestsPerSecond) during 15.seconds)).protocols(wsProtocol(url()))
}
private def url(): String = System.getProperty("ws", "localhost:8186")
}

View File

@ -12,7 +12,7 @@ trait TestCase extends Simulation {
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"
protected val jsonType: String = "application/json"
def authenticate(): String = {
val user = """{"email":"john.doe@email.com", "password":"123"}"""
@ -42,6 +42,14 @@ trait TestCase extends Simulation {
.userAgentHeader("curl/7.54.0")
.build
def wsProtocol(url: String): HttpProtocol = http
.baseURL(s"http://$url")
.inferHtmlResources()
.acceptHeader("*/*")
.userAgentHeader("Gatling2")
.wsBaseURL(s"ws://$url")
.build
def prepareAndExecute(): SetUp
prepareAndExecute()