移除过时类并标记组件和实体的update为过时方法

This commit is contained in:
YHH
2025-09-26 10:09:23 +08:00
parent 9603c6423b
commit cf9ea495d0
14 changed files with 19 additions and 1810 deletions

View File

@@ -1,60 +0,0 @@
import { EntityManager } from '../../../src/ECS/Core/EntityManager';
import { ComponentTypeManager } from '../../../src/ECS/Utils/ComponentTypeManager';
describe('批量创建功能测试', () => {
let entityManager: EntityManager;
beforeEach(() => {
ComponentTypeManager.instance.reset();
entityManager = new EntityManager();
});
test('批量创建实体应该使用ID作为名称', () => {
const entities = entityManager.createEntitiesBatch(5, "Test");
expect(entities).toHaveLength(5);
// 验证实体名称使用ID而不是索引
for (const entity of entities) {
expect(entity.name).toBe(`Test_${entity.id}`);
}
// 验证ID是唯一的
const ids = entities.map(e => e.id);
const uniqueIds = new Set(ids);
expect(uniqueIds.size).toBe(5);
});
test('单个创建实体应该使用ID作为默认名称', () => {
const entity1 = entityManager.createEntity();
const entity2 = entityManager.createEntity();
const entity3 = entityManager.createEntity("CustomName");
expect(entity1.name).toBe(`Entity_${entity1.id}`);
expect(entity2.name).toBe(`Entity_${entity2.id}`);
expect(entity3.name).toBe("CustomName");
// 确保ID是连续的或至少是唯一的
expect(entity1.id).not.toBe(entity2.id);
expect(entity2.id).not.toBe(entity3.id);
});
test('混合创建方式的名称应该一致', () => {
// 先单个创建
const single = entityManager.createEntity();
// 再批量创建
const batch = entityManager.createEntitiesBatch(3, "Batch");
// 再单个创建
const single2 = entityManager.createEntity();
// 验证名称格式一致
expect(single.name).toBe(`Entity_${single.id}`);
expect(single2.name).toBe(`Entity_${single2.id}`);
for (const entity of batch) {
expect(entity.name).toBe(`Batch_${entity.id}`);
}
});
});

View File

