新增soastorage存储器

This commit is contained in:
YHH
2025-07-30 14:14:04 +08:00
parent 0411aa9aef
commit 01fa33e122
14 changed files with 2632 additions and 5 deletions

View File

@@ -0,0 +1,88 @@
import { Component } from '../../../src/ECS/Component';
import { ComponentStorageManager, EnableSoA } from '../../../src/ECS/Core/ComponentStorage';
// 默认原始存储组件
class PositionComponent extends Component {
public x: number = 0;
public y: number = 0;
public z: number = 0;
}
// 启用SoA优化的组件用于大规模批量操作
@EnableSoA
class LargeScaleComponent extends Component {
public x: number = 0;
public y: number = 0;
public z: number = 0;
public vx: number = 0;
public vy: number = 0;
public vz: number = 0;
}
describe('SoA优化选择测试', () => {
let manager: ComponentStorageManager;
beforeEach(() => {
manager = new ComponentStorageManager();
});
test('默认使用原始存储', () => {
const storage = manager.getStorage(PositionComponent);
// 添加组件
manager.addComponent(1, new PositionComponent());
// 验证能正常工作
const component = manager.getComponent(1, PositionComponent);
expect(component).toBeTruthy();
expect(component?.x).toBe(0);
// 验证使用原始存储
expect(storage.constructor.name).toBe('ComponentStorage');
});
test('@EnableSoA装饰器启用优化', () => {
const storage = manager.getStorage(LargeScaleComponent);
// 添加组件
const component = new LargeScaleComponent();
component.x = 100;
component.vx = 10;
manager.addComponent(1, component);
// 验证能正常工作
const retrieved = manager.getComponent(1, LargeScaleComponent);
expect(retrieved).toBeTruthy();
expect(retrieved?.x).toBe(100);
expect(retrieved?.vx).toBe(10);
// 验证使用SoA存储
expect(storage.constructor.name).toBe('SoAStorage');
});
test('SoA存储功能验证', () => {
const entityCount = 1000;
// 创建实体使用SoA优化
for (let i = 0; i < entityCount; i++) {
const component = new LargeScaleComponent();
component.x = i;
component.y = i * 2;
component.vx = 1;
component.vy = 2;
manager.addComponent(i, component);
}
// 验证数据正确性
const testComponent = manager.getComponent(100, LargeScaleComponent);
expect(testComponent?.x).toBe(100);
expect(testComponent?.y).toBe(200);
expect(testComponent?.vx).toBe(1);
expect(testComponent?.vy).toBe(2);
// 验证存储类型
const storage = manager.getStorage(LargeScaleComponent);
expect(storage.constructor.name).toBe('SoAStorage');
console.log(`成功创建 ${entityCount} 个SoA实体数据验证通过`);
});
});

View File

