Files
xget/test/performance.test.js
T
xixu-me f66247c846 Migrate issue templates to YAML and add contribution docs
Replaced Markdown issue templates with structured YAML templates for bug reports, feature requests, performance issues, deployment help, and platform support. Added .prettierrc.json and .prettierignore for code formatting, a detailed CONTRIBUTING.md, and a pull request template. Updated CODE_OF_CONDUCT.md and README.md to reference new contribution guidelines. Added ESLint config, test scripts, and initial test files to improve project maintainability and onboarding.
2025-07-24 21:05:13 +08:00

231 lines
6.8 KiB
JavaScript

import { beforeEach, describe, expect, it } from 'vitest';
// Mock PerformanceMonitor class for testing
class MockPerformanceMonitor {
constructor() {
this.startTime = Date.now();
this.marks = new Map();
}
mark(name) {
if (this.marks.has(name)) {
console.warn(`Mark with name ${name} already exists.`);
}
this.marks.set(name, Date.now() - this.startTime);
}
getMetrics() {
return Object.fromEntries(this.marks.entries());
}
}
describe('Performance Monitoring', () => {
let monitor;
beforeEach(() => {
monitor = new MockPerformanceMonitor();
});
describe('PerformanceMonitor Class', () => {
it('should initialize with start time', () => {
expect(monitor.startTime).toBeDefined();
expect(typeof monitor.startTime).toBe('number');
});
it('should create timing marks', () => {
monitor.mark('test-mark');
const metrics = monitor.getMetrics();
expect(metrics).toHaveProperty('test-mark');
expect(typeof metrics['test-mark']).toBe('number');
});
it('should handle multiple marks', () => {
monitor.mark('mark1');
monitor.mark('mark2');
monitor.mark('mark3');
const metrics = monitor.getMetrics();
expect(Object.keys(metrics)).toHaveLength(3);
expect(metrics).toHaveProperty('mark1');
expect(metrics).toHaveProperty('mark2');
expect(metrics).toHaveProperty('mark3');
});
it('should warn on duplicate mark names', () => {
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
monitor.mark('duplicate');
monitor.mark('duplicate');
expect(consoleSpy).toHaveBeenCalledWith('Mark with name duplicate already exists.');
consoleSpy.mockRestore();
});
it('should return metrics as plain object', () => {
monitor.mark('test');
const metrics = monitor.getMetrics();
expect(metrics).toBeTypeOf('object');
expect(Array.isArray(metrics)).toBe(false);
});
it('should track elapsed time correctly', async () => {
monitor.mark('start');
// Wait a small amount of time
await new Promise(resolve => setTimeout(resolve, 10));
monitor.mark('end');
const metrics = monitor.getMetrics();
expect(metrics.end).toBeGreaterThan(metrics.start);
});
});
describe('Performance Metrics Validation', () => {
it('should produce serializable metrics', () => {
monitor.mark('request-start');
monitor.mark('proxy-start');
monitor.mark('proxy-end');
monitor.mark('request-end');
const metrics = monitor.getMetrics();
expect(() => JSON.stringify(metrics)).not.toThrow();
});
it('should have reasonable timing values', () => {
monitor.mark('test-mark');
const metrics = monitor.getMetrics();
const timing = metrics['test-mark'];
// Should be a positive number and reasonable (less than 1 second for this test)
expect(timing).toBeGreaterThanOrEqual(0);
expect(timing).toBeLessThan(1000);
});
it('should maintain chronological order', async () => {
monitor.mark('first');
await new Promise(resolve => setTimeout(resolve, 5));
monitor.mark('second');
await new Promise(resolve => setTimeout(resolve, 5));
monitor.mark('third');
const metrics = monitor.getMetrics();
expect(metrics.first).toBeLessThan(metrics.second);
expect(metrics.second).toBeLessThan(metrics.third);
});
});
describe('Common Performance Scenarios', () => {
it('should track request lifecycle', () => {
// Simulate typical request flow
monitor.mark('request-received');
monitor.mark('validation-complete');
monitor.mark('proxy-start');
monitor.mark('proxy-response');
monitor.mark('response-sent');
const metrics = monitor.getMetrics();
expect(metrics).toHaveProperty('request-received');
expect(metrics).toHaveProperty('validation-complete');
expect(metrics).toHaveProperty('proxy-start');
expect(metrics).toHaveProperty('proxy-response');
expect(metrics).toHaveProperty('response-sent');
});
it('should track cache operations', () => {
monitor.mark('cache-check-start');
monitor.mark('cache-miss');
monitor.mark('upstream-request');
monitor.mark('cache-store');
const metrics = monitor.getMetrics();
expect(metrics).toHaveProperty('cache-check-start');
expect(metrics).toHaveProperty('cache-miss');
expect(metrics).toHaveProperty('upstream-request');
expect(metrics).toHaveProperty('cache-store');
});
it('should track error scenarios', () => {
monitor.mark('request-start');
monitor.mark('error-occurred');
monitor.mark('error-handled');
const metrics = monitor.getMetrics();
expect(metrics).toHaveProperty('request-start');
expect(metrics).toHaveProperty('error-occurred');
expect(metrics).toHaveProperty('error-handled');
});
});
describe('Performance Thresholds', () => {
it('should identify slow operations', () => {
monitor.mark('operation-start');
// Simulate slow operation
const slowTiming = 5000; // 5 seconds
monitor.marks.set('operation-end', slowTiming);
const metrics = monitor.getMetrics();
const operationTime = metrics['operation-end'] - (metrics['operation-start'] || 0);
// Should identify as slow (> 1 second)
expect(operationTime).toBeGreaterThan(1000);
});
it('should identify fast operations', () => {
monitor.mark('fast-operation');
const metrics = monitor.getMetrics();
const timing = metrics['fast-operation'];
// Should be fast (< 100ms for this test)
expect(timing).toBeLessThan(100);
});
});
describe('Memory and Resource Usage', () => {
it('should not leak memory with many marks', () => {
const initialSize = monitor.marks.size;
// Add many marks
for (let i = 0; i < 1000; i++) {
monitor.mark(`mark-${i}`);
}
expect(monitor.marks.size).toBe(initialSize + 1000);
// Clear marks (if such method existed)
monitor.marks.clear();
expect(monitor.marks.size).toBe(0);
});
it('should handle concurrent mark operations', () => {
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(
new Promise(resolve => {
setTimeout(() => {
monitor.mark(`concurrent-${i}`);
resolve();
}, Math.random() * 10);
})
);
}
return Promise.all(promises).then(() => {
const metrics = monitor.getMetrics();
expect(Object.keys(metrics)).toHaveLength(10);
});
});
});
});