using NUnit.Framework;
using ProjectM.Simulation;
using Unity.Collections;
using Unity.Entities;
namespace ProjectM.Tests
{
///
/// Pins the room-scoped teardown contract (): destroying room i kills ONLY
/// room-i entities — the other room survives (the DR-031/DR-040 cross-room-wipe regression, load-bearing for the
/// ping-pong sub-slot handoff where two rooms transiently coexist), untagged entities are untouched, and each
/// entity is destroyed at most once (single-visit ⇒ no double-destroy Playback throw).
///
public class RoomTeardownTests
{
static Entity MakeRoomEntity(EntityManager em, byte room, bool asNode)
{
// Mimic real room content: some entities look like resource nodes, some like zone enemies — the
// teardown must be type-agnostic (RoomTag is the only contract).
var e = asNode
? em.CreateEntity(typeof(RoomTag), typeof(ResourceNode))
: em.CreateEntity(typeof(RoomTag), typeof(ZoneEnemyTag));
em.SetComponentData(e, new RoomTag { Room = room });
return e;
}
[Test]
public void DestroyRoom_KillsOnlyThatRoom_SparesOtherRoomAndUntagged()
{
using var world = new World("RoomTeardownTest");
var em = world.EntityManager;
for (int i = 0; i < 3; i++) MakeRoomEntity(em, 0, asNode: i % 2 == 0); // room 0: 3 entities
for (int i = 0; i < 2; i++) MakeRoomEntity(em, 1, asNode: i % 2 == 0); // room 1: 2 entities
var untagged = em.CreateEntity(typeof(ResourceNode)); // e.g. a base-field node
using var roomQuery = em.CreateEntityQuery(typeof(RoomTag));
var ecb = new EntityCommandBuffer(Allocator.Temp);
int destroyed = RoomTeardown.DestroyRoom(roomQuery, ecb, 0);
ecb.Playback(em);
ecb.Dispose();
Assert.AreEqual(3, destroyed, "exactly room-0's entities were queued");
using var remaining = em.CreateEntityQuery(typeof(RoomTag));
var tags = remaining.ToComponentDataArray(Allocator.Temp);
Assert.AreEqual(2, tags.Length, "room 1 survives intact");
for (int i = 0; i < tags.Length; i++)
Assert.AreEqual(1, tags[i].Room, "every survivor belongs to room 1");
tags.Dispose();
Assert.IsTrue(em.Exists(untagged), "untagged (non-room) entities are never touched");
}
[Test]
public void DestroyRoom_EmptyRoom_IsANoOp()
{
using var world = new World("RoomTeardownTest2");
var em = world.EntityManager;
MakeRoomEntity(em, 1, asNode: true);
using var roomQuery = em.CreateEntityQuery(typeof(RoomTag));
var ecb = new EntityCommandBuffer(Allocator.Temp);
int destroyed = RoomTeardown.DestroyRoom(roomQuery, ecb, 0); // room 0 has nothing
ecb.Playback(em);
ecb.Dispose();
Assert.AreEqual(0, destroyed);
using var remaining = em.CreateEntityQuery(typeof(RoomTag));
Assert.AreEqual(1, remaining.CalculateEntityCount(), "room 1 untouched");
}
}
}