@@ -0,0 +1,530 @@
import { Component } from '../../../src/ECS/Component';
import { ComponentStorage, ComponentStorageManager, EnableSoA } from '../../../src/ECS/Core/ComponentStorage';
import { SoAStorage } from '../../../src/ECS/Core/SoAStorage';
// 测试用统一组件结构启用SoA
@EnableSoA
class TestPositionComponent extends Component {
public x: number = 0;
public y: number = 0;
public z: number = 0;
constructor(x = 0, y = 0, z = 0) {
super();
this.x = x;
this.y = y;
this.z = z;
}
}
@EnableSoA
class TestVelocityComponent extends Component {
public vx: number = 0;
public vy: number = 0;
public vz: number = 0;
public maxSpeed: number = 100;
constructor(vx = 0, vy = 0, vz = 0) {
super();
this.vx = vx;
this.vy = vy;
this.vz = vz;
}
}
@EnableSoA
class TestHealthComponent extends Component {
public current: number = 100;
public max: number = 100;
public regeneration: number = 1;
constructor(current = 100, max = 100) {
super();
this.current = current;
this.max = max;
}
}
// 用于原始存储测试的版本(默认原始存储)
class OriginalPositionComponent extends Component {
public x: number = 0;
public y: number = 0;
public z: number = 0;
constructor(x = 0, y = 0, z = 0) {
super();
this.x = x;
this.y = y;
this.z = z;
}
}
class OriginalVelocityComponent extends Component {
public vx: number = 0;
public vy: number = 0;
public vz: number = 0;
public maxSpeed: number = 100;
constructor(vx = 0, vy = 0, vz = 0) {
super();
this.vx = vx;
this.vy = vy;
this.vz = vz;
}
}
class OriginalHealthComponent extends Component {
public current: number = 100;
public max: number = 100;
public regeneration: number = 1;
constructor(current = 100, max = 100) {
super();
this.current = current;
this.max = max;
}
}
interface PerformanceResult {
name: string;
storageType: 'Original' | 'SoA';
entityCount: number;
operations: number;
totalTime: number;
averageTime: number;
operationsPerSecond: number;
}
describe('ComponentStorage 严谨性能对比测试', () => {
const entityCounts = [1000, 5000, 20000];
let results: PerformanceResult[] = [];
afterAll(() => {
generateDetailedReport();
});
describe('存储器创建和初始化', () => {
test('验证SoA和原始存储使用相同接口', () => {
const originalManager = new ComponentStorageManager();
const soaManager = new ComponentStorageManager();
const originalStorage = originalManager.getStorage(OriginalPositionComponent);
const soaStorage = soaManager.getStorage(TestPositionComponent);
// 验证都实现了相同的接口
expect(typeof originalStorage.addComponent).toBe('function');
expect(typeof originalStorage.getComponent).toBe('function');
expect(typeof originalStorage.hasComponent).toBe('function');
expect(typeof originalStorage.removeComponent).toBe('function');
expect(typeof soaStorage.addComponent).toBe('function');
expect(typeof soaStorage.getComponent).toBe('function');
expect(typeof soaStorage.hasComponent).toBe('function');
expect(typeof soaStorage.removeComponent).toBe('function');
// 验证存储器类型
expect(originalStorage).toBeInstanceOf(ComponentStorage);
expect(soaStorage).toBeInstanceOf(SoAStorage);
});
});
describe('实体创建性能对比', () => {
entityCounts.forEach(entityCount => {
test(`创建 ${entityCount} 个完整实体`, () => {
console.log(`\\n=== 实体创建性能测试: ${entityCount} 个实体 ===`);
// 原始存储测试
const originalResult = measureOriginalEntityCreation(entityCount);
results.push(originalResult);
// SoA存储测试
const soaResult = measureSoAEntityCreation(entityCount);
results.push(soaResult);
// 输出对比结果
console.log(`原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`);
console.log(`SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`);
const speedup = originalResult.totalTime / soaResult.totalTime;
const improvement = ((speedup - 1) * 100);
console.log(`性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`);
// 验证功能正确性
expect(originalResult.operations).toBe(soaResult.operations);
expect(originalResult.totalTime).toBeGreaterThan(0);
expect(soaResult.totalTime).toBeGreaterThan(0);
});
});
});
describe('组件访问性能对比', () => {
entityCounts.forEach(entityCount => {
test(`随机访问 ${entityCount} 个实体组件`, () => {
console.log(`\\n=== 组件访问性能测试: ${entityCount} 个实体 ===`);
// 原始存储测试
const originalResult = measureOriginalComponentAccess(entityCount, 100);
results.push(originalResult);
// SoA存储测试
const soaResult = measureSoAComponentAccess(entityCount, 100);
results.push(soaResult);
// 输出对比结果
console.log(`原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`);
console.log(`SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`);
const speedup = originalResult.totalTime / soaResult.totalTime;
const improvement = ((speedup - 1) * 100);
console.log(`性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`);
expect(originalResult.operations).toBe(soaResult.operations);
expect(originalResult.totalTime).toBeGreaterThan(0);
expect(soaResult.totalTime).toBeGreaterThan(0);
});
});
});
describe('批量更新性能对比SoA优势场景', () => {
entityCounts.forEach(entityCount => {
test(`批量更新 ${entityCount} 个实体`, () => {
console.log(`\\n=== 批量更新性能测试: ${entityCount} 个实体 ===`);
// 原始存储测试
const originalResult = measureOriginalBatchUpdate(entityCount, 50);
results.push(originalResult);
// SoA存储测试向量化操作
const soaResult = measureSoABatchUpdate(entityCount, 50);
results.push(soaResult);
// 输出对比结果
console.log(`原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`);
console.log(`SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`);
const speedup = originalResult.totalTime / soaResult.totalTime;
const improvement = ((speedup - 1) * 100);
console.log(`性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`);
// 这是SoA的优势场景应该有性能提升
if (entityCount > 5000) {
expect(speedup).toBeGreaterThan(1.0); // SoA应该更快
}
expect(originalResult.operations).toBe(soaResult.operations);
expect(originalResult.totalTime).toBeGreaterThan(0);
expect(soaResult.totalTime).toBeGreaterThan(0);
});
});
});
// 测试辅助函数
function measureOriginalEntityCreation(entityCount: number): PerformanceResult {
const manager = new ComponentStorageManager();
const startTime = performance.now();
for (let i = 0; i < entityCount; i++) {
manager.addComponent(i, new OriginalPositionComponent(
Math.random() * 1000,
Math.random() * 1000,
Math.random() * 100
));
manager.addComponent(i, new OriginalVelocityComponent(
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 10
));
if (i % 2 === 0) {
manager.addComponent(i, new OriginalHealthComponent(
80 + Math.random() * 20,
100
));
}
}
const totalTime = performance.now() - startTime;
const operations = entityCount * 2.5; // 平均每个实体2.5个组件
return {
name: 'Entity Creation',
storageType: 'Original',
entityCount,
operations,
totalTime,
averageTime: totalTime / operations,
operationsPerSecond: operations / (totalTime / 1000)
};
}
function measureSoAEntityCreation(entityCount: number): PerformanceResult {
const manager = new ComponentStorageManager();
const startTime = performance.now();
for (let i = 0; i < entityCount; i++) {
manager.addComponent(i, new TestPositionComponent(
Math.random() * 1000,
Math.random() * 1000,
Math.random() * 100
));
manager.addComponent(i, new TestVelocityComponent(
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 20,
(Math.random() - 0.5) * 10
));
if (i % 2 === 0) {
manager.addComponent(i, new TestHealthComponent(
80 + Math.random() * 20,
100
));
}
}
const totalTime = performance.now() - startTime;
const operations = entityCount * 2.5;
return {
name: 'Entity Creation',
storageType: 'SoA',
entityCount,
operations,
totalTime,
averageTime: totalTime / operations,
operationsPerSecond: operations / (totalTime / 1000)
};
}
function measureOriginalComponentAccess(entityCount: number, iterations: number): PerformanceResult {
const manager = new ComponentStorageManager();
// 预创建实体
for (let i = 0; i < entityCount; i++) {
manager.addComponent(i, new OriginalPositionComponent(i, i, i));
manager.addComponent(i, new OriginalVelocityComponent(1, 1, 1));
if (i % 2 === 0) {
manager.addComponent(i, new OriginalHealthComponent(100, 100));
}
}
const startTime = performance.now();
for (let iter = 0; iter < iterations; iter++) {
for (let i = 0; i < entityCount; i++) {
const pos = manager.getComponent(i, OriginalPositionComponent);
const vel = manager.getComponent(i, OriginalVelocityComponent);
if (pos && vel) {
// 模拟简单的读取操作
const sum = pos.x + pos.y + pos.z + vel.vx + vel.vy + vel.vz;
if (sum < 0) continue; // 防止优化
}
}
}
const totalTime = performance.now() - startTime;
const operations = entityCount * iterations;
return {
name: 'Component Access',
storageType: 'Original',
entityCount,
operations,
totalTime,
averageTime: totalTime / operations,
operationsPerSecond: operations / (totalTime / 1000)
};
}
function measureSoAComponentAccess(entityCount: number, iterations: number): PerformanceResult {
const manager = new ComponentStorageManager();
// 预创建实体
for (let i = 0; i < entityCount; i++) {
manager.addComponent(i, new TestPositionComponent(i, i, i));
manager.addComponent(i, new TestVelocityComponent(1, 1, 1));
if (i % 2 === 0) {
manager.addComponent(i, new TestHealthComponent(100, 100));
}
}
const startTime = performance.now();
for (let iter = 0; iter < iterations; iter++) {
for (let i = 0; i < entityCount; i++) {
const pos = manager.getComponent(i, TestPositionComponent);
const vel = manager.getComponent(i, TestVelocityComponent);
if (pos && vel) {
// 模拟简单的读取操作
const sum = pos.x + pos.y + pos.z + vel.vx + vel.vy + vel.vz;
if (sum < 0) continue; // 防止优化
}
}
}
const totalTime = performance.now() - startTime;
const operations = entityCount * iterations;
return {
name: 'Component Access',
storageType: 'SoA',
entityCount,
operations,
totalTime,
averageTime: totalTime / operations,
operationsPerSecond: operations / (totalTime / 1000)
};
}
function measureOriginalBatchUpdate(entityCount: number, iterations: number): PerformanceResult {
const manager = new ComponentStorageManager();
// 预创建实体
for (let i = 0; i < entityCount; i++) {
manager.addComponent(i, new OriginalPositionComponent(i, i, 0));
manager.addComponent(i, new OriginalVelocityComponent(1, 1, 0));
}
const startTime = performance.now();
const deltaTime = 0.016;
for (let iter = 0; iter < iterations; iter++) {
for (let i = 0; i < entityCount; i++) {
const pos = manager.getComponent(i, OriginalPositionComponent);
const vel = manager.getComponent(i, OriginalVelocityComponent);
if (pos && vel) {
// 物理更新
pos.x += vel.vx * deltaTime;
pos.y += vel.vy * deltaTime;
pos.z += vel.vz * deltaTime;
}
}
}
const totalTime = performance.now() - startTime;
const operations = entityCount * iterations;
return {
name: 'Batch Update',
storageType: 'Original',
entityCount,
operations,
totalTime,
averageTime: totalTime / operations,
operationsPerSecond: operations / (totalTime / 1000)
};
}
function measureSoABatchUpdate(entityCount: number, iterations: number): PerformanceResult {
const manager = new ComponentStorageManager();
// 预创建实体
for (let i = 0; i < entityCount; i++) {
manager.addComponent(i, new TestPositionComponent(i, i, 0));
manager.addComponent(i, new TestVelocityComponent(1, 1, 0));
}
const startTime = performance.now();
const deltaTime = 0.016;
// 获取SoA存储器进行向量化操作
const posStorage = manager.getStorage(TestPositionComponent) as SoAStorage<TestPositionComponent>;
const velStorage = manager.getStorage(TestVelocityComponent) as SoAStorage<TestVelocityComponent>;
for (let iter = 0; iter < iterations; iter++) {
// 使用向量化操作
posStorage.performVectorizedOperation((posFields, activeIndices) => {
const velFields = velStorage.getFieldArray('vx') ?
new Map([
['vx', velStorage.getFieldArray('vx')!],
['vy', velStorage.getFieldArray('vy')!],
['vz', velStorage.getFieldArray('vz')!]
]) : new Map();
const posX = posFields.get('x') as Float32Array;
const posY = posFields.get('y') as Float32Array;
const posZ = posFields.get('z') as Float32Array;
const velX = velFields.get('vx') as Float32Array;
const velY = velFields.get('vy') as Float32Array;
const velZ = velFields.get('vz') as Float32Array;
// 向量化物理更新
for (let j = 0; j < activeIndices.length; j++) {
const idx = activeIndices[j];
posX[idx] += velX[idx] * deltaTime;
posY[idx] += velY[idx] * deltaTime;
posZ[idx] += velZ[idx] * deltaTime;
}
});
}
const totalTime = performance.now() - startTime;
const operations = entityCount * iterations;
return {
name: 'Batch Update',
storageType: 'SoA',
entityCount,
operations,
totalTime,
averageTime: totalTime / operations,
operationsPerSecond: operations / (totalTime / 1000)
};
}
function generateDetailedReport(): void {
console.log('\\n' + '='.repeat(80));
console.log('ComponentStorage 严谨性能对比报告');
console.log('='.repeat(80));
// 按测试类型分组
const groupedResults = new Map<string, PerformanceResult[]>();
for (const result of results) {
const key = `${result.name}-${result.entityCount}`;
if (!groupedResults.has(key)) {
groupedResults.set(key, []);
}
groupedResults.get(key)!.push(result);
}
let totalOriginalTime = 0;
let totalSoATime = 0;
let testCount = 0;
for (const [key, testResults] of groupedResults.entries()) {
console.log(`\\n${key}:`);
const originalResult = testResults.find(r => r.storageType === 'Original');
const soaResult = testResults.find(r => r.storageType === 'SoA');
if (originalResult && soaResult) {
const speedup = originalResult.totalTime / soaResult.totalTime;
const improvement = ((speedup - 1) * 100);
console.log(` 原始存储: ${originalResult.totalTime.toFixed(2)}ms (${originalResult.operationsPerSecond.toFixed(0)} ops/sec)`);
console.log(` SoA存储: ${soaResult.totalTime.toFixed(2)}ms (${soaResult.operationsPerSecond.toFixed(0)} ops/sec)`);
console.log(` 性能对比: ${speedup.toFixed(2)}x ${improvement > 0 ? '提升' : '下降'} ${Math.abs(improvement).toFixed(1)}%`);
totalOriginalTime += originalResult.totalTime;
totalSoATime += soaResult.totalTime;
testCount++;
}
}
if (testCount > 0) {
const overallSpeedup = totalOriginalTime / totalSoATime;
const overallImprovement = ((overallSpeedup - 1) * 100);
console.log('\\n' + '='.repeat(80));
console.log('总体性能对比:');
console.log(` 原始存储总耗时: ${totalOriginalTime.toFixed(2)}ms`);
console.log(` SoA存储总耗时: ${totalSoATime.toFixed(2)}ms`);
console.log(` 总体性能对比: ${overallSpeedup.toFixed(2)}x ${overallImprovement > 0 ? '提升' : '下降'} ${Math.abs(overallImprovement).toFixed(1)}%`);
console.log('\\n结论: SoA优化在批量操作场景中表现优异在小规模随机访问场景中有轻微开销。');
console.log('建议: 对于大规模游戏实体和批量系统更新SoA优化能带来显著性能提升。');
console.log('='.repeat(80));
}
}
});

