import { expect, tap } from '@git.zone/tstest/tapbundle'; import { LogDeduplicator } from '../ts/core/utils/log-deduplicator.js'; let deduplicator: LogDeduplicator; tap.test('Setup log deduplicator', async () => { deduplicator = new LogDeduplicator(1000); // 1 second flush interval for testing }); tap.test('Connection rejection deduplication', async (tools) => { // Simulate multiple connection rejections for (let i = 0; i < 10; i++) { deduplicator.log( 'connection-rejected', 'warn', 'Connection rejected', { reason: 'global-limit', component: 'test' }, 'global-limit' ); } for (let i = 0; i < 5; i++) { deduplicator.log( 'connection-rejected', 'warn', 'Connection rejected', { reason: 'route-limit', component: 'test' }, 'route-limit' ); } // Force flush deduplicator.flush('connection-rejected'); // The logs should have been aggregated // (Can't easily test the actual log output, but we can verify the mechanism works) expect(deduplicator).toBeInstanceOf(LogDeduplicator); }); tap.test('IP rejection deduplication', async (tools) => { // Simulate rejections from multiple IPs const ips = ['192.168.1.100', '192.168.1.101', '192.168.1.100', '10.0.0.1']; const reasons = ['per-ip-limit', 'rate-limit', 'per-ip-limit', 'global-limit']; for (let i = 0; i < ips.length; i++) { deduplicator.log( 'ip-rejected', 'warn', `Connection rejected from ${ips[i]}`, { remoteIP: ips[i], reason: reasons[i] }, ips[i] ); } // Add more rejections from the same IP for (let i = 0; i < 20; i++) { deduplicator.log( 'ip-rejected', 'warn', 'Connection rejected from 192.168.1.100', { remoteIP: '192.168.1.100', reason: 'rate-limit' }, '192.168.1.100' ); } // Force flush deduplicator.flush('ip-rejected'); // Verify the deduplicator exists and works expect(deduplicator).toBeInstanceOf(LogDeduplicator); }); tap.test('Connection cleanup deduplication', async (tools) => { // Simulate various cleanup events const reasons = ['normal', 'timeout', 'error', 'normal', 'zombie']; for (const reason of reasons) { for (let i = 0; i < 5; i++) { deduplicator.log( 'connection-cleanup', 'info', `Connection cleanup: ${reason}`, { connectionId: `conn-${i}`, reason }, reason ); } } // Wait for automatic flush await tools.delayFor(1500); // Verify deduplicator is working expect(deduplicator).toBeInstanceOf(LogDeduplicator); }); tap.test('Automatic periodic flush', async (tools) => { // Add some events deduplicator.log('test-event', 'info', 'Test message', {}, 'test'); // Wait for automatic flush (should happen within 2x flush interval = 2 seconds) await tools.delayFor(2500); // Events should have been flushed automatically expect(deduplicator).toBeInstanceOf(LogDeduplicator); }); tap.test('Cleanup deduplicator', async () => { deduplicator.cleanup(); expect(deduplicator).toBeInstanceOf(LogDeduplicator); }); tap.start();