@@ -1,317 +0,0 @@
import { EntityManager } from '../../../src/ECS/Core/EntityManager';
import { ComponentTypeManager } from '../../../src/ECS/Utils/ComponentTypeManager';
import { Entity } from '../../../src/ECS/Entity';
import { Component } from '../../../src/ECS/Component';
// 测试用组件
class TestComponent extends Component {
public value: number = 0;
constructor(...args: unknown[]) {
super();
if (args.length >= 1) this.value = args[0] as number;
}
}
class AnotherTestComponent extends Component {
public name: string = 'test';
constructor(...args: unknown[]) {
super();
if (args.length >= 1) this.name = args[0] as string;
}
}
describe('ComponentIndexManager功能测试', () => {
let entityManager: EntityManager;
beforeEach(() => {
ComponentTypeManager.instance.reset();
entityManager = new EntityManager();
});
describe('基本功能测试', () => {
test('应该能够正确创建空实体', () => {
const entity = entityManager.createEntity('TestEntity');
expect(entity).toBeDefined();
expect(entity.name).toBe('TestEntity');
expect(entity.components.length).toBe(0);
expect(entity.id).toBeGreaterThanOrEqual(0);
});
test('应该能够正确管理实体的组件索引', () => {
const entity = entityManager.createEntity('TestEntity');
const component = new TestComponent(42);
// 添加组件前
expect(entity.hasComponent(TestComponent)).toBe(false);
// 添加组件
entity.addComponent(component);
// 添加组件后
expect(entity.hasComponent(TestComponent)).toBe(true);
expect(entity.getComponent(TestComponent)).toBe(component);
expect(entity.components.length).toBe(1);
});
test('应该能够正确处理组件查询', () => {
const entity1 = entityManager.createEntity('Entity1');
const entity2 = entityManager.createEntity('Entity2');
entity1.addComponent(new TestComponent(1));
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test2'));
// 查询包含TestComponent的实体
const entitiesWithTest = entityManager.getEntitiesWithComponent(TestComponent);
expect(entitiesWithTest).toHaveLength(2);
expect(entitiesWithTest).toContain(entity1);
expect(entitiesWithTest).toContain(entity2);
// 查询包含AnotherTestComponent的实体
const entitiesWithAnother = entityManager.getEntitiesWithComponent(AnotherTestComponent);
expect(entitiesWithAnother).toHaveLength(1);
expect(entitiesWithAnother).toContain(entity2);
});
test('应该能够正确处理复杂查询', () => {
const entity1 = entityManager.createEntity('Entity1');
const entity2 = entityManager.createEntity('Entity2');
const entity3 = entityManager.createEntity('Entity3');
// entity1: TestComponent
entity1.addComponent(new TestComponent(1));
// entity2: TestComponent + AnotherTestComponent
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test2'));
// entity3: AnotherTestComponent
entity3.addComponent(new AnotherTestComponent('test3'));
// AND查询同时包含两个组件的实体
const bothComponents = entityManager.queryWithComponentIndex(
[TestComponent, AnotherTestComponent],
'AND'
);
expect(bothComponents.size).toBe(1);
expect(bothComponents.has(entity2)).toBe(true);
// OR查询包含任一组件的实体
const eitherComponent = entityManager.queryWithComponentIndex(
[TestComponent, AnotherTestComponent],
'OR'
);
expect(eitherComponent.size).toBe(3);
expect(eitherComponent.has(entity1)).toBe(true);
expect(eitherComponent.has(entity2)).toBe(true);
expect(eitherComponent.has(entity3)).toBe(true);
});
});
describe('组件移除功能测试', () => {
test('应该能够手动管理组件索引', () => {
const entity1 = entityManager.createEntity('TestEntity1');
const entity2 = entityManager.createEntity('TestEntity2');
const component1 = new TestComponent(42);
const component2 = new TestComponent(84);
// 添加组件到实体
entity1.addComponent(component1);
entity2.addComponent(component2);
// 手动将实体添加到索引
entityManager['_componentIndexManager'].addEntity(entity1);
entityManager['_componentIndexManager'].addEntity(entity2);
// 验证能够查询到实体
let entitiesWithTest = entityManager.getEntitiesWithComponent(TestComponent);
expect(entitiesWithTest).toHaveLength(2);
expect(entitiesWithTest).toContain(entity1);
expect(entitiesWithTest).toContain(entity2);
// 手动移除一个实体的索引
entityManager['_componentIndexManager'].removeEntity(entity1);
// 验证只能查询到剩余的实体
entitiesWithTest = entityManager.getEntitiesWithComponent(TestComponent);
expect(entitiesWithTest).toHaveLength(1);
expect(entitiesWithTest[0]).toBe(entity2);
});
test('应该能够正确处理实体销毁', () => {
const entity = entityManager.createEntity('TestEntity');
entity.addComponent(new TestComponent(42));
// 确认实体存在且有组件
expect(entityManager.getEntity(entity.id)).toBe(entity);
expect(entityManager.getEntitiesWithComponent(TestComponent)).toHaveLength(1);
// 销毁实体
const destroyed = entityManager.destroyEntity(entity);
expect(destroyed).toBe(true);
// 确认实体被正确销毁
expect(entityManager.getEntity(entity.id)).toBeNull();
expect(entityManager.getEntitiesWithComponent(TestComponent)).toHaveLength(0);
});
});
describe('批量操作功能测试', () => {
test('应该能够正确处理批量创建实体', () => {
const entities = entityManager.createEntitiesBatch(5, 'BatchEntity');
expect(entities).toHaveLength(5);
entities.forEach((entity, index) => {
expect(entity.name).toMatch(/^BatchEntity_\d+$/);
expect(entity.components.length).toBe(0);
expect(entityManager.getEntity(entity.id)).toBe(entity);
});
expect(entityManager.entityCount).toBe(5);
});
test('批量创建的实体应该有正确的索引', () => {
const entities = entityManager.createEntitiesBatch(3, 'IndexTest');
// 给第一个和第三个实体添加组件
entities[0].addComponent(new TestComponent(1));
entities[2].addComponent(new TestComponent(3));
const entitiesWithTest = entityManager.getEntitiesWithComponent(TestComponent);
expect(entitiesWithTest).toHaveLength(2);
expect(entitiesWithTest).toContain(entities[0]);
expect(entitiesWithTest).toContain(entities[2]);
});
});
describe('查询构建器功能测试', () => {
test('应该能够使用查询构建器进行复杂查询', () => {
const entity1 = entityManager.createEntity('Active1');
const entity2 = entityManager.createEntity('Active2');
const entity3 = entityManager.createEntity('Inactive');
entity1.addComponent(new TestComponent(1));
entity1.active = true;
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test2'));
entity2.active = true;
entity3.addComponent(new TestComponent(3));
entity3.active = false;
// 查询激活状态且包含TestComponent的实体
const activeWithTest = entityManager.query()
.withAll(TestComponent)
.active()
.execute();
expect(activeWithTest).toHaveLength(2);
expect(activeWithTest).toContain(entity1);
expect(activeWithTest).toContain(entity2);
expect(activeWithTest).not.toContain(entity3);
// 查询同时包含两个组件的实体
const withBothComponents = entityManager.query()
.withAll(TestComponent, AnotherTestComponent)
.execute();
expect(withBothComponents).toHaveLength(1);
expect(withBothComponents).toContain(entity2);
});
test('查询构建器应该支持自定义过滤条件', () => {
const entity1 = entityManager.createEntity('Player1');
const entity2 = entityManager.createEntity('Enemy1');
const entity3 = entityManager.createEntity('Player2');
entity1.addComponent(new TestComponent(100));
entity2.addComponent(new TestComponent(50));
entity3.addComponent(new TestComponent(200));
// 查询名称以"Player"开头且TestComponent值大于150的实体
const strongPlayers = entityManager.query()
.withAll(TestComponent)
.where(entity => entity.name.startsWith('Player'))
.where(entity => {
const testComp = entity.getComponent(TestComponent);
return testComp !== null && testComp.value > 150;
})
.execute();
expect(strongPlayers).toHaveLength(1);
expect(strongPlayers).toContain(entity3);
});
});
describe('统计信息功能测试', () => {
test('应该能够获取正确的统计信息', () => {
// 创建一些实体和组件
const entity1 = entityManager.createEntity('StatTest1');
const entity2 = entityManager.createEntity('StatTest2');
entity1.addComponent(new TestComponent(1));
entity2.addComponent(new TestComponent(2));
entity2.addComponent(new AnotherTestComponent('test'));
const stats = entityManager.getOptimizationStats();
expect(stats).toBeDefined();
expect(stats.componentIndex).toBeDefined();
expect(stats.archetypeSystem).toBeDefined();
expect(stats.dirtyTracking).toBeDefined();
});
test('应该能够正确统计实体数量', () => {
expect(entityManager.entityCount).toBe(0);
expect(entityManager.activeEntityCount).toBe(0);
const entity1 = entityManager.createEntity('Count1');
const entity2 = entityManager.createEntity('Count2');
expect(entityManager.entityCount).toBe(2);
expect(entityManager.activeEntityCount).toBe(2);
entity1.active = false;
expect(entityManager.activeEntityCount).toBe(1);
entityManager.destroyEntity(entity2);
expect(entityManager.entityCount).toBe(1);
expect(entityManager.activeEntityCount).toBe(0);
});
});
describe('边界情况测试', () => {
test('应该能够处理空组件列表的查询', () => {
const entity = entityManager.createEntity('EmptyTest');
const emptyQuery = entityManager.queryWithComponentIndex([], 'AND');
expect(emptyQuery.size).toBe(0);
const emptyOrQuery = entityManager.queryWithComponentIndex([], 'OR');
expect(emptyOrQuery.size).toBe(0);
});
test('应该能够处理不存在的组件类型查询', () => {
class NonExistentComponent extends Component {}
const entities = entityManager.getEntitiesWithComponent(NonExistentComponent);
expect(entities).toHaveLength(0);
});
test('应该能够处理重复添加相同组件类型', () => {
const entity = entityManager.createEntity('DuplicateTest');
const component1 = new TestComponent(1);
const component2 = new TestComponent(2);
entity.addComponent(component1);
expect(() => entity.addComponent(component2)).toThrow();
// 第一个组件应该仍然存在
expect(entity.getComponent(TestComponent)).toBe(component1);
});
});
});

