mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-28 13:48:49 +08:00
Removed gatling load-test (#1005)
Signed-off-by: Nikola Marcetic <n.marcetic86@gmail.com>
This commit is contained in:
parent
0d3adfdc5c
commit
8475e87fe7
@ -4,6 +4,5 @@ build
|
|||||||
docker
|
docker
|
||||||
docs
|
docs
|
||||||
k8s
|
k8s
|
||||||
load-test
|
|
||||||
metrics
|
metrics
|
||||||
scripts
|
scripts
|
||||||
|
2
load-test/.gitignore
vendored
2
load-test/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
.idea/
|
|
||||||
target/
|
|
@ -1,64 +0,0 @@
|
|||||||
# Load Test
|
|
||||||
|
|
||||||
This project contains platform's load tests.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
Tests are configured to use variables from `JAVA_OPTS` presented in the
|
|
||||||
following table. Note that any unset variables will be replaced with their
|
|
||||||
default values.
|
|
||||||
|
|
||||||
| Variable | Description | Default |
|
|
||||||
|----------|------------------------------------------|-----------------------|
|
|
||||||
| 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 three simulations:
|
|
||||||
|
|
||||||
- `CreateAndRetrieveThings`
|
|
||||||
- `PublishHttpMessages`
|
|
||||||
- `PublishWsMessages`
|
|
||||||
|
|
||||||
To run all tests you will have to run following commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd <path_to_mainflux_project>/load-test
|
|
||||||
sbt gatling:test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Things creation and retrieval
|
|
||||||
|
|
||||||
`CreateAndRetrieveThings` contains load tests for creating and retrieving things.
|
|
||||||
Execute the following command to run the suite:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sbt "gatling:testOnly com.mainflux.loadtest.CreateAndRetrieveThings"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Message publishing over HTTP adapter
|
|
||||||
|
|
||||||
`PublishHttpMessages` contains load tests for publishing messages over HTTP.
|
|
||||||
Execute the following command to run the suite:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
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"
|
|
||||||
```
|
|
@ -1,18 +0,0 @@
|
|||||||
enablePlugins(GatlingPlugin)
|
|
||||||
|
|
||||||
name := "load-test"
|
|
||||||
version := "0.10.0"
|
|
||||||
|
|
||||||
scalaVersion := "2.12.4"
|
|
||||||
|
|
||||||
val gatlingVersion = "2.3.1"
|
|
||||||
val circeVersion = "0.9.3"
|
|
||||||
|
|
||||||
libraryDependencies ++= Seq(
|
|
||||||
"io.gatling.highcharts" % "gatling-charts-highcharts" % gatlingVersion,
|
|
||||||
"io.gatling" % "gatling-test-framework" % gatlingVersion,
|
|
||||||
"org.scalaj" %% "scalaj-http" % "2.3.0",
|
|
||||||
"io.circe" %% "circe-core" % circeVersion,
|
|
||||||
"io.circe" %% "circe-generic" % circeVersion,
|
|
||||||
"io.circe" %% "circe-parser" % circeVersion
|
|
||||||
)
|
|
@ -1 +0,0 @@
|
|||||||
sbt.version=1.1.2
|
|
@ -1 +0,0 @@
|
|||||||
addSbtPlugin("io.gatling" % "gatling-sbt" % "2.2.2")
|
|
@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
|
|
||||||
</encoder>
|
|
||||||
<immediateFlush>false</immediateFlush>
|
|
||||||
</appender>
|
|
||||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
|
||||||
<appender-ref ref="CONSOLE" />
|
|
||||||
</appender>
|
|
||||||
<root level="WARN">
|
|
||||||
<appender-ref ref="ASYNC" />
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Mainflux
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 CreateAndRetrieveThings extends TestCase {
|
|
||||||
override def prepareAndExecute(): SetUp = {
|
|
||||||
val token = authenticate()
|
|
||||||
val thing = """{"name":"weio"}"""
|
|
||||||
|
|
||||||
val scn = scenario("create and retrieve things")
|
|
||||||
.exec(http("create thing")
|
|
||||||
.post("/things")
|
|
||||||
.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))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Mainflux
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Mainflux
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.mainflux.loadtest
|
|
||||||
|
|
||||||
import io.circe._
|
|
||||||
import io.circe.parser._
|
|
||||||
import io.gatling.http.Predef._
|
|
||||||
import scalaj.http.Http
|
|
||||||
|
|
||||||
abstract class PublishMessages extends TestCase {
|
|
||||||
def makeThing(token: String): (String, String) = {
|
|
||||||
val thing = """{"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 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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Mainflux
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Mainflux
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
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/json"
|
|
||||||
|
|
||||||
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 wsProtocol(url: String): HttpProtocol = http
|
|
||||||
.baseURL(s"http://$url")
|
|
||||||
.inferHtmlResources()
|
|
||||||
.acceptHeader("*/*")
|
|
||||||
.userAgentHeader("Gatling2")
|
|
||||||
.wsBaseURL(s"ws://$url")
|
|
||||||
.build
|
|
||||||
|
|
||||||
def prepareAndExecute(): SetUp
|
|
||||||
|
|
||||||
prepareAndExecute()
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user