acdream/tests/AcDream.Core.Tests/Streaming/StreamingRegionTests.cs
Erik 9d1c2c45e5 feat(app): Phase A.1 — job + result records for LandblockStreamer
LandblockStreamJob (Load/Unload) and LandblockStreamResult
(Loaded/Failed/Unloaded) are the channel payload types the next
task's LandblockStreamer will use. Separate file because they're
shared between the worker thread and the render thread and deserve
a focused home.

Folds in two carryover nits from the Task 1 fix review:
- Stale "radius + 1" comments in StreamingRegionTests updated to
  match the real radius+2 threshold (no numeric-assertion changes).
- Single-step recenter test now asserts Visible.Count == 25 and
  Resident.Count == 30, locking in the Visible/Resident semantic
  split behaviorally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:11:35 +02:00

113 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AcDream.App.Streaming;
using Xunit;
namespace AcDream.Core.Tests.Streaming;
public class StreamingRegionTests
{
[Fact]
public void Constructor_Radius2_Produces25Landblocks()
{
var region = new StreamingRegion(cx: 50, cy: 50, radius: 2);
Assert.Equal(25, region.Visible.Count);
}
[Fact]
public void Constructor_NearOrigin_ClampsToWorldEdge()
{
// Center at (0, 0) with radius 2: only the +X / +Y quadrant is
// in-bounds. That's a 3×3 subset of the 5×5 window = 9 landblocks.
var region = new StreamingRegion(cx: 0, cy: 0, radius: 2);
Assert.Equal(9, region.Visible.Count);
}
[Fact]
public void Constructor_NearFarEdge_ClampsToWorldEdge()
{
var region = new StreamingRegion(cx: 0xFF, cy: 0xFF, radius: 2);
Assert.Equal(9, region.Visible.Count);
}
[Fact]
public void RecenterTo_SamePosition_EmptyDiff()
{
var region = new StreamingRegion(cx: 50, cy: 50, radius: 2);
var diff = region.RecenterTo(50, 50);
Assert.Empty(diff.ToLoad);
Assert.Empty(diff.ToUnload);
}
[Fact]
public void RecenterTo_SingleStepEast_LoadsColumn_NoUnloadsDueToHysteresis()
{
// Radius 2 → unload threshold is radius+2 = 4.
// Starting center (50,50) covers X in [48..52]. Step to (51,50):
// new coverage X in [49..53]. New column is x=53 (5 entries).
// Departing column x=48 is at distance |48-51| = 3, which is within
// the radius+2 threshold, so it stays loaded (hysteresis keeps radius+2).
var region = new StreamingRegion(cx: 50, cy: 50, radius: 2);
var diff = region.RecenterTo(51, 50);
Assert.Equal(5, diff.ToLoad.Count);
Assert.Empty(diff.ToUnload);
// Visible is strictly the 5×5 window around (51, 50).
Assert.Equal(25, region.Visible.Count);
// Resident includes the hysteresis-retained x=48 column (5 entries)
// plus the full new window, for 30 total.
Assert.Equal(30, region.Resident.Count);
}
[Fact]
public void RecenterTo_ThreeStepEast_LoadsAndUnloadsColumns()
{
// Starting (50,50) covers X in [48..52]. Step to (53,50):
// new coverage X in [51..55]. New columns: x=53,54,55 (15 entries).
// x=48 is now 5 away, > radius+2 = 4 → unload. x=49 is 4 away, not > 4 → keep. x=50 is 3 away, not > 4 → keep.
var region = new StreamingRegion(cx: 50, cy: 50, radius: 2);
var diff = region.RecenterTo(53, 50);
Assert.Equal(15, diff.ToLoad.Count);
Assert.Equal(5, diff.ToUnload.Count);
}
[Fact]
public void RecenterTo_LongTeleport_UnloadsEverythingLoadsEverything()
{
var region = new StreamingRegion(cx: 50, cy: 50, radius: 2);
var diff = region.RecenterTo(200, 200);
Assert.Equal(25, diff.ToLoad.Count);
Assert.Equal(25, diff.ToUnload.Count);
}
[Fact]
public void Constructor_NearXEdgeOnly_ClampsOnlyXAxis()
{
// cx=0, cy=50, radius=2:
// X is clamped to [0..2] (3 entries)
// Y is unclamped [48..52] (5 entries)
// Total = 3 × 5 = 15 landblocks.
var region = new StreamingRegion(cx: 0, cy: 50, radius: 2);
Assert.Equal(15, region.Visible.Count);
}
[Fact]
public void Constructor_SmallRadius_IDsMatchEncodingRule()
{
// Verify EncodeLandblockId is correct (not swapped shifts).
// radius=0 at (0x12, 0x34) → exactly one entry, id = 0x1234FFFE.
var region = new StreamingRegion(cx: 0x12, cy: 0x34, radius: 0);
Assert.Single(region.Visible);
Assert.Contains(0x1234FFFEu, region.Visible);
}
}