View File

@@ -7,7 +7,7 @@ import {
import { Component } from '../../../src/ECS/Component';
import { BigIntFactory } from '../../../src/ECS/Utils/BigIntCompatibility';
// 测试组件类
// 测试组件类(默认使用原始存储)
class TestComponent extends Component {
constructor(public value: number = 0) {
super();

View File

@@ -0,0 +1,252 @@
import { Component } from '../../../src/ECS/Component';
import { ComponentStorageManager, EnableSoA, SerializeMap, SerializeSet, SerializeArray, DeepCopy } from '../../../src/ECS/Core/ComponentStorage';
// 测试组件:使用集合类型装饰器
@EnableSoA
class CollectionsComponent extends Component {
// 序列化Map存储
@SerializeMap
public playerStats: Map<string, number> = new Map();
// 序列化Set存储
@SerializeSet
public achievements: Set<string> = new Set();
// 序列化Array存储
@SerializeArray
public inventory: string[] = [];
// 深拷贝对象存储
@DeepCopy
public config: { settings: { volume: number } } = { settings: { volume: 0.5 } };
// 普通对象(引用存储)
public metadata: any = null;
constructor() {
super();
}
}
describe('SoA集合类型装饰器测试', () => {
let manager: ComponentStorageManager;
beforeEach(() => {
manager = new ComponentStorageManager();
});
test('验证Map序列化存储', () => {
console.log('\\n=== 测试Map序列化存储 ===');
const component = new CollectionsComponent();
// 设置Map数据
component.playerStats.set('health', 100);
component.playerStats.set('mana', 50);
component.playerStats.set('experience', 1250);
console.log('原始Map数据:', {
size: component.playerStats.size,
entries: Array.from(component.playerStats.entries())
});
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, CollectionsComponent);
console.log('取回Map数据:', {
size: retrieved?.playerStats.size,
entries: Array.from(retrieved?.playerStats.entries() || [])
});
// 验证Map数据完整性
expect(retrieved?.playerStats).toBeInstanceOf(Map);
expect(retrieved?.playerStats.size).toBe(3);
expect(retrieved?.playerStats.get('health')).toBe(100);
expect(retrieved?.playerStats.get('mana')).toBe(50);
expect(retrieved?.playerStats.get('experience')).toBe(1250);
console.log('✅ Map序列化存储验证通过');
});
test('验证Set序列化存储', () => {
console.log('\\n=== 测试Set序列化存储 ===');
const component = new CollectionsComponent();
// 设置Set数据
component.achievements.add('first_kill');
component.achievements.add('level_10');
component.achievements.add('boss_defeated');
console.log('原始Set数据:', {
size: component.achievements.size,
values: Array.from(component.achievements)
});
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, CollectionsComponent);
console.log('取回Set数据:', {
size: retrieved?.achievements.size,
values: Array.from(retrieved?.achievements || [])
});
// 验证Set数据完整性
expect(retrieved?.achievements).toBeInstanceOf(Set);
expect(retrieved?.achievements.size).toBe(3);
expect(retrieved?.achievements.has('first_kill')).toBe(true);
expect(retrieved?.achievements.has('level_10')).toBe(true);
expect(retrieved?.achievements.has('boss_defeated')).toBe(true);
console.log('✅ Set序列化存储验证通过');
});
test('验证Array序列化存储', () => {
console.log('\\n=== 测试Array序列化存储 ===');
const component = new CollectionsComponent();
// 设置Array数据
component.inventory.push('sword', 'shield', 'potion');
console.log('原始Array数据:', component.inventory);
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, CollectionsComponent);
console.log('取回Array数据:', retrieved?.inventory);
// 验证Array数据完整性
expect(Array.isArray(retrieved?.inventory)).toBe(true);
expect(retrieved?.inventory.length).toBe(3);
expect(retrieved?.inventory).toEqual(['sword', 'shield', 'potion']);
console.log('✅ Array序列化存储验证通过');
});
test('验证深拷贝对象存储', () => {
console.log('\\n=== 测试深拷贝对象存储 ===');
const component = new CollectionsComponent();
const originalConfig = component.config;
// 修改配置
component.config.settings.volume = 0.8;
console.log('原始配置:', component.config);
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, CollectionsComponent);
console.log('取回配置:', retrieved?.config);
// 验证深拷贝
expect(retrieved?.config).toEqual(component.config);
expect(retrieved?.config).not.toBe(originalConfig); // 不是同一个引用
expect(retrieved?.config.settings.volume).toBe(0.8);
// 修改原始对象不应该影响取回的对象
component.config.settings.volume = 0.3;
expect(retrieved?.config.settings.volume).toBe(0.8); // 保持不变
console.log('✅ 深拷贝对象存储验证通过');
});
test('对比普通对象存储(引用存储)', () => {
console.log('\\n=== 测试普通对象存储(引用存储)===');
const component = new CollectionsComponent();
const sharedObject = { data: 'shared' };
component.metadata = sharedObject;
console.log('原始metadata:', component.metadata);
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, CollectionsComponent);
console.log('取回metadata:', retrieved?.metadata);
// 验证引用存储
expect(retrieved?.metadata).toBe(sharedObject); // 是同一个引用
expect(retrieved?.metadata.data).toBe('shared');
console.log('✅ 普通对象存储验证通过');
});
test('复杂场景:多种类型混合使用', () => {
console.log('\\n=== 测试复杂场景 ===');
const component = new CollectionsComponent();
// 设置复杂数据
component.playerStats.set('level', 25);
component.playerStats.set('gold', 5000);
component.achievements.add('explorer');
component.achievements.add('warrior');
component.inventory.push('legendary_sword', 'magic_potion');
component.config = {
settings: {
volume: 0.75
}
};
component.metadata = { timestamp: Date.now() };
console.log('复杂数据设置完成');
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, CollectionsComponent);
// 全面验证
expect(retrieved?.playerStats.get('level')).toBe(25);
expect(retrieved?.achievements.has('explorer')).toBe(true);
expect(retrieved?.inventory).toContain('legendary_sword');
expect(retrieved?.config.settings.volume).toBe(0.75);
expect(retrieved?.metadata).toBeDefined();
console.log('✅ 复杂场景验证通过');
});
test('性能测试:序列化 vs 深拷贝', () => {
console.log('\\n=== 性能对比测试 ===');
const entityCount = 100;
// 准备测试数据
const startTime = performance.now();
for (let i = 0; i < entityCount; i++) {
const component = new CollectionsComponent();
// 设置数据
component.playerStats.set('id', i);
component.playerStats.set('score', i * 100);
component.achievements.add(`achievement_${i}`);
component.inventory.push(`item_${i}`);
component.config = { settings: { volume: i / entityCount } };
manager.addComponent(i, component);
}
const createTime = performance.now() - startTime;
// 读取测试
const readStartTime = performance.now();
for (let i = 0; i < entityCount; i++) {
const component = manager.getComponent(i, CollectionsComponent);
expect(component?.playerStats.get('id')).toBe(i);
}
const readTime = performance.now() - readStartTime;
console.log(`创建${entityCount}个复杂组件: ${createTime.toFixed(2)}ms`);
console.log(`读取${entityCount}个复杂组件: ${readTime.toFixed(2)}ms`);
console.log(`平均每个组件: ${((createTime + readTime) / entityCount).toFixed(4)}ms`);
console.log('✅ 性能测试完成');
});
});

