PRIX / scripts /load-test.js
Rachit-Tw's picture
Upload 169 files
9284ad7 verified
Raw
History Blame Contribute Delete
6.01 kB
/**
* Load Test Configuration for PRIX
* Simulates 500 concurrent users hitting the webhook endpoint
*
* Prerequisites:
* npm install -g k6
* k6 login cloud (optional for trending)
*
* Usage:
* k6 run scripts/load-test.js
* k6 run --vus 500 --duration 60s scripts/load-test.js
* k6 run --stage rps:10-50:30s,rps:50-100:60s scripts/load-test.js
*/
import http from 'k6/http';
import { check, sleep, group } from 'k6';
import { Rate, Trend } from 'k6/metrics';
// Custom metrics
const errorRate = new Rate('errors');
const responseTime = new Trend('response_time');
const webhookSuccess = new Trend('webhook_success');
const healthCheckTime = new Trend('health_check_time');
// Test configuration
export const options = {
scenarios: {
// Warmup scenario
warmup: {
executor: 'ramping-arrival-rate',
duration: '30s',
preAllocatedVUs: 50,
maxVUs: 100,
stages: [
{ duration: '10s', target: 10 },
{ duration: '20s', target: 50 },
],
},
// Main load test - 500 concurrent users
load_test: {
executor: 'ramping-vus',
duration: '2m',
maxVUs: 500,
stages: [
{ duration: '30s', target: 100 },
{ duration: '30s', target: 250 },
{ duration: '30s', target: 500 },
{ duration: '30s', target: 500 }, // Hold at 500
{ duration: '30s', target: 0 }, // Ramp down
],
},
},
thresholds: {
http_req_duration: ['p(95)<5000'], // 95% of requests under 5s
http_req_failed: ['rate<0.1'], // Less than 10% failure
errors: ['rate<0.05'], // Less than 5% error rate
webhook_success: ['p(90)<10000'], // 90% of webhooks complete in 10s
},
};
// Test data generation
function generateMockGitHubPayload(prNumber) {
const timestamp = Date.now();
return {
action: 'opened',
number: prNumber,
pull_request: {
number: prNumber,
title: `Load test PR #${prNumber} - ${timestamp}`,
body: 'This is a load test pull request for performance testing',
state: 'open',
user: {
login: `loadtest-user-${prNumber % 100}`,
id: 1000 + (prNumber % 100),
},
base: {
ref: 'main',
sha: '136795cc20e35ffa9a345771e8eeaaf4bce69ae2',
},
head: {
ref: `feature/load-test-${prNumber}`,
sha: `${timestamp.toString(16)}`,
},
},
repository: {
id: 123456,
name: 'TEST-PRIX',
full_name: 'Rachit-Tiwari-7/TEST-PRIX',
owner: {
login: 'Rachit-Tiwari-7',
id: 789,
},
},
installation: {
id: 12345,
},
};
}
// Simulated PR file changes
function generateMockFileChanges() {
return [
{
filename: 'test-file.js',
status: 'modified',
additions: 5,
deletions: 2,
changes: 7,
patch: `@@ -1,3 +1,6 @@
const x = 1;
const y = 2;
+const z = 3;
+const w = 4;
function calculate() {
return x + y;
}
+function extra() { return z + w; }`,
},
{
filename: 'calc.py',
status: 'modified',
additions: 2,
deletions: 1,
changes: 3,
patch: `@@ -1,5 +1,6 @@
if __name__ == "__main__":
print(f"Addition: {add(10, 5)}")
- print(f"Division: {divide(10, 5)}")
+ print(f"Division: {divide(10, 5)}")
+ print("Load test line")
result = add(5, 3)`,
},
];
}
// Default function - main test loop
export default function () {
const baseUrl = __ENV.TARGET_URL || 'http://localhost:7860';
const githubToken = __ENV.GITHUB_TOKEN || 'test-token';
// Health check
group('Health Check', () => {
const healthStart = Date.now();
const healthRes = http.get(`${baseUrl}/ping`, {
headers: { 'Content-Type': 'application/json' },
});
healthCheckTime.add(Date.now() - healthStart);
check(healthRes, {
'health check status is 200': (r) => r.status === 200,
'health check has correct response': (r) => r.body.includes('pong') || r.status === 200,
});
});
// Simulate webhook payload
group('Webhook Delivery', () => {
const prNumber = 10000 + Math.floor(Math.random() * 1000);
const payload = generateMockGitHubPayload(prNumber);
const files = generateMockFileChanges();
// Mock GitHub API responses
const mockGitHubResponses = {
'repos/compareCommits': {
files: files,
commits: [{ sha: 'commit-1' }, { sha: 'commit-2' }],
},
'repos/getContent': {
content: Buffer.from('const existing = true;').toString('base64'),
encoding: 'base64',
},
};
const webhookStart = Date.now();
// Note: In real load test against production, you'd hit the actual webhook endpoint
// For local testing, we simulate the webhook processing
const webhookRes = http.post(
`${baseUrl}/api/github/webhooks`,
JSON.stringify(payload),
{
headers: {
'Content-Type': 'application/json',
'X-GitHub-Event': 'pull_request',
'X-GitHub-Delivery': `${Date.now()}`,
'X-Hub-Signature-256': 'sha256=test-signature',
},
}
);
webhookSuccess.add(Date.now() - webhookStart);
responseTime.add(Date.now() - webhookStart);
const isSuccess = check(webhookRes, {
'webhook status is 200': (r) => r.status === 200,
'webhook response time < 5s': (r) => r.timings.duration < 5000,
});
errorRate.add(!isSuccess);
});
// Random think time between requests (1-3 seconds)
sleep(Math.random() * 2 + 1);
}
// Setup function - runs once before test
export function setup() {
console.log('Starting PRIX Load Test');
console.log(`Target URL: ${__ENV.TARGET_URL || 'http://localhost:7860'}`);
console.log('Simulating 500 concurrent users...');
return { startTime: Date.now() };
}
// Teardown function - runs once after test
export function teardown(data) {
console.log('Load Test Complete');
console.log(`Total Duration: ${(Date.now() - data.startTime) / 1000}s`);
}