Files
TheriapolisV3/Theriapolis.Tests/WorldCache.cs
T
Christopher Wiebe b451f83174 Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback
anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md).
All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:40:51 -07:00

54 lines
2.1 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 Theriapolis.Core.World.Generation;
namespace Theriapolis.Tests;
/// <summary>
/// Class-level fixture that memoizes worldgen pipeline runs so multiple tests
/// in the same class (all hitting e.g. seed 0xCAFEBABE) share one expensive run.
///
/// Each test class gets its own WorldCache via <see cref="Xunit.IClassFixture{T}"/>,
/// which keeps cross-class parallelism intact while collapsing within-class duplicate
/// runs. A full pipeline takes ~30s; a test class that previously did 9 runs now does 1.
///
/// Cache key is (seed, stageThroughIndex, variant):
/// - stageThroughIndex = -1 means RunAll; otherwise RunThrough(ctx, idx).
/// - variant is used by determinism tests that intentionally want TWO independent
/// runs of the same seed to compare: pass variant 0 and variant 1.
/// </summary>
public sealed class WorldCache : IDisposable
{
private readonly Dictionary<(ulong Seed, int Stage, int Variant), WorldGenContext> _cache = new();
private readonly object _lock = new();
/// <summary>Full pipeline run for <paramref name="seed"/>, memoized.</summary>
public WorldGenContext Get(ulong seed, int variant = 0) =>
GetInternal(seed, stageThroughIndex: -1, variant);
/// <summary>
/// Partial pipeline run through stage index (0-based), memoized.
/// E.g. <c>GetThrough(seed, 9)</c> runs stages 110 (HydrologyGen).
/// </summary>
public WorldGenContext GetThrough(ulong seed, int stageThroughIndex, int variant = 0) =>
GetInternal(seed, stageThroughIndex, variant);
private WorldGenContext GetInternal(ulong seed, int stageThroughIndex, int variant)
{
var key = (seed, stageThroughIndex, variant);
lock (_lock)
{
if (_cache.TryGetValue(key, out var cached)) return cached;
var ctx = new WorldGenContext(seed, TestHelpers.DataDirectory);
if (stageThroughIndex < 0)
WorldGenerator.RunAll(ctx);
else
WorldGenerator.RunThrough(ctx, stageThroughIndex);
_cache[key] = ctx;
return ctx;
}
}
public void Dispose() => _cache.Clear();
}