From ea340cde2172e3876a731e2456984db420e73aac Mon Sep 17 00:00:00 2001 From: gamer147 Date: Sun, 31 May 2026 16:03:06 -0400 Subject: [PATCH] =?UTF-8?q?test(inventory):=20lifecycle=20=E2=80=94=20disp?= =?UTF-8?q?ose=20rollback=20+=20use-after-commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- .../Inventory/InventoryLifecycleTests.cs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 SVSim.UnitTests/Services/Inventory/InventoryLifecycleTests.cs diff --git a/SVSim.UnitTests/Services/Inventory/InventoryLifecycleTests.cs b/SVSim.UnitTests/Services/Inventory/InventoryLifecycleTests.cs new file mode 100644 index 0000000..a9a5188 --- /dev/null +++ b/SVSim.UnitTests/Services/Inventory/InventoryLifecycleTests.cs @@ -0,0 +1,51 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using SVSim.Database; +using SVSim.Database.Enums; +using SVSim.Database.Services; +using SVSim.Database.Services.Inventory; +using SVSim.UnitTests.Infrastructure; + +namespace SVSim.UnitTests.Services.Inventory; + +public class InventoryLifecycleTests +{ + [Test] + public async Task Dispose_without_commit_does_not_persist() + { + using var factory = new SVSimTestFactory(); + long viewerId = await factory.SeedViewerAsync(); + using var scope = factory.Services.CreateScope(); + var ctx = scope.ServiceProvider.GetRequiredService(); + var v = await ctx.Viewers.FirstAsync(x => x.Id == viewerId); + v.Currency.Rupees = 100; + await ctx.SaveChangesAsync(); + + var inv = scope.ServiceProvider.GetRequiredService(); + await using (var tx = await inv.BeginAsync(viewerId)) + { + await tx.GrantAsync(UserGoodsType.Rupy, 0, 50); + // no commit; dispose runs + } + + using var verifyScope = factory.Services.CreateScope(); + var ctx2 = verifyScope.ServiceProvider.GetRequiredService(); + var v2 = await ctx2.Viewers.AsNoTracking().FirstAsync(x => x.Id == viewerId); + Assert.That(v2.Currency.Rupees, Is.EqualTo(100UL), "no persistence without commit"); + } + + [Test] + public async Task Use_after_commit_throws() + { + using var factory = new SVSimTestFactory(); + long viewerId = await factory.SeedViewerAsync(); + using var scope = factory.Services.CreateScope(); + var inv = scope.ServiceProvider.GetRequiredService(); + + await using var tx = await inv.BeginAsync(viewerId); + await tx.CommitAsync(); + + Assert.ThrowsAsync( + async () => { await tx.GrantAsync(UserGoodsType.Rupy, 0, 1); }); + } +}