@making-sense/antlr-editor
Version:
ANTLR Typescript editor
222 lines (180 loc) • 7.58 kB
text/typescript
import { describe, it, expect } from "vitest";
// Test performance scenarios without Monaco Editor
describe("Performance Tests", () => {
describe("Timing Measurements", () => {
it("should measure function execution time", () => {
const start = performance.now();
// Simulate some work
let sum = 0;
for (let i = 0; i < 1000; i++) {
sum += i;
}
const end = performance.now();
const duration = end - start;
expect(duration).toBeGreaterThanOrEqual(0);
expect(sum).toBe(499500); // Sum of 0 to 999
});
it("should measure async operations", async () => {
const start = performance.now();
await new Promise(resolve => setTimeout(resolve, 10));
const end = performance.now();
const duration = end - start;
// Allow for timing variations in CI environments (GitHub Actions can be faster)
// The actual delay is 10ms, but measurement can be slightly less due to timer precision
expect(duration).toBeGreaterThanOrEqual(8);
});
});
describe("Memory Usage", () => {
it("should check memory availability", () => {
if (performance.memory) {
expect(performance.memory.usedJSHeapSize).toBeGreaterThan(0);
expect(performance.memory.totalJSHeapSize).toBeGreaterThan(0);
expect(performance.memory.jsHeapSizeLimit).toBeGreaterThan(0);
}
});
it("should simulate memory cleanup", () => {
const resources = {
editor: { disposed: false },
providers: { disposed: false },
listeners: { disposed: false }
};
// Simulate cleanup
resources.editor.disposed = true;
resources.providers.disposed = true;
resources.listeners.disposed = true;
expect(resources.editor.disposed).toBe(true);
expect(resources.providers.disposed).toBe(true);
expect(resources.listeners.disposed).toBe(true);
});
});
describe("Debouncing", () => {
it("should simulate debounced operations", async () => {
let callCount = 0;
const debounce = (fn: () => void, delay: number) => {
let timeoutId: NodeJS.Timeout;
return () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(fn, delay);
};
};
const debouncedFn = debounce(() => {
callCount++;
}, 100);
// Call multiple times rapidly
debouncedFn();
debouncedFn();
debouncedFn();
// Should not have been called yet
expect(callCount).toBe(0);
// Wait for debounce delay
await new Promise(resolve => setTimeout(resolve, 150));
// Should have been called only once
expect(callCount).toBe(1);
});
it("should handle rapid script changes", () => {
const changes = [];
const maxChanges = 100;
for (let i = 0; i < maxChanges; i++) {
changes.push(`script${i}`);
}
expect(changes).toHaveLength(maxChanges);
expect(changes[0]).toBe("script0");
expect(changes[maxChanges - 1]).toBe(`script${maxChanges - 1}`);
});
});
describe("Large Content Handling", () => {
it("should handle large script content", () => {
const largeScript = "a := 1;\n".repeat(1000);
expect(largeScript.length).toBeGreaterThan(1000);
const lines = largeScript.split("\n");
expect(lines).toHaveLength(1001); // 1000 lines + 1 empty line
// Simulate processing
const processedLines = lines.filter(line => line.trim().length > 0);
expect(processedLines).toHaveLength(1000);
});
it("should handle large variables object", () => {
const variables = {};
for (let i = 0; i < 1000; i++) {
variables[`var${i}`] = {
type: i % 2 === 0 ? "STRING" : "INTEGER",
role: i % 3 === 0 ? "IDENTIFIER" : "MEASURE"
};
}
expect(Object.keys(variables)).toHaveLength(1000);
expect(variables["var0"].type).toBe("STRING");
expect(variables["var1"].type).toBe("INTEGER");
});
});
describe("Concurrent Operations", () => {
it("should handle concurrent operations", async () => {
const operations = [];
const numOperations = 50;
for (let i = 0; i < numOperations; i++) {
operations.push(
new Promise(resolve => {
setTimeout(() => {
resolve(`operation${i}`);
}, i * 2);
})
);
}
const results = await Promise.all(operations);
expect(results).toHaveLength(numOperations);
expect(results[0]).toBe("operation0");
expect(results[numOperations - 1]).toBe(`operation${numOperations - 1}`);
});
it("should handle rapid mount/unmount cycles", () => {
let mountCount = 0;
let unmountCount = 0;
const mount = () => {
mountCount++;
};
const unmount = () => {
unmountCount++;
};
// Simulate rapid cycles
for (let i = 0; i < 10; i++) {
mount();
unmount();
}
expect(mountCount).toBe(10);
expect(unmountCount).toBe(10);
});
});
describe("Performance Marks", () => {
it("should create performance marks", () => {
const markName = "test-mark";
performance.mark(markName);
// Check if mark was created (may not work in test environment)
const marks = performance.getEntriesByName(markName);
// In test environment, marks might not be available
if (marks.length > 0) {
expect(marks[0].name).toBe(markName);
} else {
// Just verify the function doesn't throw
expect(() => performance.mark(markName)).not.toThrow();
}
});
it("should measure performance between marks", () => {
const startMark = "start-mark";
const endMark = "end-mark";
const measureName = "test-measure";
performance.mark(startMark);
// Simulate some work
for (let i = 0; i < 100; i++) {
// Simulate work without storing result
void (i * 2);
}
performance.mark(endMark);
performance.measure(measureName, startMark, endMark);
const measures = performance.getEntriesByName(measureName);
// In test environment, measures might not be available
if (measures.length > 0) {
expect(measures[0].name).toBe(measureName);
} else {
// Just verify the functions don't throw
expect(() => performance.measure(measureName, startMark, endMark)).not.toThrow();
}
});
});
});