View File

@@ -0,0 +1,307 @@
import { Component } from '../../../src/ECS/Component';
import { ComponentStorageManager, EnableSoA, HighPrecision, Float64, Int32, SerializeMap, SerializeSet, SerializeArray, DeepCopy } from '../../../src/ECS/Core/ComponentStorage';
import { SoAStorage } from '../../../src/ECS/Core/SoAStorage';
// 综合测试组件,覆盖所有装饰器
@EnableSoA
class ComprehensiveComponent extends Component {
@HighPrecision
public bigIntId: number = BigInt(Number.MAX_SAFE_INTEGER + 1) as any;
@Float64
public preciseValue: number = Math.PI;
@Int32
public intValue: number = -2147483648;
@SerializeMap
public gameMap: Map<string, any> = new Map();
@SerializeSet
public flags: Set<number> = new Set();
@SerializeArray
public items: any[] = [];
@DeepCopy
public nestedConfig: any = { deep: { nested: { value: 42 } } };
// 未装饰的字段
public normalFloat: number = 1.23;
public flag: boolean = true;
public text: string = 'default';
public complexObject: any = null;
constructor() {
super();
}
}
describe('SoA存储综合测试覆盖', () => {
let manager: ComponentStorageManager;
beforeEach(() => {
manager = new ComponentStorageManager();
});
test('验证所有装饰器类型的存储和检索', () => {
console.log('\\n=== 综合装饰器测试 ===');
const component = new ComprehensiveComponent();
// 设置复杂数据
component.gameMap.set('player1', { level: 10, gold: 500 });
component.gameMap.set('player2', { level: 15, gold: 1200 });
component.flags.add(1);
component.flags.add(2);
component.flags.add(4);
component.items.push({ type: 'weapon', name: 'sword' });
component.items.push({ type: 'armor', name: 'shield' });
component.nestedConfig.deep.nested.value = 999;
component.complexObject = { reference: 'shared' };
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, ComprehensiveComponent);
// 验证所有类型
expect(retrieved?.bigIntId).toBe(component.bigIntId);
expect(retrieved?.preciseValue).toBeCloseTo(Math.PI, 15);
expect(retrieved?.intValue).toBe(-2147483648);
expect(retrieved?.gameMap).toBeInstanceOf(Map);
expect(retrieved?.gameMap.get('player1')).toEqual({ level: 10, gold: 500 });
expect(retrieved?.flags).toBeInstanceOf(Set);
expect(retrieved?.flags.has(2)).toBe(true);
expect(retrieved?.items).toEqual(component.items);
expect(retrieved?.nestedConfig.deep.nested.value).toBe(999);
// 深拷贝验证
expect(retrieved?.nestedConfig).not.toBe(component.nestedConfig);
console.log('✅ 综合装饰器测试通过');
});
test('测试存储器内存统计和容量管理', () => {
console.log('\\n=== 存储器管理测试 ===');
const storage = manager.getStorage(ComprehensiveComponent) as SoAStorage<ComprehensiveComponent>;
// 添加多个组件
for (let i = 1; i <= 5; i++) {
const component = new ComprehensiveComponent();
component.intValue = i * 100;
component.preciseValue = i * Math.PI;
manager.addComponent(i, component);
}
// 检查统计信息
const stats = storage.getStats();
console.log('存储统计:', {
size: stats.size,
capacity: stats.capacity,
memoryUsage: stats.memoryUsage,
fieldCount: stats.fieldStats.size
});
expect(stats.size).toBe(5);
expect(stats.capacity).toBeGreaterThanOrEqual(5);
expect(stats.memoryUsage).toBeGreaterThan(0);
// 测试压缩
storage.removeComponent(2);
storage.removeComponent(4);
const statsBeforeCompact = storage.getStats();
storage.compact();
const statsAfterCompact = storage.getStats();
expect(statsAfterCompact.size).toBe(3);
console.log('压缩前后对比:', {
before: statsBeforeCompact.size,
after: statsAfterCompact.size
});
console.log('✅ 存储器管理测试通过');
});
test('测试序列化错误处理', () => {
console.log('\\n=== 序列化错误处理测试 ===');
// 创建包含循环引用的对象
const component = new ComprehensiveComponent();
const cyclicObject: any = { name: 'test' };
cyclicObject.self = cyclicObject; // 循环引用
// 这应该不会崩溃,而是优雅处理
component.items.push(cyclicObject);
expect(() => {
manager.addComponent(1, component);
}).not.toThrow();
const retrieved = manager.getComponent(1, ComprehensiveComponent);
expect(retrieved).toBeDefined();
console.log('✅ 序列化错误处理测试通过');
});
test('测试大容量扩展和性能', () => {
console.log('\\n=== 大容量性能测试 ===');
const startTime = performance.now();
const entityCount = 2000;
// 创建大量实体
for (let i = 1; i <= entityCount; i++) {
const component = new ComprehensiveComponent();
component.intValue = i;
component.preciseValue = i * 0.1;
component.gameMap.set(`key${i}`, i);
component.flags.add(i % 10);
component.items.push(`item${i}`);
manager.addComponent(i, component);
}
const createTime = performance.now() - startTime;
// 随机访问测试
const readStartTime = performance.now();
for (let i = 0; i < 100; i++) {
const randomId = Math.floor(Math.random() * entityCount) + 1;
const component = manager.getComponent(randomId, ComprehensiveComponent);
expect(component?.intValue).toBe(randomId);
}
const readTime = performance.now() - readStartTime;
console.log(`创建${entityCount}个组件: ${createTime.toFixed(2)}ms`);
console.log(`随机读取100次: ${readTime.toFixed(2)}ms`);
console.log(`平均创建时间: ${(createTime / entityCount).toFixed(4)}ms/组件`);
// 验证存储统计
const storage = manager.getStorage(ComprehensiveComponent) as SoAStorage<ComprehensiveComponent>;
const stats = storage.getStats();
expect(stats.size).toBe(entityCount);
expect(stats.capacity).toBeGreaterThanOrEqual(entityCount);
console.log('✅ 大容量性能测试通过');
});
test('测试空值和边界处理', () => {
console.log('\\n=== 空值边界测试 ===');
const component = new ComprehensiveComponent();
// 设置各种边界值
component.gameMap.set('null', null);
component.gameMap.set('undefined', undefined);
component.gameMap.set('empty', '');
component.gameMap.set('zero', 0);
component.gameMap.set('false', false);
component.flags.add(0);
component.items.push(null, undefined, '', 0, false);
component.nestedConfig = null;
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, ComprehensiveComponent);
// 验证边界值处理
expect(retrieved?.gameMap.get('null')).toBe(null);
expect(retrieved?.gameMap.get('undefined')).toBe(null); // JSON序列化会将undefined转为null
expect(retrieved?.gameMap.get('empty')).toBe('');
expect(retrieved?.gameMap.get('zero')).toBe(0);
expect(retrieved?.gameMap.get('false')).toBe(false);
expect(retrieved?.flags.has(0)).toBe(true);
expect(retrieved?.items).toEqual([null, null, '', 0, false]); // undefined序列化为null
expect(retrieved?.nestedConfig).toBe(null);
console.log('✅ 空值边界测试通过');
});
test('测试不同TypedArray类型的字段访问', () => {
console.log('\\n=== TypedArray字段测试 ===');
const storage = manager.getStorage(ComprehensiveComponent) as SoAStorage<ComprehensiveComponent>;
// 添加测试数据
const component = new ComprehensiveComponent();
manager.addComponent(1, component);
// 检查不同类型的TypedArray
const preciseArray = storage.getFieldArray('preciseValue');
const intArray = storage.getFieldArray('intValue');
const normalArray = storage.getFieldArray('normalFloat');
const flagArray = storage.getFieldArray('flag');
expect(preciseArray).toBeInstanceOf(Float64Array);
expect(intArray).toBeInstanceOf(Int32Array);
expect(normalArray).toBeInstanceOf(Float32Array);
expect(flagArray).toBeInstanceOf(Float32Array);
// 高精度字段不应该在TypedArray中
const bigIntArray = storage.getFieldArray('bigIntId');
expect(bigIntArray).toBeNull();
console.log('TypedArray类型验证:', {
preciseValue: preciseArray?.constructor.name,
intValue: intArray?.constructor.name,
normalFloat: normalArray?.constructor.name,
flag: flagArray?.constructor.name,
bigIntId: bigIntArray ? 'Found' : 'null (正确)'
});
console.log('✅ TypedArray字段测试通过');
});
test('测试向量化批量操作', () => {
console.log('\\n=== 向量化操作测试 ===');
const storage = manager.getStorage(ComprehensiveComponent) as SoAStorage<ComprehensiveComponent>;
// 添加测试数据
for (let i = 1; i <= 10; i++) {
const component = new ComprehensiveComponent();
component.normalFloat = i;
component.intValue = i * 10;
manager.addComponent(i, component);
}
// 执行向量化操作
let operationExecuted = false;
storage.performVectorizedOperation((fieldArrays, activeIndices) => {
operationExecuted = true;
const normalFloatArray = fieldArrays.get('normalFloat') as Float32Array;
const intArray = fieldArrays.get('intValue') as Int32Array;
expect(normalFloatArray).toBeInstanceOf(Float32Array);
expect(intArray).toBeInstanceOf(Int32Array);
expect(activeIndices.length).toBe(10);
// 批量修改数据
for (let i = 0; i < activeIndices.length; i++) {
const idx = activeIndices[i];
normalFloatArray[idx] *= 2; // 乘以2
intArray[idx] += 5; // 加5
}
});
expect(operationExecuted).toBe(true);
// 验证批量操作结果
const component = manager.getComponent(5, ComprehensiveComponent);
expect(component?.normalFloat).toBe(10); // 5 * 2
expect(component?.intValue).toBe(55); // 50 + 5
console.log('✅ 向量化操作测试通过');
});
});

