Skip to content

Commit

Permalink
Ws load tests (#22)
Browse files Browse the repository at this point in the history
* [US] Changed the websocket protocol for load test

* [US] Modified the messages sent to the CSMS via the websocket connection

* [US] Added an array of csids

* [US] Added base64 encoding and iteration per vu load simulation

* [US] Added VU ramp up and ramp down simulation

* [US] Added VUIds to match the number of charge stations available

* [US] Added more load duration for vus

* [US] Added wait times for the messages during the websocket connection

* [US] Modified load simulation time and vus

* Include grafana and prometheus in docker compose and k6 for loadtests

* [US] Added README file to set up load tests in k6

* [US] Removed K6 executable file

* [US] Modified README
  • Loading branch information
usuletw022 authored Oct 19, 2023
1 parent ebbdf0c commit ec80784
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,7 @@ fabric.properties
.history
.ionide

#k6 executable file
k6

# End of https://www.toptal.com/developers/gitignore/api/goland+all,visualstudiocode,go
15 changes: 15 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,18 @@ services:
- --host-port=0.0.0.0:8080
ports:
- "8080:8080"

grafana:
image: grafana/grafana:7.5.7
ports:
- 3000:3000
restart: unless-stopped

prometheus:
image: prom/prometheus:v2.45.1
ports:
- "9090:9090"
volumes:
- ./prometheus:/etc/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
Binary file added loadtests/.DS_Store
Binary file not shown.
77 changes: 77 additions & 0 deletions loadtests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Project Name

Load Testing with K6

## Table of Contents

- [Project Description](#project-description)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Getting Started](#getting-started)
- [Usage](#usage)
- [Contributing](#contributing)
- [License](#license)

## Project Description

To set up a load test against the CSMS back-end using a number of simulated charge stations.

## Prerequisites
1. Ensure that the CSMS backend is running via docker

## Installation

1. Install k6 onto your local machine
```bash
brew install k6
```
2. Download xk6 using go
```bash
go install go.k6.io/xk6/cmd/xk6@latest
```

3. Build the binary
```bash
xk6 build --with github.com/grafana/xk6-dashboard@latest
```

## Getting Started

1. Extract and copy the base64SHA256Password using the following command
```bash
(cd manager && go run main.go auth encode-password fiddlesticks_fishsticks)
```
2. Register a number of charge stations to the CSMS (e.g. cs1, cs2, cs3 etc). Replace 'BASE64_SHA256_PASSWORD' with the base64SHA256Password that was extracted
```bash
curl http://localhost:9410/api/v0/cs/cs1 -H 'content-type: application/json' -d '{"securityProfile":1,"base64SHA256Password":"BASE64_SHA256_PASSWORD"}' &&
curl http://localhost:9410/api/v0/cs/cs2 -H 'content-type: application/json' -d '{"securityProfile":1,"base64SHA256Password":"BASE64_SHA256_PASSWORD"}' &&
curl http://localhost:9410/api/v0/cs/cs3 -H 'content-type: application/json' -d '{"securityProfile":1,"base64SHA256Password":"BASE64_SHA256_PASSWORD"}'
```

3. Register the contract token to the CSMS
```bash
curl -i http://localhost:9410/api/v0/token -H 'content-type: application/json' -d '{"countryCode": "GB","partyId": "TWK","type": "RFID","uid": "38748383L7337848H823","contractId": "GBTWK012345678V","issuer": "Thoughtworks","valid": true,"cacheMode": "ALWAYS"}'
```

4. Set the load simulation in loadtests/ws_load_test.js

```bash
scenarios: {
contacts: {
executor: 'ramping-vus',
startVUs: ,
stages: [
{ duration: '', target: },
],
gracefulRampDown: '',
}
```
5. Run the load test using the script file and output the results to the k6 dashboard
```bash
./k6 run --out dashboard loadtests/ws_load_test.js
```
84 changes: 84 additions & 0 deletions loadtests/ws_load_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import ws from 'k6/ws';
import { check } from 'k6';
import encoding from 'k6/encoding';
import exec from 'k6/execution';
import { sleep } from 'k6';

export const options = {
discardResponseBodies: true,
scenarios: {
contacts: {
executor: 'ramping-vus',
startVUs: 2,
stages: [
{ duration: '5m', target: 50 },
{ duration: '5m', target: 100 },
{ duration: '10m', target: 200 },
{ duration: '10m', target: 300 },
{ duration: '10m', target: 400 },
{ duration: '10m', target: 500 },
{ duration: '10m', target: 600 },
{ duration: '5m', target: 550 },
{ duration: '5m', target: 600 },
{ duration: '5m', target: 550 },
{ duration: '5m', target: 600 },
{ duration: '10m', target: 500 },
{ duration: '10m', target: 400 },
{ duration: '10m', target: 300 },
{ duration: '10m', target: 100 },
{ duration: '5m', target: 50 },
{ duration: '5m', target: 0 }
],
gracefulRampDown: '0s',
},
},
};

export default function () {
let vuIdInTest = exec.vu.idInTest
let data = `cs${vuIdInTest}:fiddlesticks_fishsticks`;
let base64data = encoding.b64encode(data)
const params = {
headers: {'Sec-WebSocket-Protocol': 'ocpp1.6', 'Authorization': `Basic ${base64data}`}
};
const url = `ws://localhost/ws/cs${vuIdInTest}`;
const res = ws.connect(url, params, function (socket) {
socket.send('[2,"1","BootNotification",{"chargePointModel":"me100","chargePointVendor":"me"}]');
sleep(10)
socket.send('[2,"2", "StatusNotification", {"connectorId": 1, "errorCode": "NoError", "status": "Available"}]');
sleep(10)
socket.send('[2,"3","Heartbeat", {}]');
sleep(10)
socket.send('[2,"4","Heartbeat", {}]');
sleep(10)
socket.send('[2,"5","Heartbeat", {}]');
sleep(10)
socket.send('[2, "6", "Authorize", {"idTag": "38748383L7337848H823"}]');
sleep(10)
socket.send('[2,"7", "StatusNotification", {"connectorId": 1, "errorCode": "NoError", "status": "Preparing"}]');
sleep(10)
socket.send('[2,"8", "StartTransaction",{"connectorId": 1, "idTag": "38748383L7337848H823", "meterStart": 3, "reservationId": 5, "timestamp":"2023-09-18T08:25:40.20Z"}]');
sleep(300)
socket.send('[2,"9","Heartbeat", {}]');
sleep(60)
socket.send('[2,"10","Heartbeat", {}]');
sleep(60)
socket.send('[2,"11","Heartbeat", {}]');
sleep(60)
sleep(300)
socket.send('[2,"12", "MeterValues", {"connectorId": 1, "meterValue":[{"timestamp":"2023-09-18T08:25:40.20Z", "sampledValue": [{"value": "5"}]}]}]');
sleep(60)
socket.send('[2,"13", "MeterValues", {"connectorId": 1, "meterValue":[{"timestamp":"2023-09-18T08:25:40.20Z", "sampledValue": [{"value": "5"}]}]}]');
sleep(60)
socket.send('[2,"14", "StopTransaction", {"idTag": "38748383L7337848H823", "meterStop": 3, "timestamp": "2023-09-18T08:25:40.20Z", "transactionId": 3}]');
sleep(10)
socket.send('[2,"15", "StatusNotification", {"connectorId": 1, "errorCode": "NoError", "status": "Finishing"}]');
sleep(10)
socket.send('[2,"16", "StatusNotification", {"connectorId": 1, "errorCode": "NoError", "status": "Available"}]');
sleep(10)
socket.close()
}
);

check(res, { 'status is 101': (r) => r && r.status === 101 });
}
11 changes: 11 additions & 0 deletions prometheus/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
global:
scrape_interval: 15s

scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: [ 'host.docker.internal:9090' ]
- job_name: 'endpoints'
static_configs:
- targets: ['gateway:9312', 'manager:9410']

0 comments on commit ec80784

Please sign in to comment.