View File

@@ -1,626 +0,0 @@
import { EntityManager, EntityQueryBuilder } from '../../../src/ECS/Core/EntityManager';
import { Entity } from '../../../src/ECS/Entity';
import { Component } from '../../../src/ECS/Component';
// 测试组件
class PositionComponent extends Component {
public x: number;
public y: number;
constructor(...args: unknown[]) {
super();
const [x = 0, y = 0] = args as [number?, number?];
this.x = x;
this.y = y;
}
}
class VelocityComponent extends Component {
public vx: number;
public vy: number;
constructor(...args: unknown[]) {
super();
const [vx = 0, vy = 0] = args as [number?, number?];
this.vx = vx;
this.vy = vy;
}
}
class HealthComponent extends Component {
public health: number;
public maxHealth: number;
constructor(...args: unknown[]) {
super();
const [health = 100, maxHealth = 100] = args as [number?, number?];
this.health = health;
this.maxHealth = maxHealth;
}
}
class RenderComponent extends Component {
public visible: boolean;
public color: string;
constructor(...args: unknown[]) {
super();
const [visible = true, color = 'white'] = args as [boolean?, string?];
this.visible = visible;
this.color = color;
}
}
class AIComponent extends Component {
public intelligence: number;
constructor(...args: unknown[]) {
super();
const [intelligence = 50] = args as [number?];
this.intelligence = intelligence;
}
}
class PlayerComponent extends Component {
public name: string;
constructor(...args: unknown[]) {
super();
const [name = 'Player'] = args as [string?];
this.name = name;
}
}
describe('EntityManager - 实体管理器测试', () => {
let entityManager: EntityManager;
beforeEach(() => {
entityManager = new EntityManager();
});
describe('基本功能测试', () => {
test('应该能够创建EntityManager实例', () => {
expect(entityManager).toBeDefined();
expect(entityManager).toBeInstanceOf(EntityManager);
expect(entityManager.entityCount).toBe(0);
});
test('应该能够创建实体', () => {
const entity = entityManager.createEntity('TestEntity');
expect(entity).toBeDefined();
expect(entity.name).toBe('TestEntity');
expect(entity.id).toBeGreaterThan(0);
expect(entityManager.entityCount).toBe(1);
});
test('应该能够创建实体使用默认名称', () => {
const entity = entityManager.createEntity();
expect(entity).toBeDefined();
expect(entity.name).toContain('Entity_');
expect(entity.id).toBeGreaterThan(0);
});
test('应该能够批量创建实体', () => {
const entities: Entity[] = [];
for (let i = 0; i < 5; i++) {
entities.push(entityManager.createEntity(`Entity_${i}`));
}
expect(entities.length).toBe(5);
expect(entityManager.entityCount).toBe(5);
for (let i = 0; i < entities.length; i++) {
expect(entities[i].name).toBe(`Entity_${i}`);
expect(entities[i].id).toBeGreaterThan(0);
}
});
test('应该能够通过ID查找实体', () => {
const entity = entityManager.createEntity('TestEntity');
const found = entityManager.getEntity(entity.id);
expect(found).toBe(entity);
});
test('查找不存在的实体应该返回null', () => {
const found = entityManager.getEntity(999999);
expect(found).toBeNull();
});
test('应该能够销毁实体', () => {
const entity = entityManager.createEntity('TestEntity');
const entityId = entity.id;
const result = entityManager.destroyEntity(entity);
expect(result).toBe(true);
expect(entityManager.getEntity(entityId)).toBeNull();
expect(entityManager.entityCount).toBe(0);
});
test('应该能够通过ID销毁实体', () => {
const entity = entityManager.createEntity('TestEntity');
const entityId = entity.id;
const result = entityManager.destroyEntity(entityId);
expect(result).toBe(true);
expect(entityManager.getEntity(entityId)).toBeNull();
});
test('销毁不存在的实体应该返回false', () => {
const result = entityManager.destroyEntity(999999);
expect(result).toBe(false);
});
test('应该正确统计激活状态的实体', () => {
const entity1 = entityManager.createEntity('Active1');
const entity2 = entityManager.createEntity('Active2');
const entity3 = entityManager.createEntity('Inactive');
entity3.active = false;
expect(entityManager.activeEntityCount).toBe(2);
expect(entityManager.entityCount).toBe(3);
});
});
describe('实体标签功能测试', () => {
test('实体应该有默认标签', () => {
const entity = entityManager.createEntity('TaggedEntity');
expect(entity.tag).toBe(0); // 默认标签为0
});
test('应该能够为实体设置标签', () => {
const entity = entityManager.createEntity('TaggedEntity');
entity.tag = 1;
expect(entity.tag).toBe(1);
});
test('应该能够按标签查询实体', () => {
const entity1 = entityManager.createEntity('Entity1');
const entity2 = entityManager.createEntity('Entity2');
const entity3 = entityManager.createEntity('Entity3');
entity1.tag = 1;
entity2.tag = 1;
entity3.tag = 2;
const tag1Entities = entityManager.getEntitiesByTag(1);
const tag2Entities = entityManager.getEntitiesByTag(2);
expect(tag1Entities.length).toBe(2);
expect(tag2Entities.length).toBe(1);
expect(tag1Entities).toContain(entity1);
expect(tag1Entities).toContain(entity2);
expect(tag2Entities).toContain(entity3);
});
test('查询不存在的标签应该返回空数组', () => {
const entities = entityManager.getEntitiesByTag(999);
expect(entities).toEqual([]);
});
});
describe('查询构建器测试', () => {
let player: Entity;
let enemy1: Entity;
let enemy2: Entity;
let npc: Entity;
beforeEach(() => {
// 创建测试实体
player = entityManager.createEntity('Player');
player.addComponent(new PositionComponent(50, 50));
player.addComponent(new HealthComponent(100, 100));
player.addComponent(new PlayerComponent('Hero'));
player.tag = 1;
enemy1 = entityManager.createEntity('Enemy1');
enemy1.addComponent(new PositionComponent(10, 10));
enemy1.addComponent(new VelocityComponent(1, 0));
enemy1.addComponent(new HealthComponent(50, 50));
enemy1.addComponent(new AIComponent(30));
enemy1.tag = 2;
enemy2 = entityManager.createEntity('Enemy2');
enemy2.addComponent(new PositionComponent(90, 90));
enemy2.addComponent(new VelocityComponent(-1, 0));
enemy2.addComponent(new HealthComponent(75, 75));
enemy2.addComponent(new AIComponent(45));
enemy2.tag = 2;
npc = entityManager.createEntity('NPC');
npc.addComponent(new PositionComponent(25, 75));
npc.addComponent(new RenderComponent(true, 'blue'));
npc.tag = 3;
});
test('应该能够查询具有所有指定组件的实体', () => {
const results = entityManager.query()
.withAll(PositionComponent, HealthComponent)
.execute();
expect(results.length).toBe(3); // player, enemy1, enemy2
expect(results).toContain(player);
expect(results).toContain(enemy1);
expect(results).toContain(enemy2);
expect(results).not.toContain(npc);
});
test('应该能够查询具有任意指定组件的实体', () => {
const results = entityManager.query()
.withAny(PlayerComponent, AIComponent)
.execute();
expect(results.length).toBe(3); // player, enemy1, enemy2
expect(results).toContain(player);
expect(results).toContain(enemy1);
expect(results).toContain(enemy2);
expect(results).not.toContain(npc);
});
test('应该能够排除具有指定组件的实体', () => {
const results = entityManager.query()
.withAll(PositionComponent)
.without(AIComponent)
.execute();
expect(results.length).toBe(2); // player, npc
expect(results).toContain(player);
expect(results).toContain(npc);
expect(results).not.toContain(enemy1);
expect(results).not.toContain(enemy2);
});
test('应该能够按标签过滤实体', () => {
const results = entityManager.query()
.withTag(2)
.execute();
expect(results.length).toBe(2); // enemy1, enemy2
expect(results).toContain(enemy1);
expect(results).toContain(enemy2);
expect(results).not.toContain(player);
expect(results).not.toContain(npc);
});
test('应该能够排除特定标签的实体', () => {
const results = entityManager.query()
.withAll(PositionComponent)
.withoutTag(2)
.execute();
expect(results.length).toBe(2); // player, npc
expect(results).toContain(player);
expect(results).toContain(npc);
expect(results).not.toContain(enemy1);
expect(results).not.toContain(enemy2);
});
test('应该能够只查询激活状态的实体', () => {
enemy1.active = false;
const results = entityManager.query()
.withAll(PositionComponent, HealthComponent)
.active()
.execute();
expect(results.length).toBe(2); // player, enemy2
expect(results).toContain(player);
expect(results).toContain(enemy2);
expect(results).not.toContain(enemy1);
});
test('应该能够只查询启用状态的实体', () => {
npc.enabled = false;
const results = entityManager.query()
.withAll(PositionComponent)
.enabled()
.execute();
expect(results.length).toBe(3); // player, enemy1, enemy2
expect(results).toContain(player);
expect(results).toContain(enemy1);
expect(results).toContain(enemy2);
expect(results).not.toContain(npc);
});
test('应该能够使用自定义过滤条件', () => {
const results = entityManager.query()
.withAll(HealthComponent)
.where(entity => {
const health = entity.getComponent(HealthComponent);
return health!.health > 60;
})
.execute();
expect(results.length).toBe(2); // player, enemy2
expect(results).toContain(player);
expect(results).toContain(enemy2);
expect(results).not.toContain(enemy1);
});
test('应该能够组合多个查询条件', () => {
const results = entityManager.query()
.withAll(PositionComponent, HealthComponent)
.without(PlayerComponent)
.withTag(2)
.where(entity => {
const position = entity.getComponent(PositionComponent);
return position!.x < 50;
})
.execute();
expect(results.length).toBe(1); // enemy1
expect(results).toContain(enemy1);
expect(results).not.toContain(player);
expect(results).not.toContain(enemy2);
expect(results).not.toContain(npc);
});
test('空查询应该返回所有实体', () => {
const results = entityManager.query().execute();
expect(results.length).toBe(4); // all entities
expect(results).toContain(player);
expect(results).toContain(enemy1);
expect(results).toContain(enemy2);
expect(results).toContain(npc);
});
test('不匹配的查询应该返回空数组', () => {
const results = entityManager.query()
.withAll(PlayerComponent, AIComponent) // 不可能的组合
.execute();
expect(results).toEqual([]);
});
});
describe('事件系统集成', () => {
test('创建实体应该触发事件', () => {
let eventData: any = null;
entityManager.eventBus.onEntityCreated((data) => {
eventData = data;
});
const entity = entityManager.createEntity('EventEntity');
expect(eventData).toBeDefined();
expect(eventData.entityName).toBe('EventEntity');
expect(eventData.entityId).toBe(entity.id);
});
test('销毁实体应该触发事件', () => {
let eventData: any = null;
entityManager.eventBus.on('entity:destroyed', (data: any) => {
eventData = data;
});
const entity = entityManager.createEntity('EventEntity');
entityManager.destroyEntity(entity);
expect(eventData).toBeDefined();
expect(eventData.entityName).toBe('EventEntity');
expect(eventData.entityId).toBe(entity.id);
});
test('添加组件应该触发事件', () => {
let eventData: any = null;
entityManager.eventBus.onComponentAdded((data) => {
eventData = data;
});
const entity = entityManager.createEntity('ComponentEntity');
entity.addComponent(new PositionComponent(10, 20));
expect(eventData).toBeDefined();
expect(eventData.componentType).toBe('PositionComponent');
expect(eventData.entityId).toBe(entity.id);
});
test('移除组件应该触发事件', () => {
let eventData: any = null;
entityManager.eventBus.on('component:removed', (data: any) => {
eventData = data;
});
const entity = entityManager.createEntity('ComponentEntity');
const component = entity.addComponent(new PositionComponent(10, 20));
entity.removeComponent(component);
expect(eventData).toBeDefined();
expect(eventData.componentType).toBe('PositionComponent');
expect(eventData.entityId).toBe(entity.id);
});
});
describe('性能和内存测试', () => {
test('大量实体创建性能应该可接受', () => {
const entityCount = 10000;
const startTime = performance.now();
const entities: Entity[] = [];
for (let i = 0; i < entityCount; i++) {
entities.push(entityManager.createEntity(`PerfEntity_${i}`));
}
const endTime = performance.now();
const duration = endTime - startTime;
expect(entities.length).toBe(entityCount);
expect(entityManager.entityCount).toBe(entityCount);
// 性能记录实体创建性能数据不设硬阈值避免CI不稳定
console.log(`创建${entityCount}个实体耗时: ${duration.toFixed(2)}ms`);
});
test('大量实体查询性能应该可接受', () => {
const entityCount = 5000;
// 创建大量实体并添加组件
for (let i = 0; i < entityCount; i++) {
const entity = entityManager.createEntity(`Entity_${i}`);
entity.addComponent(new PositionComponent(i, i));
if (i % 2 === 0) {
entity.addComponent(new VelocityComponent(1, 1));
}
if (i % 3 === 0) {
entity.addComponent(new HealthComponent(100));
}
}
const startTime = performance.now();
// 执行多个查询
const positionResults = entityManager.query().withAll(PositionComponent).execute();
const velocityResults = entityManager.query().withAll(VelocityComponent).execute();
const healthResults = entityManager.query().withAll(HealthComponent).execute();
const complexResults = entityManager.query()
.withAll(PositionComponent, VelocityComponent)
.without(HealthComponent)
.execute();
const endTime = performance.now();
const duration = endTime - startTime;
expect(positionResults.length).toBe(entityCount);
expect(velocityResults.length).toBe(entityCount / 2);
expect(healthResults.length).toBe(Math.floor(entityCount / 3) + 1);
// 性能记录复杂查询性能数据不设硬阈值避免CI不稳定
console.log(`${entityCount}个实体的复杂查询耗时: ${duration.toFixed(2)}ms`);
});
test('实体销毁应该正确清理内存', () => {
const entityCount = 1000;
const entities: Entity[] = [];
// 创建实体
for (let i = 0; i < entityCount; i++) {
const entity = entityManager.createEntity(`MemoryEntity_${i}`);
entity.addComponent(new PositionComponent(0, 0));
entity.addComponent(new HealthComponent(100));
entities.push(entity);
}
expect(entityManager.entityCount).toBe(entityCount);
// 销毁所有实体
entities.forEach(entity => {
entityManager.destroyEntity(entity);
});
// 验证所有实体都已被清理
expect(entityManager.entityCount).toBe(0);
entities.forEach(entity => {
expect(entityManager.getEntity(entity.id)).toBeNull();
});
// 查询应该返回空结果
const positionResults = entityManager.query().withAll(PositionComponent).execute();
const healthResults = entityManager.query().withAll(HealthComponent).execute();
expect(positionResults).toEqual([]);
expect(healthResults).toEqual([]);
});
});
describe('错误处理和边界情况', () => {
test('对已销毁实体的查询操作应该安全处理', () => {
const entity = entityManager.createEntity('ToBeDestroyed');
entity.addComponent(new PositionComponent(0, 0));
entityManager.destroyEntity(entity);
// 查询不应该包含已销毁的实体
const results = entityManager.query().withAll(PositionComponent).execute();
expect(results).not.toContain(entity);
});
test('空查询构建器应该能正常工作', () => {
const builder = entityManager.query();
expect(() => {
const results = builder.execute();
expect(Array.isArray(results)).toBe(true);
}).not.toThrow();
});
test('重复销毁同一实体应该安全处理', () => {
const entity = entityManager.createEntity('TestEntity');
const result1 = entityManager.destroyEntity(entity);
const result2 = entityManager.destroyEntity(entity);
expect(result1).toBe(true);
expect(result2).toBe(false);
});
test('销毁实体后其组件应该正确清理', () => {
const entity = entityManager.createEntity('TestEntity');
entity.addComponent(new PositionComponent(10, 20));
entity.addComponent(new HealthComponent(100));
const initialPositionResults = entityManager.query().withAll(PositionComponent).execute();
expect(initialPositionResults).toContain(entity);
entityManager.destroyEntity(entity);
const finalPositionResults = entityManager.query().withAll(PositionComponent).execute();
expect(finalPositionResults).not.toContain(entity);
});
});
describe('统计和调试信息', () => {
test('应该能够获取实体管理器统计信息', () => {
// 创建一些实体和组件
const entities: Entity[] = [];
for (let i = 0; i < 10; i++) {
const entity = entityManager.createEntity(`StatsEntity_${i}`);
entity.addComponent(new PositionComponent(0, 0));
entities.push(entity);
}
// EntityManager doesn't have getStats method, use basic counts
expect(entityManager.entityCount).toBe(10);
expect(entityManager.activeEntityCount).toBe(10);
});
test('销毁实体后统计信息应该更新', () => {
const entities: Entity[] = [];
for (let i = 0; i < 5; i++) {
entities.push(entityManager.createEntity(`StatsEntity_${i}`));
}
entityManager.destroyEntity(entities[0]);
entityManager.destroyEntity(entities[1]);
expect(entityManager.entityCount).toBe(3);
expect(entityManager.activeEntityCount).toBe(3);
});
test('非激活实体应该在统计中正确反映', () => {
const entities: Entity[] = [];
for (let i = 0; i < 5; i++) {
entities.push(entityManager.createEntity(`StatsEntity_${i}`));
}
entities[0].active = false;
entities[1].active = false;
expect(entityManager.entityCount).toBe(5);
expect(entityManager.activeEntityCount).toBe(3);
});
});
});