Files
aida_front/src/component/Canvas/CanvasEditor/tests/liquifyIntegrationTests.js

481 lines
12 KiB
JavaScript
Raw Normal View History

2025-06-18 11:05:23 +08:00
/**
* 液化功能集成测试
* 用于在浏览器环境中测试完整的液化工作流程
*/
import { LiquifyCPUManager } from "../managers/liquify/LiquifyCPUManager.js";
import { LiquifyWebGLManager } from "../managers/liquify/LiquifyWebGLManager.js";
import { LiquifyRealTimeUpdater } from "../managers/liquify/LiquifyRealTimeUpdater.js";
import { EnhancedLiquifyManager } from "../managers/liquify/EnhancedLiquifyManager.js";
// 集成测试结果
let testResults = {
totalTests: 0,
passedTests: 0,
failedTests: 0,
errors: [],
};
/**
* 创建测试图像数据
*/
function createTestImageData(width = 100, height = 100) {
const imageData = new ImageData(width, height);
const data = imageData.data;
// 创建一个简单的渐变图案用于测试
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const index = (y * width + x) * 4;
data[index] = (x / width) * 255; // Red
data[index + 1] = (y / height) * 255; // Green
data[index + 2] = 128; // Blue
data[index + 3] = 255; // Alpha
}
}
return imageData;
}
/**
* 创建测试Canvas
*/
function createTestCanvas(width = 200, height = 200) {
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
return canvas;
}
/**
* 创建模拟Fabric对象
*/
function createMockFabricObject(imageData) {
return {
left: 50,
top: 50,
width: imageData.width,
height: imageData.height,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
_element: null,
calcTransformMatrix: function () {
return [this.scaleX, 0, 0, this.scaleY, this.left, this.top];
},
set: function (props) {
Object.assign(this, props);
},
};
}
/**
* 运行单个测试
*/
async function runTest(testName, testFunction) {
testResults.totalTests++;
try {
console.log(`🧪 运行测试: ${testName}`);
await testFunction();
testResults.passedTests++;
console.log(`✅ 测试通过: ${testName}`);
} catch (error) {
testResults.failedTests++;
testResults.errors.push({ testName, error: error.message });
console.error(`❌ 测试失败: ${testName}`, error);
}
}
/**
* 测试CPU管理器基本功能
*/
async function testCPUManagerBasics() {
const manager = new LiquifyCPUManager();
const testImageData = createTestImageData();
// 初始化
manager.initialize(testImageData);
// 设置参数
manager.setParams({
size: 50,
pressure: 0.5,
distortion: 0.3,
power: 0.8,
});
// 设置模式
manager.setMode("push");
// 应用变形
const result = manager.applyDeformation(50, 50);
if (
!result ||
result.width !== testImageData.width ||
result.height !== testImageData.height
) {
throw new Error("CPU管理器变形结果无效");
}
// 测试不同模式
const modes = [
"push",
"clockwise",
"counterclockwise",
"pinch",
"expand",
"reconstruct",
];
for (const mode of modes) {
manager.setMode(mode);
const modeResult = manager.applyDeformation(25, 25);
if (!modeResult) {
throw new Error(`模式 ${mode} 变形失败`);
}
}
}
/**
* 测试WebGL管理器基本功能
*/
async function testWebGLManagerBasics() {
const manager = new LiquifyWebGLManager();
const testImageData = createTestImageData();
try {
// 初始化
manager.initialize(testImageData);
// 检查WebGL是否可用
if (!manager.initialized) {
console.warn("WebGL不可用跳过WebGL测试");
return;
}
// 设置参数
manager.setParams({
size: 50,
pressure: 0.5,
distortion: 0.3,
power: 0.8,
});
// 设置模式
manager.setMode("push");
// 应用变形
const result = manager.applyDeformation(50, 50);
if (
!result ||
result.width !== testImageData.width ||
result.height !== testImageData.height
) {
throw new Error("WebGL管理器变形结果无效");
}
} catch (error) {
if (error.message.includes("WebGL")) {
console.warn("WebGL不支持跳过WebGL测试");
return;
}
throw error;
}
}
/**
* 测试实时更新器功能
*/
async function testRealTimeUpdater() {
const canvas = createTestCanvas();
const testImageData = createTestImageData();
const mockFabricObject = createMockFabricObject(testImageData);
// 模拟fabric Canvas
const fabricCanvas = {
getObjects: () => [mockFabricObject],
remove: () => {},
insertAt: () => {},
renderAll: () => {},
};
const updater = new LiquifyRealTimeUpdater(fabricCanvas);
// 设置目标对象
updater.setTargetObject(mockFabricObject);
// 测试快速更新
await updater.updateImage(testImageData, true);
// 测试完整更新
await updater.updateImage(testImageData, false);
// 测试待处理更新
updater.pendingImageData = testImageData;
await updater.processPendingUpdates();
// 清理
updater.dispose();
}
/**
* 测试增强液化管理器
*/
async function testEnhancedLiquifyManager() {
const manager = new EnhancedLiquifyManager();
const testImageData = createTestImageData();
const mockFabricObject = createMockFabricObject(testImageData);
// 初始化
const result = await manager.prepareForLiquify(mockFabricObject);
if (!result || !result.originalImageData) {
throw new Error("增强液化管理器初始化失败");
}
// 设置参数
manager.setParams({
size: 50,
pressure: 0.5,
distortion: 0.3,
power: 0.8,
});
// 应用液化
const liquifyResult = await manager.applyLiquify(
mockFabricObject,
"push",
{ size: 50, pressure: 0.5, distortion: 0.3, power: 0.8 },
50,
50
);
if (!liquifyResult) {
throw new Error("液化应用失败");
}
}
/**
* 测试坐标转换准确性
*/
async function testCoordinateConversion() {
const testImageData = createTestImageData(200, 200);
const mockFabricObject = createMockFabricObject(testImageData);
// 测试不同的缩放情况
const testCases = [
{ scaleX: 1, scaleY: 1, flipX: false, flipY: false },
{ scaleX: 2, scaleY: 2, flipX: false, flipY: false },
{ scaleX: 0.5, scaleY: 0.5, flipX: false, flipY: false },
{ scaleX: 1, scaleY: 1, flipX: true, flipY: false },
{ scaleX: 1, scaleY: 1, flipX: false, flipY: true },
];
for (const testCase of testCases) {
Object.assign(mockFabricObject, testCase);
// 模拟坐标转换函数(简化版)
const fabricX = 100,
fabricY = 100;
// 创建变换矩阵模拟
const transform = mockFabricObject.calcTransformMatrix();
// 基本的坐标边界检查
const localX = (fabricX - mockFabricObject.left) / mockFabricObject.scaleX;
const localY = (fabricY - mockFabricObject.top) / mockFabricObject.scaleY;
if (
localX < -mockFabricObject.width / 2 ||
localX > mockFabricObject.width / 2 ||
localY < -mockFabricObject.height / 2 ||
localY > mockFabricObject.height / 2
) {
// 坐标在对象外部,这是正常情况
continue;
}
// 转换到图像坐标
let imageX =
(localX + mockFabricObject.width / 2) *
(testImageData.width / mockFabricObject.width);
let imageY =
(localY + mockFabricObject.height / 2) *
(testImageData.height / mockFabricObject.height);
// 处理翻转
if (mockFabricObject.flipX) {
imageX = testImageData.width - imageX;
}
if (mockFabricObject.flipY) {
imageY = testImageData.height - imageY;
}
// 验证结果在合理范围内
if (
imageX < 0 ||
imageX >= testImageData.width ||
imageY < 0 ||
imageY >= testImageData.height
) {
throw new Error(`坐标转换结果超出图像范围: (${imageX}, ${imageY})`);
}
}
}
/**
* 测试性能表现
*/
async function testPerformance() {
const manager = new LiquifyCPUManager();
const testImageData = createTestImageData(400, 400); // 更大的图像
manager.initialize(testImageData);
manager.setParams({
size: 50,
pressure: 0.5,
distortion: 0.3,
power: 0.8,
});
manager.setMode("push");
// 测试多次操作的性能
const startTime = performance.now();
const operationCount = 100;
for (let i = 0; i < operationCount; i++) {
const x = Math.random() * testImageData.width;
const y = Math.random() * testImageData.height;
manager.applyDeformation(x, y);
}
const endTime = performance.now();
const totalTime = endTime - startTime;
const avgTime = totalTime / operationCount;
console.log(
`性能测试结果: ${operationCount} 次操作,总耗时 ${totalTime.toFixed(
2
)}ms平均 ${avgTime.toFixed(2)}ms/`
);
// 验证性能阈值每次操作不应超过50ms
if (avgTime > 50) {
throw new Error(
`性能不达标:平均操作时间 ${avgTime.toFixed(2)}ms 超过阈值 50ms`
);
}
}
/**
* 测试内存管理
*/
async function testMemoryManagement() {
const initialMemory = performance.memory
? performance.memory.usedJSHeapSize
: 0;
// 创建多个管理器实例
const managers = [];
for (let i = 0; i < 10; i++) {
const manager = new LiquifyCPUManager();
const testImageData = createTestImageData(200, 200);
manager.initialize(testImageData);
managers.push(manager);
}
// 销毁所有管理器
for (const manager of managers) {
if (manager.destroy) {
manager.destroy();
}
}
// 强制垃圾回收(如果可用)
if (window.gc) {
window.gc();
}
const finalMemory = performance.memory
? performance.memory.usedJSHeapSize
: 0;
const memoryIncrease = finalMemory - initialMemory;
console.log(
`内存测试: 初始 ${(initialMemory / 1024 / 1024).toFixed(2)}MB, 最终 ${(
finalMemory /
1024 /
1024
).toFixed(2)}MB, 增长 ${(memoryIncrease / 1024 / 1024).toFixed(2)}MB`
);
// 验证内存增长不超过10MB基本的内存泄漏检查
if (memoryIncrease > 10 * 1024 * 1024) {
console.warn(
`潜在内存泄漏: 内存增长 ${(memoryIncrease / 1024 / 1024).toFixed(2)}MB`
);
}
}
/**
* 运行所有集成测试
*/
export async function runLiquifyIntegrationTests() {
console.log("🚀 开始液化功能集成测试...");
// 重置测试结果
testResults = {
totalTests: 0,
passedTests: 0,
failedTests: 0,
errors: [],
};
try {
// 基础功能测试
await runTest("CPU管理器基本功能", testCPUManagerBasics);
await runTest("WebGL管理器基本功能", testWebGLManagerBasics);
await runTest("实时更新器功能", testRealTimeUpdater);
await runTest("增强液化管理器", testEnhancedLiquifyManager);
// 高级功能测试
await runTest("坐标转换准确性", testCoordinateConversion);
await runTest("性能表现", testPerformance);
await runTest("内存管理", testMemoryManagement);
} catch (error) {
console.error("集成测试出现严重错误:", error);
}
// 输出测试结果
console.log("\n📊 液化功能集成测试结果:");
console.log(`总测试数: ${testResults.totalTests}`);
console.log(`通过: ${testResults.passedTests}`);
console.log(`失败: ${testResults.failedTests}`);
console.log(
`成功率: ${(
(testResults.passedTests / testResults.totalTests) *
100
).toFixed(1)}%`
);
if (testResults.errors.length > 0) {
console.log("\n❌ 失败的测试:");
testResults.errors.forEach(({ testName, error }) => {
console.log(` - ${testName}: ${error}`);
});
}
return testResults;
}
/**
* 在浏览器控制台中运行测试
*/
if (typeof window !== "undefined") {
window.runLiquifyIntegrationTests = runLiquifyIntegrationTests;
console.log("💡 使用 window.runLiquifyIntegrationTests() 运行液化集成测试");
}