View File

@@ -0,0 +1,171 @@
import { Component } from '../../../src/ECS/Component';
import { ComponentStorageManager, EnableSoA, HighPrecision, Float64, Int32 } from '../../../src/ECS/Core/ComponentStorage';
import { SoAStorage } from '../../../src/ECS/Core/SoAStorage';
// 测试组件:使用不同的数值类型装饰器
@EnableSoA
class DecoratedComponent extends Component {
// 默认Float32Array存储
public normalFloat: number = 3.14;
// 高精度存储(作为复杂对象)
@HighPrecision
public highPrecisionNumber: number = Number.MAX_SAFE_INTEGER;
// Float64Array存储
@Float64
public preciseFloat: number = Math.PI;
// Int32Array存储
@Int32
public integerValue: number = 42;
// 布尔值默认Float32Array
public flag: boolean = true;
// 字符串(专门数组)
public text: string = 'hello';
constructor() {
super();
}
}
describe('SoA数值类型装饰器测试', () => {
let manager: ComponentStorageManager;
beforeEach(() => {
manager = new ComponentStorageManager();
});
test('验证不同装饰器的存储类型', () => {
console.log('\\n=== 测试装饰器存储类型 ===');
const component = new DecoratedComponent();
component.highPrecisionNumber = Number.MAX_SAFE_INTEGER;
component.preciseFloat = Math.PI;
component.integerValue = 999999;
component.normalFloat = 2.718;
console.log('原始数据:', {
normalFloat: component.normalFloat,
highPrecisionNumber: component.highPrecisionNumber,
preciseFloat: component.preciseFloat,
integerValue: component.integerValue,
flag: component.flag,
text: component.text
});
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, DecoratedComponent);
console.log('\\n取回数据:', {
normalFloat: retrieved?.normalFloat,
highPrecisionNumber: retrieved?.highPrecisionNumber,
preciseFloat: retrieved?.preciseFloat,
integerValue: retrieved?.integerValue,
flag: retrieved?.flag,
text: retrieved?.text
});
// 验证精度保持
expect(retrieved?.normalFloat).toBeCloseTo(2.718, 5); // Float32精度
expect(retrieved?.highPrecisionNumber).toBe(Number.MAX_SAFE_INTEGER); // 高精度保持
expect(retrieved?.preciseFloat).toBeCloseTo(Math.PI, 15); // Float64精度
expect(retrieved?.integerValue).toBe(999999); // 整数保持
expect(retrieved?.flag).toBe(true);
expect(retrieved?.text).toBe('hello');
console.log('✅ 所有装饰器类型验证通过');
});
test('验证存储器内部结构', () => {
console.log('\\n=== 测试存储器内部结构 ===');
const component = new DecoratedComponent();
manager.addComponent(1, component);
const storage = manager.getStorage(DecoratedComponent) as SoAStorage<DecoratedComponent>;
// 检查TypedArray字段
const normalFloatArray = storage.getFieldArray('normalFloat');
const preciseFloatArray = storage.getFieldArray('preciseFloat');
const integerArray = storage.getFieldArray('integerValue');
const flagArray = storage.getFieldArray('flag');
console.log('存储类型:', {
normalFloat: normalFloatArray?.constructor.name,
preciseFloat: preciseFloatArray?.constructor.name,
integerValue: integerArray?.constructor.name,
flag: flagArray?.constructor.name
});
// 验证存储类型
expect(normalFloatArray).toBeInstanceOf(Float32Array);
expect(preciseFloatArray).toBeInstanceOf(Float64Array);
expect(integerArray).toBeInstanceOf(Int32Array);
expect(flagArray).toBeInstanceOf(Float32Array);
// 高精度字段不应该在TypedArray中
const highPrecisionArray = storage.getFieldArray('highPrecisionNumber');
expect(highPrecisionArray).toBeNull();
console.log('✅ 存储器内部结构验证通过');
});
test('测试边界值精度', () => {
console.log('\\n=== 测试边界值精度 ===');
const component = new DecoratedComponent();
// 测试极限值
component.highPrecisionNumber = Number.MAX_SAFE_INTEGER;
component.preciseFloat = Number.MIN_VALUE;
component.normalFloat = 16777217; // 超出Float32精度
component.integerValue = -2147483648; // Int32最小值
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, DecoratedComponent);
console.log('边界值测试结果:', {
highPrecision: retrieved?.highPrecisionNumber === Number.MAX_SAFE_INTEGER,
preciseFloat: retrieved?.preciseFloat === Number.MIN_VALUE,
normalFloat: retrieved?.normalFloat, // 可能有精度损失
integerValue: retrieved?.integerValue === -2147483648
});
// 验证高精度保持
expect(retrieved?.highPrecisionNumber).toBe(Number.MAX_SAFE_INTEGER);
expect(retrieved?.preciseFloat).toBe(Number.MIN_VALUE);
expect(retrieved?.integerValue).toBe(-2147483648);
console.log('✅ 边界值精度测试通过');
});
test('性能对比:装饰器 vs 自动检测', () => {
console.log('\\n=== 性能对比测试 ===');
const entityCount = 1000;
// 使用装饰器的组件
const startTime = performance.now();
for (let i = 0; i < entityCount; i++) {
const component = new DecoratedComponent();
component.highPrecisionNumber = Number.MAX_SAFE_INTEGER;
component.preciseFloat = Math.PI * i;
component.integerValue = i;
manager.addComponent(i, component);
}
const decoratorTime = performance.now() - startTime;
console.log(`装饰器方式: ${decoratorTime.toFixed(2)}ms`);
console.log(`平均每个组件: ${(decoratorTime / entityCount).toFixed(4)}ms`);
// 验证数据完整性
const sample = manager.getComponent(500, DecoratedComponent);
expect(sample?.highPrecisionNumber).toBe(Number.MAX_SAFE_INTEGER);
expect(sample?.integerValue).toBe(500);
console.log('✅ 性能测试完成,数据完整性验证通过');
});
});

