451 lines
12 KiB
JavaScript
451 lines
12 KiB
JavaScript
/**
|
||
* 液化功能集成测试
|
||
* 用于在浏览器环境中测试完整的液化工作流程
|
||
*/
|
||
|
||
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() 运行液化集成测试");
|
||
}
|