who_need_help/load/k6/scale-readonly.js

126 lines
3.4 KiB
JavaScript

import { check, sleep } from "k6";
import http from "k6/http";
import exec from "k6/execution";
import { Trend } from "k6/metrics";
function required(name) {
const value = __ENV[name];
if (value === undefined || value === "") {
throw new Error(`${name} is required`);
}
return value;
}
function positiveInteger(name) {
const value = Number(required(name));
if (!Number.isInteger(value) || value <= 0) {
throw new Error(`${name} must be a positive integer`);
}
return value;
}
function nonNegativeNumber(name) {
const value = Number(required(name));
if (!Number.isFinite(value) || value < 0) {
throw new Error(`${name} must be a non-negative number`);
}
return value;
}
const baseUrl = required("BASE_URL").replace(/\/+$/, "");
if (baseUrl !== "http://web:4000") {
throw new Error("The scale read-only profile is pinned to http://web:4000");
}
const sessionCookie = required("SESSION_COOKIE");
const vus = positiveInteger("VUS");
const duration = required("DURATION");
const thinkSeconds = nonNegativeNumber("THINK_SECONDS");
const viewports = [
{
path:
"/requests?west=22.096886&south=45.034261&east=38.949914&north=55.310025&zoom=5&width=767&height=734&view=split",
endpoint: "requests_europe",
heading: "Who needs help?",
},
{
path:
"/activities?west=22.096886&south=45.034261&east=38.949914&north=55.310025&zoom=5&width=767&height=734&view=split",
endpoint: "activities_europe",
heading: "Nearby activities",
},
{
path:
"/requests?west=-179.9&south=-80&east=179.9&north=80&zoom=1&width=1280&height=720&view=map",
endpoint: "requests_world",
heading: "Who needs help?",
},
{
path:
"/activities?west=-179.9&south=-80&east=179.9&north=80&zoom=1&width=1280&height=720&view=map",
endpoint: "activities_world",
heading: "Nearby activities",
},
];
const endpointDurations = {
requests_europe: new Trend("wnh_requests_europe_duration", true),
activities_europe: new Trend("wnh_activities_europe_duration", true),
requests_world: new Trend("wnh_requests_world_duration", true),
activities_world: new Trend("wnh_activities_world_duration", true),
};
export const options = {
scenarios: {
scale_readonly_http: {
executor: "constant-vus",
exec: "scaleReadonlyHttp",
vus,
duration,
},
},
thresholds: {
checks: [{ threshold: "rate==1", abortOnFail: true }],
http_req_failed: [{ threshold: "rate==0", abortOnFail: true }],
},
};
export function scaleReadonlyHttp() {
const viewport = viewports[exec.scenario.iterationInTest % viewports.length];
const response = http.get(`${baseUrl}${viewport.path}`, {
redirects: 0,
tags: {
endpoint: viewport.endpoint,
safety_scope: "persistent_local_scale_readonly",
},
headers: {
Cookie: sessionCookie,
Host: "scale.localhost",
"X-Forwarded-Host": "scale.localhost",
"X-Forwarded-Port": "4121",
"X-Forwarded-Proto": "https",
"User-Agent": "WhoNeedHelp-persistent-scale-readonly/1",
},
});
endpointDurations[viewport.endpoint].add(response.timings.duration);
check(response, {
[`GET ${viewport.endpoint} returned 200`]: (candidate) =>
candidate.status === 200,
[`GET ${viewport.endpoint} rendered its loading shell`]: (candidate) =>
candidate.body.includes(viewport.heading) &&
candidate.body.includes("Loading results"),
});
sleep(thinkSeconds);
}