Fix 4 Code Review findings on FRE-4928: dead heredoc, token warmup, summary path, .gitignore

- P2: Remove dead heredoc from run.sh mixed scenario
- P2: Add setup() warmup to seed real tokens for standalone scenarios
- P3: Replace handleSummary file output with --summary-export in run.sh
- P3: Add .gitignore for k6 results and .env
- Fix stray closing brace in scripts/load-test/lib/common.js

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-05-10 11:44:56 -04:00
parent c1e4e8e404
commit 4a2f6cf0fd
4 changed files with 66 additions and 41 deletions

5
load-tests/darkwatch-auth/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# k6 load test results
results/
# Local environment overrides
.env

View File

@@ -45,12 +45,42 @@ const credentialPool = Array.from({ length: CREDENTIAL_POOL_SIZE }, (_, i) => ({
password: TEST_PASSWORD,
}));
// Pre-warmed token pool for refresh/logout standalone scenarios
// Fake token pool fallback — used when setup() warmup is skipped or fails
const tokenPool = Array.from({ length: CREDENTIAL_POOL_SIZE }, () => ({
accessToken: uuidv4(),
refreshToken: uuidv4(),
}));
// ── Setup: Seed real tokens via login warmup ──────────────────────────────────
export function setup() {
const creds = credentialPool[0];
const payload = JSON.stringify({ email: creds.email, password: creds.password });
const res = http.post(`${BASE_URL}/auth/login`, payload, { headers: authHeaders });
try {
const json = JSON.parse(res.body);
const accessToken = json.access_token || json.token || json.data?.access_token;
const refreshToken = json.refresh_token || json.data?.refresh_token;
if (accessToken && refreshToken) {
return {
accessToken,
refreshToken,
warmupSuccess: true,
};
}
} catch {
// fall through to fake tokens
}
console.warn(`[warmup] Login returned ${res.status} — standalone scenarios will use fake tokens (expect 401/403)`);
return {
accessToken: tokenPool[0].accessToken,
refreshToken: tokenPool[0].refreshToken,
warmupSuccess: false,
};
}
// ── Scenario: Login (POST /auth/login) ──────────────────────────────────────
function testLogin(email, password) {
const creds = email
@@ -243,13 +273,25 @@ export function loginOnly() {
sleep(0.1);
}
export function logoutOnly() {
testLogout();
export function logoutOnly(data) {
if (data && data.warmupSuccess) {
testLogout(data.accessToken, data.refreshToken);
} else {
const poolEntry = tokenPool[Math.floor(Math.random() * tokenPool.length)];
console.warn('[logoutOnly] Using fake token (warmup skipped or failed)');
testLogout(poolEntry.accessToken, poolEntry.refreshToken);
}
sleep(0.1);
}
export function refreshOnly() {
testRefresh();
export function refreshOnly(data) {
if (data && data.warmupSuccess) {
testRefresh(data.refreshToken);
} else {
const poolEntry = tokenPool[Math.floor(Math.random() * tokenPool.length)];
console.warn('[refreshOnly] Using fake token (warmup skipped or failed)');
testRefresh(poolEntry.refreshToken);
}
sleep(0.1);
}
@@ -264,37 +306,15 @@ export function handleSummary(data) {
metric.thresholds.every((t) => t.pass)
);
const loginP99 = data.metrics.login_p99?.values['p(99)']?.toFixed(2) || 'N/A';
const logoutP99 = data.metrics.logout_p99?.values['p(99)']?.toFixed(2) || 'N/A';
const refreshP99 = data.metrics.refresh_p99?.values['p(99)']?.toFixed(2) || 'N/A';
return {
'stdout': `\n=== Darkwatch Auth Load Test Results ===\n`,
'summary.json': JSON.stringify({
timestamp: new Date().toISOString(),
duration: DURATION,
targetRPS: TARGET_RPS,
thresholds: THRESHOLDS,
metrics: {
login: {
p99: data.metrics.login_p99?.values['p(99)']?.toFixed(2) || 'N/A',
p95: data.metrics.login_p99?.values['p(95)']?.toFixed(2) || 'N/A',
avg: data.metrics.login_p99?.values.avg?.toFixed(2) || 'N/A',
count: data.metrics.login_p99?.values.count || 0,
successRate: (data.metrics.login_success?.values.rate || 0) * 100 + '%',
},
logout: {
p99: data.metrics.logout_p99?.values['p(99)']?.toFixed(2) || 'N/A',
p95: data.metrics.logout_p99?.values['p(95)']?.toFixed(2) || 'N/A',
avg: data.metrics.logout_p99?.values.avg?.toFixed(2) || 'N/A',
count: data.metrics.logout_p99?.values.count || 0,
successRate: (data.metrics.logout_success?.values.rate || 0) * 100 + '%',
},
refresh: {
p99: data.metrics.refresh_p99?.values['p(99)']?.toFixed(2) || 'N/A',
p95: data.metrics.refresh_p99?.values['p(95)']?.toFixed(2) || 'N/A',
avg: data.metrics.refresh_p99?.values.avg?.toFixed(2) || 'N/A',
count: data.metrics.refresh_p99?.values.count || 0,
successRate: (data.metrics.refresh_success?.values.rate || 0) * 100 + '%',
},
},
passed: passed,
}, null, 2),
'stdout': `\n=== Darkwatch Auth Load Test Results ===\n` +
`Login P99: ${loginP99}ms (threshold: ${THRESHOLDS.login}ms)\n` +
`Logout P99: ${logoutP99}ms (threshold: ${THRESHOLDS.logout}ms)\n` +
`Refresh P99: ${refreshP99}ms (threshold: ${THRESHOLDS.refresh}ms)\n` +
`Overall: ${passed ? 'PASS' : 'FAIL'}\n`,
};
}

View File

@@ -31,20 +31,22 @@ echo ""
case "$SCENARIO" in
mixed)
k6 run darkwatch-auth.js \
--out json="$OUTPUT_DIR/results-${TIMESTAMP}.json" \
<<EOF
EOF
--summary-export "$OUTPUT_DIR/summary-${TIMESTAMP}.json" \
--out json="$OUTPUT_DIR/results-${TIMESTAMP}.json"
;;
login)
k6 run --scenario login_only darkwatch-auth.js \
--summary-export "$OUTPUT_DIR/summary-${TIMESTAMP}.json" \
--out json="$OUTPUT_DIR/results-${TIMESTAMP}.json"
;;
logout)
k6 run --scenario logout_only darkwatch-auth.js \
--summary-export "$OUTPUT_DIR/summary-${TIMESTAMP}.json" \
--out json="$OUTPUT_DIR/results-${TIMESTAMP}.json"
;;
refresh)
k6 run --scenario refresh_only darkwatch-auth.js \
--summary-export "$OUTPUT_DIR/summary-${TIMESTAMP}.json" \
--out json="$OUTPUT_DIR/results-${TIMESTAMP}.json"
;;
*)

View File

@@ -45,6 +45,4 @@ export const autoscaleMetric = new Trend('autoscale_vu_count');
export function recordAutoscaleMetric(vuCount) {
autoscaleMetric.add(vuCount);
}
return result;
}