import { BitMaskOptimizer } from '../../../src/ECS/Core/BitMaskOptimizer'; import { BigIntFactory } from '../../../src/ECS/Utils/BigIntCompatibility'; describe('BitMaskOptimizer - 位掩码优化器测试', () => { let optimizer: BitMaskOptimizer; beforeEach(() => { optimizer = BitMaskOptimizer.getInstance(); optimizer.reset(); // 确保每个测试开始时都是干净的状态 }); describe('单例模式测试', () => { it('应该返回同一个实例', () => { const instance1 = BitMaskOptimizer.getInstance(); const instance2 = BitMaskOptimizer.getInstance(); expect(instance1).toBe(instance2); }); }); describe('组件类型注册', () => { it('应该能够注册组件类型', () => { const id = optimizer.registerComponentType('Transform'); expect(id).toBe(0); }); it('重复注册相同组件应该返回相同ID', () => { const id1 = optimizer.registerComponentType('Transform'); const id2 = optimizer.registerComponentType('Transform'); expect(id1).toBe(id2); }); it('应该能够注册多个不同组件类型', () => { const id1 = optimizer.registerComponentType('Transform'); const id2 = optimizer.registerComponentType('Velocity'); const id3 = optimizer.registerComponentType('Health'); expect(id1).toBe(0); expect(id2).toBe(1); expect(id3).toBe(2); }); it('应该能够获取已注册组件的类型ID', () => { optimizer.registerComponentType('Transform'); const id = optimizer.getComponentTypeId('Transform'); expect(id).toBe(0); }); it('获取未注册组件的类型ID应该返回undefined', () => { const id = optimizer.getComponentTypeId('UnknownComponent'); expect(id).toBeUndefined(); }); }); describe('单组件掩码创建', () => { beforeEach(() => { optimizer.registerComponentType('Transform'); optimizer.registerComponentType('Velocity'); }); it('应该能够创建单个组件的掩码', () => { const mask = optimizer.createSingleComponentMask('Transform'); expect(mask.toString()).toBe('1'); }); it('不同组件应该有不同的掩码', () => { const transformMask = optimizer.createSingleComponentMask('Transform'); const velocityMask = optimizer.createSingleComponentMask('Velocity'); expect(transformMask.toString()).toBe('1'); expect(velocityMask.toString()).toBe('2'); }); it('创建未注册组件的掩码应该抛出错误', () => { expect(() => { optimizer.createSingleComponentMask('UnknownComponent'); }).toThrow('Component type not registered: UnknownComponent'); }); it('相同组件的掩码应该使用缓存', () => { const mask1 = optimizer.createSingleComponentMask('Transform'); const mask2 = optimizer.createSingleComponentMask('Transform'); expect(mask1).toBe(mask2); }); }); describe('组合掩码创建', () => { beforeEach(() => { optimizer.registerComponentType('Transform'); optimizer.registerComponentType('Velocity'); optimizer.registerComponentType('Health'); }); it('应该能够创建多个组件的组合掩码', () => { const mask = optimizer.createCombinedMask(['Transform', 'Velocity']); expect(mask.toString()).toBe('3'); // 1 | 2 = 3 }); it('组件顺序不应该影响掩码结果', () => { const mask1 = optimizer.createCombinedMask(['Transform', 'Velocity']); const mask2 = optimizer.createCombinedMask(['Velocity', 'Transform']); expect(mask1).toBe(mask2); }); it('三个组件的组合掩码应该正确', () => { const mask = optimizer.createCombinedMask(['Transform', 'Velocity', 'Health']); expect(mask.toString()).toBe('7'); // 1 | 2 | 4 = 7 }); it('空数组应该返回0掩码', () => { const mask = optimizer.createCombinedMask([]); expect(mask.isZero()).toBe(true); }); it('包含未注册组件应该抛出错误', () => { expect(() => { optimizer.createCombinedMask(['Transform', 'UnknownComponent']); }).toThrow('Component type not registered: UnknownComponent'); }); }); describe('掩码检查功能', () => { beforeEach(() => { optimizer.registerComponentType('Transform'); optimizer.registerComponentType('Velocity'); optimizer.registerComponentType('Health'); }); it('应该能够检查掩码是否包含指定组件', () => { const mask = optimizer.createCombinedMask(['Transform', 'Velocity']); expect(optimizer.maskContainsComponent(mask, 'Transform')).toBe(true); expect(optimizer.maskContainsComponent(mask, 'Velocity')).toBe(true); expect(optimizer.maskContainsComponent(mask, 'Health')).toBe(false); }); it('应该能够检查掩码是否包含所有指定组件', () => { const mask = optimizer.createCombinedMask(['Transform', 'Velocity', 'Health']); expect(optimizer.maskContainsAllComponents(mask, ['Transform'])).toBe(true); expect(optimizer.maskContainsAllComponents(mask, ['Transform', 'Velocity'])).toBe(true); expect(optimizer.maskContainsAllComponents(mask, ['Transform', 'Velocity', 'Health'])).toBe(true); }); it('不完全包含时maskContainsAllComponents应该返回false', () => { const mask = optimizer.createCombinedMask(['Transform']); expect(optimizer.maskContainsAllComponents(mask, ['Transform', 'Velocity'])).toBe(false); }); it('应该能够检查掩码是否包含任一指定组件', () => { const mask = optimizer.createCombinedMask(['Transform']); expect(optimizer.maskContainsAnyComponent(mask, ['Transform', 'Velocity'])).toBe(true); expect(optimizer.maskContainsAnyComponent(mask, ['Velocity', 'Health'])).toBe(false); }); }); describe('掩码操作功能', () => { beforeEach(() => { optimizer.registerComponentType('Transform'); optimizer.registerComponentType('Velocity'); optimizer.registerComponentType('Health'); }); it('应该能够向掩码添加组件', () => { let mask = optimizer.createSingleComponentMask('Transform'); mask = optimizer.addComponentToMask(mask, 'Velocity'); expect(optimizer.maskContainsComponent(mask, 'Transform')).toBe(true); expect(optimizer.maskContainsComponent(mask, 'Velocity')).toBe(true); }); it('应该能够从掩码移除组件', () => { let mask = optimizer.createCombinedMask(['Transform', 'Velocity']); mask = optimizer.removeComponentFromMask(mask, 'Velocity'); expect(optimizer.maskContainsComponent(mask, 'Transform')).toBe(true); expect(optimizer.maskContainsComponent(mask, 'Velocity')).toBe(false); }); it('移除不存在的组件不应该影响掩码', () => { const originalMask = optimizer.createSingleComponentMask('Transform'); const newMask = optimizer.removeComponentFromMask(originalMask, 'Velocity'); expect(newMask.equals(originalMask)).toBe(true); }); }); describe('工具功能', () => { beforeEach(() => { optimizer.registerComponentType('Transform'); optimizer.registerComponentType('Velocity'); optimizer.registerComponentType('Health'); }); it('应该能够将掩码转换为组件名称数组', () => { const mask = optimizer.createCombinedMask(['Transform', 'Health']); const componentNames = optimizer.maskToComponentNames(mask); expect(componentNames).toContain('Transform'); expect(componentNames).toContain('Health'); expect(componentNames).not.toContain('Velocity'); expect(componentNames.length).toBe(2); }); it('空掩码应该返回空数组', () => { const componentNames = optimizer.maskToComponentNames(BigIntFactory.zero()); expect(componentNames).toEqual([]); }); it('应该能够获取掩码中组件的数量', () => { const mask1 = optimizer.createSingleComponentMask('Transform'); const mask2 = optimizer.createCombinedMask(['Transform', 'Velocity']); const mask3 = optimizer.createCombinedMask(['Transform', 'Velocity', 'Health']); expect(optimizer.getComponentCount(mask1)).toBe(1); expect(optimizer.getComponentCount(mask2)).toBe(2); expect(optimizer.getComponentCount(mask3)).toBe(3); }); it('空掩码的组件数量应该为0', () => { expect(optimizer.getComponentCount(BigIntFactory.zero())).toBe(0); }); }); describe('缓存和性能优化', () => { beforeEach(() => { optimizer.registerComponentType('Transform'); optimizer.registerComponentType('Velocity'); optimizer.registerComponentType('Health'); }); it('应该能够预计算常用掩码组合', () => { const commonCombinations = [ ['Transform', 'Velocity'], ['Transform', 'Health'], ['Velocity', 'Health'] ]; optimizer.precomputeCommonMasks(commonCombinations); // 验证掩码已被缓存 const stats = optimizer.getCacheStats(); expect(stats.size).toBeGreaterThan(0); }); it('应该能够获取缓存统计信息', () => { optimizer.createSingleComponentMask('Transform'); optimizer.createCombinedMask(['Transform', 'Velocity']); const stats = optimizer.getCacheStats(); expect(stats.size).toBeGreaterThan(0); expect(stats.componentTypes).toBe(3); }); it('应该能够清空缓存', () => { optimizer.createSingleComponentMask('Transform'); optimizer.clearCache(); const stats = optimizer.getCacheStats(); expect(stats.size).toBe(0); expect(stats.componentTypes).toBe(3); // 组件类型不会被清除 }); it('应该能够重置优化器', () => { optimizer.registerComponentType('NewComponent'); optimizer.createSingleComponentMask('Transform'); optimizer.reset(); const stats = optimizer.getCacheStats(); expect(stats.size).toBe(0); expect(stats.componentTypes).toBe(0); }); }); describe('边界情况和错误处理', () => { it('处理大量组件类型注册', () => { for (let i = 0; i < 100; i++) { const id = optimizer.registerComponentType(`Component${i}`); expect(id).toBe(i); } }); it('处理大掩码值', () => { // 注册64个组件类型 for (let i = 0; i < 64; i++) { optimizer.registerComponentType(`Component${i}`); } const mask = optimizer.createSingleComponentMask('Component63'); expect(mask.toString()).toBe(BigIntFactory.one().shiftLeft(63).toString()); }); it('空组件名称数组的组合掩码', () => { const mask = optimizer.createCombinedMask([]); expect(mask.isZero()).toBe(true); expect(optimizer.getComponentCount(mask)).toBe(0); }); }); describe('性能测试', () => { beforeEach(() => { // 注册一些组件类型 for (let i = 0; i < 10; i++) { optimizer.registerComponentType(`Component${i}`); } }); it('大量掩码创建应该高效', () => { const startTime = performance.now(); for (let i = 0; i < 1000; i++) { optimizer.createSingleComponentMask('Component0'); } const endTime = performance.now(); expect(endTime - startTime).toBeLessThan(100); // 应该在100ms内完成 }); it('大量掩码检查应该高效', () => { const mask = optimizer.createCombinedMask(['Component0', 'Component1', 'Component2']); const startTime = performance.now(); for (let i = 0; i < 10000; i++) { optimizer.maskContainsComponent(mask, 'Component1'); } const endTime = performance.now(); expect(endTime - startTime).toBeLessThan(100); // 应该在100ms内完成 }); }); });