69 lines
2.2 KiB
JavaScript
69 lines
2.2 KiB
JavaScript
import http from 'k6/http';
|
|
import { check, sleep } from 'k6';
|
|
import { Rate } from 'k6/metrics';
|
|
|
|
// Custom metric to explicitly track the percentage of unauthorized requests
|
|
const unauthorizedRate = new Rate('unauthorized_rate');
|
|
|
|
export const options = {
|
|
// Test scenario: 1000 virtual users executing 1 iteration each
|
|
vus: 1000,
|
|
iterations: 1000,
|
|
// We can also define thresholds for CI/CD pipelines
|
|
thresholds: {
|
|
'http_req_duration': ['p(95)<500'], // 95% of requests must complete below 500ms
|
|
'unauthorized_rate': ['rate==0'], // 0% unauthorized errors (strict constraint)
|
|
},
|
|
};
|
|
|
|
const BASE_URL = 'http://localhost:5064';
|
|
|
|
export default function () {
|
|
// --- Setup / Login Phase ---
|
|
// Each VU initializes its own secure session and receives a unique token.
|
|
const initRes = http.post(`${BASE_URL}/Init`);
|
|
|
|
check(initRes, {
|
|
'init status is 200': (r) => r.status === 200,
|
|
'init returned sequenceId': (r) => r.json('initialSequenceId') !== undefined,
|
|
});
|
|
|
|
if (initRes.status !== 200) {
|
|
return; // Stop VU if init fails to prevent cascading errors
|
|
}
|
|
|
|
// Local state for the virtual user
|
|
let currentToken = initRes.json('initialSequenceId');
|
|
|
|
// --- Stateful Mutation Phase ---
|
|
// The VU performs 50 sequential requests. In a real scenario, these would be GET/POST/PUT.
|
|
for (let i = 0; i < 50; i++) {
|
|
const res = http.get(`${BASE_URL}/Secure/data`, {
|
|
headers: {
|
|
'X-Auth-Seq': currentToken,
|
|
},
|
|
});
|
|
|
|
const success = check(res, {
|
|
'status is 200': (r) => r.status === 200,
|
|
'has X-Next-Seq header': (r) => r.headers['X-Next-Seq'] !== undefined,
|
|
});
|
|
|
|
if (res.status === 401) {
|
|
unauthorizedRate.add(1);
|
|
console.error(`VU ${__VU} experienced sequence break on iteration ${i}! Received 401.`);
|
|
break; // The chain is broken, stop further requests
|
|
} else {
|
|
unauthorizedRate.add(0);
|
|
}
|
|
|
|
if (success) {
|
|
// Critical Step: Read X-Next-Seq from Response and save it for the next request in the chain
|
|
currentToken = res.headers['X-Next-Seq'];
|
|
}
|
|
|
|
// Simulate real-world delay between operations (optional, but realistic)
|
|
// sleep(Math.random() * 0.1);
|
|
}
|
|
}
|