Files
deeplx/tests/performance/load.test.ts
T
xixu-me 8afa94767e Initial repository setup and core files added
Add configuration, documentation, code of conduct, contributing guide, license, and README files. Set up .gitignore, coverage config, GitHub issue templates, pull request template, and initial source code, scripts, and tests for DeepLX optimized for Cloudflare Workers.
2025-07-27 02:09:25 +08:00

279 lines
7.4 KiB
TypeScript

/**
* Performance and load tests
*/
describe("Performance Tests", () => {
let mockEnv: Env;
beforeEach(() => {
mockEnv = createMockEnv();
});
afterEach(() => {
jest.clearAllMocks();
});
describe("Response time benchmarks", () => {
it("should respond to translation requests within acceptable time", async () => {
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: () =>
Promise.resolve({
result: {
texts: [{ text: "你好世界" }],
lang: "ZH",
},
id: 12345,
}),
});
const { query } = await import("../../src/lib/query");
const startTime = Date.now();
await query(
{
text: "Hello world",
source_lang: "en",
target_lang: "zh",
},
{ env: mockEnv }
);
const endTime = Date.now();
const responseTime = endTime - startTime;
// Should respond within 5 seconds for normal requests
expect(responseTime).toBeLessThan(5000);
});
it("should handle cache lookups efficiently", async () => {
const cachedEntry = {
data: "你好世界",
timestamp: Date.now(),
source_lang: "EN",
target_lang: "ZH",
id: 12345,
};
(mockEnv.CACHE_KV.get as jest.Mock).mockResolvedValue(
JSON.stringify(cachedEntry)
);
const { getCachedTranslation, generateCacheKey } = await import(
"../../src/lib/cache"
);
const startTime = Date.now();
const cacheKey = generateCacheKey("Hello world", "EN", "ZH");
await getCachedTranslation(cacheKey, mockEnv);
const endTime = Date.now();
const responseTime = endTime - startTime;
// Cache lookups should be very fast
expect(responseTime).toBeLessThan(100);
});
});
describe("Memory usage tests", () => {
it("should not leak memory during repeated operations", async () => {
const { clearMemoryCache } = await import("../../src/lib/cache");
// Simulate repeated cache operations
for (let i = 0; i < 100; i++) {
const { generateCacheKey } = await import("../../src/lib/cache");
generateCacheKey(`test text ${i}`, "EN", "ZH");
}
// Clear cache should not throw
expect(() => clearMemoryCache()).not.toThrow();
});
it("should handle large text inputs efficiently", async () => {
const { validateTextLength } = await import("../../src/lib/textUtils");
const largeText = "This is a test sentence. ".repeat(1000);
const startTime = Date.now();
const validation = validateTextLength(largeText);
const endTime = Date.now();
expect(validation.isValid).toBe(false);
expect(endTime - startTime).toBeLessThan(1000); // Should complete within 1 second
});
});
describe("Concurrent request handling", () => {
it("should handle multiple simultaneous requests", async () => {
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: () =>
Promise.resolve({
result: {
texts: [{ text: "你好世界" }],
lang: "ZH",
},
id: 12345,
}),
});
const { query } = await import("../../src/lib/query");
const concurrentRequests = 50;
const startTime = Date.now();
const promises = Array.from({ length: concurrentRequests }, (_, i) =>
query(
{
text: `Hello world ${i}`,
source_lang: "en",
target_lang: "zh",
},
{ env: mockEnv }
)
);
const results = await Promise.all(promises);
const endTime = Date.now();
// All requests should succeed
results.forEach((result) => {
expect(result.code).toBe(200);
});
// Should handle concurrent requests efficiently
const avgTimePerRequest = (endTime - startTime) / concurrentRequests;
expect(avgTimePerRequest).toBeLessThan(1000);
});
it("should handle rate limiting under load", async () => {
const { checkRateLimit } = await import("../../src/lib/rateLimit");
// Simulate rapid requests from same IP
const results = [];
for (let i = 0; i < 20; i++) {
const result = await checkRateLimit("192.168.1.1", mockEnv);
results.push(result);
}
// Should eventually hit rate limits
const allowedCount = results.filter((r) => r.allowed).length;
const deniedCount = results.filter((r) => !r.allowed).length;
expect(allowedCount).toBeGreaterThan(0);
// Depending on rate limit configuration, some might be denied
});
});
describe("Resource utilization", () => {
it("should handle proxy failover efficiently", async () => {
// Mock multiple proxy failures then success
global.fetch = jest
.fn()
.mockRejectedValueOnce(new Error("Proxy 1 failed"))
.mockRejectedValueOnce(new Error("Proxy 2 failed"))
.mockResolvedValueOnce({
ok: true,
json: () =>
Promise.resolve({
result: {
texts: [{ text: "你好世界" }],
lang: "ZH",
},
id: 12345,
}),
});
const { query } = await import("../../src/lib/query");
const startTime = Date.now();
const result = await query(
{
text: "Hello world",
source_lang: "en",
target_lang: "zh",
},
{ env: mockEnv }
);
const endTime = Date.now();
expect(result.code).toBe(200);
// Failover should not take too long
const failoverTime = endTime - startTime;
expect(failoverTime).toBeLessThan(10000);
});
});
describe("Stress tests", () => {
it("should handle rapid sequential requests", async () => {
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: () =>
Promise.resolve({
result: {
texts: [{ text: "你好世界" }],
lang: "ZH",
},
id: 12345,
}),
});
const { query } = await import("../../src/lib/query");
const requestCount = 100;
const results = [];
const startTime = Date.now();
for (let i = 0; i < requestCount; i++) {
const result = await query(
{
text: `Hello world ${i}`,
source_lang: "en",
target_lang: "zh",
},
{ env: mockEnv }
);
results.push(result);
}
const endTime = Date.now();
// All requests should succeed
results.forEach((result) => {
expect(result.code).toBe(200);
});
const totalTime = endTime - startTime;
const avgTimePerRequest = totalTime / requestCount;
// Should maintain reasonable performance under load
expect(avgTimePerRequest).toBeLessThan(500);
});
it("should handle large payload processing", async () => {
const { validateTextLength } = await import("../../src/lib/textUtils");
const largeText =
"This is a very long text that needs to be processed efficiently. ".repeat(
500
);
const startTime = Date.now();
const validation = validateTextLength(largeText);
expect(validation.isValid).toBe(false);
const endTime = Date.now();
// Large text processing should complete quickly
expect(endTime - startTime).toBeLessThan(1000);
});
});
});