using NUnit.Framework;
using ProjectM.Simulation;
using Unity.Collections;
using Unity.Entities;
namespace ProjectM.Tests
{
///
/// Regression guard for the Phase 1 inline-mod design: returns the
/// def BY VALUE, so the inline slots must survive that copy. (A nested BlobArray of
/// mods would corrupt its relative-offset pointer on this copy and read empty — the blocker the inline layout
/// avoids.) Looks up the SECOND item by id and reads a non-zero mod value: an index-1 lookup + a non-zero read
/// is exactly what would expose an offset corruption that a length-only check on item 0 could miss.
///
public class ItemDatabaseBlobTests
{
[Test]
public void TryGetItem_RoundTrips_Inline_Mods_For_Second_Item()
{
var builder = new BlobBuilder(Allocator.Temp);
ref var root = ref builder.ConstructRoot();
var arr = builder.Allocate(ref root.Items, 2);
arr[0] = new ItemDefBlob { ItemId = 100, EquipSlot = EquipSlotId.Weapon };
arr[1] = new ItemDefBlob
{
ItemId = 101,
EquipSlot = EquipSlotId.Armor,
Mod0 = new ItemModSpec { Target = (byte)StatTarget.MoveSpeed, Op = (byte)ModOp.PercentAdd, Value = 0.25f },
Mod1 = new ItemModSpec { Target = (byte)StatTarget.Damage, Op = (byte)ModOp.Flat, Value = 7f },
Mod2 = new ItemModSpec { Target = 255 },
Mod3 = new ItemModSpec { Target = 255 },
};
var blob = builder.CreateBlobAssetReference(Allocator.Persistent);
builder.Dispose();
try
{
ref var db = ref blob.Value;
Assert.IsTrue(db.TryGetItem(101, out var def), "Second item resolves by id.");
Assert.AreEqual(EquipSlotId.Armor, def.EquipSlot);
var m0 = def.GetMod(0);
Assert.AreEqual((byte)StatTarget.MoveSpeed, m0.Target, "Inline Mod0 target survives the by-value copy.");
Assert.AreEqual(0.25f, m0.Value, 1e-4f, "Inline Mod0 value survives the by-value copy (would read 0 under a nested-blob corruption).");
var m1 = def.GetMod(1);
Assert.AreEqual((byte)StatTarget.Damage, m1.Target);
Assert.AreEqual(7f, m1.Value, 1e-4f);
Assert.AreEqual(255, def.GetMod(2).Target, "Unused inline slots stay 255.");
}
finally { blob.Dispose(); }
}
}
}