test: split stress test into streaming and non-streaming variants
- Rename stress-test.cjs to stress-test-normal.cjs (non-streaming) - Add stress-test-streaming.cjs for SSE streaming tests - Both tests verify rate limit handling under concurrent load Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
93
tests/stress-test-normal.cjs
Normal file
93
tests/stress-test-normal.cjs
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Stress Test - Send multiple concurrent requests to test rate limit handling
|
||||
*
|
||||
* Usage: node tests/stress-test.cjs [count] [model]
|
||||
* Example: node tests/stress-test.cjs 10 gemini-3-flash
|
||||
*/
|
||||
|
||||
const BASE_URL = process.env.ANTHROPIC_BASE_URL || 'http://localhost:8080';
|
||||
|
||||
const count = parseInt(process.argv[2]) || 8;
|
||||
const model = process.argv[3] || 'gemini-3-flash';
|
||||
|
||||
async function sendRequest(id) {
|
||||
const startTime = Date.now();
|
||||
try {
|
||||
const response = await fetch(`${BASE_URL}/v1/messages`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-api-key': 'test',
|
||||
'anthropic-version': '2023-06-01'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: model,
|
||||
max_tokens: 100,
|
||||
messages: [
|
||||
{ role: 'user', content: `Request ${id}: Say "Hello ${id}" and nothing else.` }
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
const elapsed = Date.now() - startTime;
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.log(`[${id}] ❌ ${response.status} after ${elapsed}ms: ${errorText.substring(0, 100)}`);
|
||||
return { id, success: false, status: response.status, elapsed };
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const text = data.content?.[0]?.text?.substring(0, 50) || 'No text';
|
||||
console.log(`[${id}] ✅ 200 after ${elapsed}ms: "${text}..."`);
|
||||
return { id, success: true, status: 200, elapsed };
|
||||
} catch (error) {
|
||||
const elapsed = Date.now() - startTime;
|
||||
console.log(`[${id}] ❌ Error after ${elapsed}ms: ${error.message}`);
|
||||
return { id, success: false, error: error.message, elapsed };
|
||||
}
|
||||
}
|
||||
|
||||
async function runStressTest() {
|
||||
console.log(`\n🚀 Stress Test: Sending ${count} concurrent requests to ${model}\n`);
|
||||
console.log(`Target: ${BASE_URL}/v1/messages\n`);
|
||||
console.log('─'.repeat(70));
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
// Send all requests concurrently
|
||||
const promises = [];
|
||||
for (let i = 1; i <= count; i++) {
|
||||
promises.push(sendRequest(i));
|
||||
}
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
|
||||
const totalElapsed = Date.now() - startTime;
|
||||
console.log('─'.repeat(70));
|
||||
|
||||
// Summary
|
||||
const successful = results.filter(r => r.success).length;
|
||||
const failed = results.filter(r => !r.success).length;
|
||||
const avgElapsed = Math.round(results.reduce((sum, r) => sum + r.elapsed, 0) / results.length);
|
||||
|
||||
console.log(`\n📊 Summary:`);
|
||||
console.log(` Total time: ${totalElapsed}ms`);
|
||||
console.log(` Successful: ${successful}/${count}`);
|
||||
console.log(` Failed: ${failed}/${count}`);
|
||||
console.log(` Avg response time: ${avgElapsed}ms`);
|
||||
|
||||
if (failed > 0) {
|
||||
const errors = results.filter(r => !r.success);
|
||||
const statusCounts = {};
|
||||
errors.forEach(e => {
|
||||
const key = e.status || 'network';
|
||||
statusCounts[key] = (statusCounts[key] || 0) + 1;
|
||||
});
|
||||
console.log(` Error breakdown: ${JSON.stringify(statusCounts)}`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
runStressTest().catch(console.error);
|
||||
Reference in New Issue
Block a user