using System.Collections.Generic; using System.Linq; using AcDream.App.Rendering; using Xunit; namespace AcDream.App.Tests.Rendering; public sealed class BuildingGroupScratchTests { [Fact] public void Rebuild_DropsHistoricalKeys_BoundsRetention_AndPreservesEncounterOrder() { var scratch = new BuildingGroupScratch(); int pathologicalCount = BuildingGroupScratch.MaxRetainedGroups * 4; var pathological = new List(pathologicalCount); for (int i = 0; i < pathologicalCount; i++) { pathological.Add(new LoadedCell { CellId = (uint)i + 1u, BuildingId = 0x1000_0000u + (uint)i, }); } scratch.Rebuild(pathological); Assert.Equal(pathologicalCount, scratch.ActiveGroupCount); Assert.True(scratch.MapCapacity > BuildingGroupScratch.MaxRetainedGroups); var firstA = new LoadedCell { CellId = 0xAA01u, BuildingId = 0x20u }; var second = new LoadedCell { CellId = 0xBB01u, BuildingId = 0x10u }; var firstB = new LoadedCell { CellId = 0xAA02u, BuildingId = 0x20u }; var unstamped = new LoadedCell { CellId = 0xCC01u }; scratch.Rebuild([firstA, second, firstB, unstamped]); Assert.Equal(3, scratch.ActiveGroupCount); Assert.Equal( new uint[] { 0x20u, 0x10u, unstamped.CellId }, scratch.Groups.Keys.ToArray()); Assert.Equal(new[] { firstA, firstB }, scratch.Groups[0x20u]); Assert.Equal(new[] { second }, scratch.Groups[0x10u]); Assert.Equal(new[] { unstamped }, scratch.Groups[unstamped.CellId]); Assert.DoesNotContain( scratch.Groups.Keys, key => key >= 0x1000_0000u); Assert.InRange( scratch.RetainedListCount, 0, BuildingGroupScratch.MaxRetainedGroups); Assert.InRange( scratch.MapCapacity, 0, BuildingGroupScratch.MaxRetainedGroups); scratch.Reset(); Assert.Equal(0, scratch.ActiveGroupCount); Assert.Empty(scratch.Groups); Assert.InRange( scratch.RetainedListCount, 0, BuildingGroupScratch.MaxRetainedGroups); Assert.InRange( scratch.MapCapacity, 0, BuildingGroupScratch.MaxRetainedGroups); } [Fact] public void Reset_DoesNotRetainPathologicalGroupBackingArray() { var scratch = new BuildingGroupScratch(); var oversizedGroup = new List( BuildingGroupScratch.MaxRetainedCellsPerGroup * 2); for (int i = 0; i < BuildingGroupScratch.MaxRetainedCellsPerGroup * 2; i++) { oversizedGroup.Add(new LoadedCell { CellId = (uint)i + 1u, BuildingId = 0x42u, }); } scratch.Rebuild(oversizedGroup); Assert.Single(scratch.Groups); Assert.True( scratch.Groups[0x42u].Capacity > BuildingGroupScratch.MaxRetainedCellsPerGroup); scratch.Reset(); Assert.Equal(0, scratch.RetainedListCount); Assert.Empty(scratch.Groups); } } public sealed class RetailPViewScratchRetentionTests { [Fact] public void ClearFrameBuffers_DropsPathologicalHighWater_AfterIdleHysteresis() { var retention = new RetailPViewScratchRetention(); int pathologicalCellCount = RetailPViewScratchRetention.MaxRetainedCellItems * 4; int pathologicalFrameCount = RetailPViewScratchRetention.MaxRetainedLookInFrames * 4; var lookInFrames = new List(pathologicalFrameCount); var lookInPrepare = new HashSet(); var drawableCells = new HashSet(); var shellBatch = new HashSet(); var orderedTransparent = new List(pathologicalCellCount); for (int i = 0; i < pathologicalFrameCount; i++) lookInFrames.Add(new PortalVisibilityFrame()); for (int i = 0; i < pathologicalCellCount; i++) { uint id = (uint)i; lookInPrepare.Add(id); drawableCells.Add(id); shellBatch.Add(id); orderedTransparent.Add(id); } Assert.True( lookInFrames.Capacity > RetailPViewScratchRetention.MaxRetainedLookInFrames); Assert.True( drawableCells.EnsureCapacity(0) > RetailPViewScratchRetention.MaxRetainedCellItems); retention.ClearFrameBuffers( lookInFrames, lookInPrepare, drawableCells, shellBatch, orderedTransparent); Assert.Empty(lookInFrames); Assert.Empty(lookInPrepare); Assert.Empty(drawableCells); Assert.Empty(shellBatch); Assert.Empty(orderedTransparent); Assert.True( lookInFrames.Capacity > RetailPViewScratchRetention.MaxRetainedLookInFrames); for (int i = 0; i < RetailPViewScratchRetention.CapacityTrimIdleFrames; i++) { retention.ClearFrameBuffers( lookInFrames, lookInPrepare, drawableCells, shellBatch, orderedTransparent); } Assert.InRange( lookInFrames.Capacity, 0, RetailPViewScratchRetention.MaxRetainedLookInFrames); Assert.InRange( lookInPrepare.EnsureCapacity(0), 0, RetailPViewScratchRetention.MaxRetainedCellItems); Assert.InRange( drawableCells.EnsureCapacity(0), 0, RetailPViewScratchRetention.MaxRetainedCellItems); Assert.InRange( shellBatch.EnsureCapacity(0), 0, RetailPViewScratchRetention.MaxRetainedCellItems); Assert.InRange( orderedTransparent.Capacity, 0, RetailPViewScratchRetention.MaxRetainedCellItems); } [Fact] public void ClearFrameBuffers_PreservesNormalWarmCapacity() { var retention = new RetailPViewScratchRetention(); var lookInFrames = new List(8); var lookInPrepare = new HashSet(); var drawableCells = new HashSet(); var shellBatch = new HashSet(); var orderedTransparent = new List(64); for (uint id = 0; id < 64; id++) { lookInPrepare.Add(id); drawableCells.Add(id); shellBatch.Add(id); orderedTransparent.Add(id); } int lookInCapacity = lookInFrames.Capacity; int prepareCapacity = lookInPrepare.EnsureCapacity(0); int drawableCapacity = drawableCells.EnsureCapacity(0); int shellCapacity = shellBatch.EnsureCapacity(0); int transparentCapacity = orderedTransparent.Capacity; retention.ClearFrameBuffers( lookInFrames, lookInPrepare, drawableCells, shellBatch, orderedTransparent); Assert.Equal(lookInCapacity, lookInFrames.Capacity); Assert.Equal(prepareCapacity, lookInPrepare.EnsureCapacity(0)); Assert.Equal(drawableCapacity, drawableCells.EnsureCapacity(0)); Assert.Equal(shellCapacity, shellBatch.EnsureCapacity(0)); Assert.Equal(transparentCapacity, orderedTransparent.Capacity); } [Fact] public void ClearFrameBuffers_RecurringLargeWorkingSet_PreservesWarmCapacity() { const int recurringCount = RetailPViewScratchRetention.MaxRetainedCellItems + 163; var retention = new RetailPViewScratchRetention(); var lookInFrames = new List(); var lookInPrepare = new HashSet(); var drawableCells = new HashSet(); var shellBatch = new HashSet(); var orderedTransparent = new List(); for (int iteration = 0; iteration < RetailPViewScratchRetention.CapacityTrimIdleFrames + 5; iteration++) { for (int i = 0; i < recurringCount; i++) { uint id = (uint)i; drawableCells.Add(id); orderedTransparent.Add(id); } int drawableCapacity = drawableCells.EnsureCapacity(0); int transparentCapacity = orderedTransparent.Capacity; retention.ClearFrameBuffers( lookInFrames, lookInPrepare, drawableCells, shellBatch, orderedTransparent); Assert.Equal(drawableCapacity, drawableCells.EnsureCapacity(0)); Assert.Equal(transparentCapacity, orderedTransparent.Capacity); } } }