View File

@@ -0,0 +1,128 @@
import { Component } from '../../../src/ECS/Component';
import { ComponentStorageManager, EnableSoA } from '../../../src/ECS/Core/ComponentStorage';
// 模拟复杂对象如cocos的node节点
class MockNode {
public name: string;
public active: boolean;
constructor(name: string) {
this.name = name;
this.active = true;
}
public toString() {
return `Node(${this.name})`;
}
}
// 包含复杂属性的组件
@EnableSoA
class ProblematicComponent extends Component {
public x: number = 0;
public y: number = 0;
public node: MockNode | null = null;
public callback: Function | null = null;
public data: any = null;
constructor() {
super();
this.node = new MockNode('test');
this.callback = () => console.log('test');
this.data = { complex: 'object' };
}
}
// 安全的数值组件
@EnableSoA
class SafeComponent extends Component {
public x: number = 0;
public y: number = 0;
public active: boolean = true;
}
describe('SoA边界情况和复杂属性测试', () => {
let manager: ComponentStorageManager;
beforeEach(() => {
manager = new ComponentStorageManager();
});
test('包含复杂对象的组件会有什么问题', () => {
console.log('\\n=== 测试复杂对象处理 ===');
// 创建包含复杂属性的组件
const originalComponent = new ProblematicComponent();
console.log('原始组件:', {
x: originalComponent.x,
y: originalComponent.y,
node: originalComponent.node?.name,
callback: typeof originalComponent.callback,
data: originalComponent.data
});
// 添加到SoA存储
manager.addComponent(1, originalComponent);
// 获取组件看看发生了什么
const retrievedComponent = manager.getComponent(1, ProblematicComponent);
console.log('取回的组件:', {
x: retrievedComponent?.x,
y: retrievedComponent?.y,
node: retrievedComponent?.node,
callback: retrievedComponent?.callback,
data: retrievedComponent?.data
});
// 验证数据完整性
expect(retrievedComponent?.x).toBe(0);
expect(retrievedComponent?.y).toBe(0);
// 复杂对象的问题
console.log('\\n⚠ 问题发现:');
console.log('- node对象:', retrievedComponent?.node);
console.log('- callback函数:', retrievedComponent?.callback);
console.log('- data对象:', retrievedComponent?.data);
// 复杂属性现在应该正确保存
expect(retrievedComponent?.node?.name).toBe('test'); // 应该保持原始值
expect(retrievedComponent?.callback).toBe(originalComponent.callback); // 应该是同一个函数
expect(retrievedComponent?.data).toEqual({ complex: 'object' }); // 应该保持原始数据
console.log('✅ 修复成功:复杂对象现在能正确处理!');
});
test('纯数值组件工作正常', () => {
console.log('\\n=== 测试纯数值组件 ===');
const safeComponent = new SafeComponent();
safeComponent.x = 100;
safeComponent.y = 200;
safeComponent.active = false;
manager.addComponent(1, safeComponent);
const retrieved = manager.getComponent(1, SafeComponent);
console.log('纯数值组件正常工作:', {
x: retrieved?.x,
y: retrieved?.y,
active: retrieved?.active
});
expect(retrieved?.x).toBe(100);
expect(retrieved?.y).toBe(200);
expect(retrieved?.active).toBe(false);
});
test('SoA是否能检测到不适合的组件类型', () => {
console.log('\\n=== 测试类型检测 ===');
// 当前实现会静默忽略复杂字段
// 这是一个潜在的问题!
const storage = manager.getStorage(ProblematicComponent);
console.log('存储类型:', storage.constructor.name);
// SoA存储应该能警告或拒绝不适合的组件
expect(storage.constructor.name).toBe('SoAStorage');
});
});

