diff --git a/load-tests/darkwatch-auth/.gitignore b/load-tests/darkwatch-auth/.gitignore new file mode 100644 index 0000000..08780e5 --- /dev/null +++ b/load-tests/darkwatch-auth/.gitignore @@ -0,0 +1,5 @@ +# k6 load test results +results/ + +# Local environment overrides +.env diff --git a/load-tests/darkwatch-auth/darkwatch-auth.js b/load-tests/darkwatch-auth/darkwatch-auth.js index e0f5b9f..a0831c9 100644 --- a/load-tests/darkwatch-auth/darkwatch-auth.js +++ b/load-tests/darkwatch-auth/darkwatch-auth.js @@ -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`, }; } diff --git a/load-tests/darkwatch-auth/run.sh b/load-tests/darkwatch-auth/run.sh index 40028b4..ec96980 100755 --- a/load-tests/darkwatch-auth/run.sh +++ b/load-tests/darkwatch-auth/run.sh @@ -31,20 +31,22 @@ echo "" case "$SCENARIO" in mixed) k6 run darkwatch-auth.js \ - --out json="$OUTPUT_DIR/results-${TIMESTAMP}.json" \ - <