rate-limit-standalone-test.jsā¢5.87 kB
/**
* Test Rate Limiting Implementation - Standalone
*/
import { RateLimiter } from '../lib/security/RateLimiter.js';
async function testRateLimiterStandalone() {
console.log('š Testing Rate Limiter - Standalone');
console.log('===================================');
// Test 1: Basic functionality
console.log('ā Testing instantiation...');
const rateLimiter = new RateLimiter({
maxRequests: 10,
windowMs: 5000,
burstLimit: 3,
burstWindowMs: 500
});
console.log('ā
RateLimiter instantiated successfully');
// Test 2: Allow normal requests
console.log('ā Testing normal request flow...');
let result = await rateLimiter.isAllowed('client1', 'echo', { args: ['hello'] });
console.log('ā
Normal request allowed:', result.allowed);
console.log(' - Remaining requests:', result.remaining);
console.log(' - Reset time:', new Date(result.resetTime));
// Test 3: Burst protection
console.log('ā Testing burst protection...');
const promises = [];
for (let i = 0; i < 5; i++) {
promises.push(rateLimiter.isAllowed('burst-client', 'test', {}));
}
const results = await Promise.all(promises);
const allowedCount = results.filter(r => r.allowed).length;
const deniedCount = results.filter(r => !r.allowed).length;
console.log(`ā
Burst test: ${allowedCount} allowed, ${deniedCount} denied`);
// Test 4: Rate limit enforcement
console.log('ā Testing rate limit enforcement...');
const rapidClient = 'rapid-client';
let allowedRequests = 0;
let deniedRequests = 0;
for (let i = 0; i < 15; i++) {
const result = await rateLimiter.isAllowed(rapidClient, 'test', {});
if (result.allowed) {
allowedRequests++;
} else {
deniedRequests++;
if (deniedRequests === 1) {
console.log(' - First denial reason:', result.reason);
console.log(' - Retry after:', result.retryAfter, 'ms');
}
}
await new Promise(resolve => setTimeout(resolve, 50));
}
console.log(`ā
Rate limit test: ${allowedRequests} allowed, ${deniedRequests} denied`);
// Test 5: Suspicious activity detection
console.log('ā Testing suspicious activity detection...');
const suspiciousClient = 'suspicious-client';
let suspiciousBlocked = false;
for (let i = 0; i < 30; i++) {
const result = await rateLimiter.isAllowed(suspiciousClient, 'test', {});
if (!result.allowed && result.reason === 'SUSPICIOUS_ACTIVITY') {
console.log('ā
Suspicious activity detected at request', i + 1);
suspiciousBlocked = true;
break;
}
}
if (!suspiciousBlocked) {
console.log('ā ļø Suspicious activity not detected (might need adjustment)');
}
// Test 6: Client isolation
console.log('ā Testing client isolation...');
const isolatedResult = await rateLimiter.isAllowed('isolated-client', 'test', {});
console.log('ā
Isolated client not affected:', isolatedResult.allowed);
// Test 7: Statistics
console.log('ā Testing statistics...');
const stats = rateLimiter.getStats();
console.log('ā
Statistics available:');
console.log(' - Active clients:', stats.activeClients);
console.log(' - Blocked clients:', stats.blockedClients);
console.log(' - Suspicious clients:', stats.suspiciousClients);
console.log(' - Rate limit config:', stats.rateLimitConfig);
// Test 8: Error handling for invalid inputs
console.log('ā Testing error handling...');
try {
await rateLimiter.isAllowed(null, 'test', {});
console.log('ā ļø Null client ID should be handled gracefully');
} catch (error) {
console.log('ā
Error handling works for invalid inputs');
}
// Test 9: Window reset behavior
console.log('ā Testing window reset behavior...');
const resetClient = 'reset-client';
await rateLimiter.isAllowed(resetClient, 'test', {});
console.log(' - Waiting for partial window reset...');
await new Promise(resolve => setTimeout(resolve, 1000));
const afterWaitResult = await rateLimiter.isAllowed(resetClient, 'test', {});
console.log('ā
Window reset behavior working:', afterWaitResult.allowed);
// Cleanup
rateLimiter.destroy();
console.log('ā
RateLimiter cleanup completed');
return true;
}
async function testRateLimiterConfiguration() {
console.log('\nš§ Testing Rate Limiter Configuration');
console.log('====================================');
// Test different configurations
const configs = [
{ name: 'Strict', maxRequests: 5, windowMs: 1000, burstLimit: 1 },
{ name: 'Moderate', maxRequests: 20, windowMs: 5000, burstLimit: 5 },
{ name: 'Lenient', maxRequests: 100, windowMs: 60000, burstLimit: 20 }
];
for (const config of configs) {
console.log(`ā Testing ${config.name} configuration...`);
const limiter = new RateLimiter(config);
let allowed = 0;
for (let i = 0; i < config.burstLimit + 2; i++) {
const result = await limiter.isAllowed('test', 'cmd', {});
if (result.allowed) allowed++;
}
console.log(`ā
${config.name}: ${allowed} requests allowed of ${config.burstLimit + 2} attempted`);
limiter.destroy();
}
return true;
}
async function runAllTests() {
try {
console.log('š Starting Rate Limiter Standalone Tests\n');
await testRateLimiterStandalone();
await testRateLimiterConfiguration();
console.log('\nš Test Summary:');
console.log('ā
All rate limiter tests passed!');
console.log('š Rate limiting implementation is working correctly');
return true;
} catch (error) {
console.error('ā Tests failed:', error);
console.error(error.stack);
return false;
}
}
// Run tests if called directly
if (import.meta.url === `file://${process.argv[1]}`) {
runAllTests().then(success => {
process.exit(success ? 0 : 1);
});
}
export { runAllTests };