Files
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

75 lines
2.5 KiB
C#

using Theriapolis.Core;
using Theriapolis.Core.Persistence;
using Theriapolis.Core.Persistence.SaveMigrations;
using Xunit;
namespace Theriapolis.Tests.Persistence;
/// <summary>
/// Phase 6 M2 — additive V5→V6 migration. Unlike V4→V5 (rejection), v5
/// saves are accepted and migrated up by zero-filling the new typed
/// reputation containers.
/// </summary>
public sealed class V5ToV6MigrationTests
{
[Fact]
public void V5Header_IsAcceptedByMigration()
{
var header = new SaveHeader { Version = 5 };
Assert.True(SaveCodec.IsCompatible(header),
"v5 must remain readable post-Phase-6 (MIN_VERSION = 5).");
var body = new SaveBody();
bool ok = Migrations.MigrateUp(header, body);
Assert.True(ok);
Assert.Equal(C.SAVE_SCHEMA_VERSION, header.Version);
}
[Fact]
public void V6_NewBody_HasEmptyReputationState()
{
var body = new SaveBody();
Assert.NotNull(body.ReputationState);
Assert.Empty(body.ReputationState.FactionStandings);
Assert.Empty(body.ReputationState.Personal);
Assert.Empty(body.ReputationState.Ledger);
}
[Fact]
public void V5SaveBody_AfterMigration_HasEmptyReputation()
{
// Construct what a Phase-5-saved body might look like — v5 fields
// (Player, Clock, ModifiedChunks, ModifiedWorldTiles, Flags,
// PlayerCharacter, NpcRoster, ActiveEncounter), no v6 fields.
var header = new SaveHeader { Version = 5 };
var body = new SaveBody
{
Player = new() { Name = "Old Hand", PositionX = 50, PositionY = 50 },
};
body.Flags["debug-flag"] = 1;
bool ok = Migrations.MigrateUp(header, body);
Assert.True(ok);
// Migration chains all the way up to the current schema version.
Assert.Equal(C.SAVE_SCHEMA_VERSION, header.Version);
// V5 fields must survive untouched.
Assert.Equal("Old Hand", body.Player.Name);
Assert.Equal(1, body.Flags["debug-flag"]);
// V6 fields must be empty (the migration does not synthesise data).
Assert.NotNull(body.ReputationState);
Assert.Empty(body.ReputationState.FactionStandings);
Assert.Empty(body.ReputationState.Personal);
}
[Fact]
public void NewSaveHeader_DefaultsToCurrentSchemaVersion()
{
// Schema version increments per phase (Phase 6 = v6, Phase 6.5 = v7);
// SaveHeader picks up the constant.
var header = new SaveHeader();
Assert.Equal(C.SAVE_SCHEMA_VERSION, header.Version);
}
}