View File

@@ -0,0 +1,158 @@
import { Component } from '../../../src/ECS/Component';
import { ComponentStorageManager, EnableSoA, HighPrecision, Float64 } from '../../../src/ECS/Core/ComponentStorage';
// 包含所有基础类型的组件
@EnableSoA
class AllTypesComponent extends Component {
// 数值类型
public intNumber: number = 42;
public floatNumber: number = 3.14;
public zeroNumber: number = 0;
// 布尔类型
public trueBoolean: boolean = true;
public falseBoolean: boolean = false;
// 字符串类型
public emptyString: string = '';
public normalString: string = 'hello';
public longString: string = 'this is a long string with spaces and 123 numbers!';
// 其他基础类型
public nullValue: null = null;
public undefinedValue: undefined = undefined;
// 复杂类型
public arrayValue: number[] = [1, 2, 3];
public objectValue: { name: string } = { name: 'test' };
constructor() {
super();
}
}
// 边界测试专用组件
@EnableSoA
class BoundaryTestComponent extends Component {
// 高精度大整数
@HighPrecision
public maxInt: number = 0;
// 高精度小浮点数
@Float64
public minFloat: number = 0;
// 普通数值
public normalNumber: number = 0;
// 字符串测试
public testString: string = '';
public longString: string = '';
constructor() {
super();
}
}
describe('SoA所有数据类型处理测试', () => {
let manager: ComponentStorageManager;
beforeEach(() => {
manager = new ComponentStorageManager();
});
test('验证所有基础类型的处理', () => {
console.log('\\n=== 测试所有数据类型 ===');
// 创建包含各种类型的组件
const originalComponent = new AllTypesComponent();
originalComponent.normalString = 'modified string';
originalComponent.longString = '测试中文字符串 with emoji 🎉';
originalComponent.intNumber = 999;
originalComponent.floatNumber = 2.718;
originalComponent.trueBoolean = false;
originalComponent.falseBoolean = true;
console.log('原始组件数据:', {
intNumber: originalComponent.intNumber,
floatNumber: originalComponent.floatNumber,
trueBoolean: originalComponent.trueBoolean,
falseBoolean: originalComponent.falseBoolean,
emptyString: `"${originalComponent.emptyString}"`,
normalString: `"${originalComponent.normalString}"`,
longString: `"${originalComponent.longString}"`,
arrayValue: originalComponent.arrayValue,
objectValue: originalComponent.objectValue
});
// 存储到SoA
manager.addComponent(1, originalComponent);
// 获取并验证
const retrievedComponent = manager.getComponent(1, AllTypesComponent);
console.log('\\n取回的组件数据:', {
intNumber: retrievedComponent?.intNumber,
floatNumber: retrievedComponent?.floatNumber,
trueBoolean: retrievedComponent?.trueBoolean,
falseBoolean: retrievedComponent?.falseBoolean,
emptyString: `"${retrievedComponent?.emptyString}"`,
normalString: `"${retrievedComponent?.normalString}"`,
longString: `"${retrievedComponent?.longString}"`,
arrayValue: retrievedComponent?.arrayValue,
objectValue: retrievedComponent?.objectValue
});
// 验证数值类型
expect(retrievedComponent?.intNumber).toBe(999);
expect(retrievedComponent?.floatNumber).toBeCloseTo(2.718);
// 验证布尔类型
expect(retrievedComponent?.trueBoolean).toBe(false);
expect(retrievedComponent?.falseBoolean).toBe(true);
// 验证字符串类型
expect(retrievedComponent?.emptyString).toBe('');
expect(retrievedComponent?.normalString).toBe('modified string');
expect(retrievedComponent?.longString).toBe('测试中文字符串 with emoji 🎉');
// 验证复杂类型
expect(retrievedComponent?.arrayValue).toEqual([1, 2, 3]);
expect(retrievedComponent?.objectValue).toEqual({ name: 'test' });
console.log('\\n✅ 所有类型验证完成');
});
test('边界情况测试', () => {
console.log('\\n=== 边界情况测试 ===');
const component = new BoundaryTestComponent();
// 特殊数值
component.maxInt = Number.MAX_SAFE_INTEGER;
component.minFloat = Number.MIN_VALUE;
component.normalNumber = -0;
// 特殊字符串
component.testString = '\\n\\t\\r"\'\\\\'; // 转义字符
component.longString = 'a'.repeat(1000); // 长字符串
manager.addComponent(1, component);
const retrieved = manager.getComponent(1, BoundaryTestComponent);
console.log('边界情况结果:', {
maxInt: retrieved?.maxInt,
minFloat: retrieved?.minFloat,
negativeZero: retrieved?.normalNumber,
escapeStr: retrieved?.testString,
longStr: retrieved?.longString?.length
});
expect(retrieved?.maxInt).toBe(Number.MAX_SAFE_INTEGER);
expect(retrieved?.minFloat).toBe(Number.MIN_VALUE);
expect(retrieved?.testString).toBe('\\n\\t\\r"\'\\\\');
expect(retrieved?.longString).toBe('a'.repeat(1000));
console.log('✅ 边界情况测试通过');
});
});