// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.Tests.CastleSiege; using MUnique.OpenMU.GameLogic.CastleSiege; /// /// Tests for the Castle Siege phase state machine (time-driven, injected clock). /// [TestFixture] public class CastleSiegeContextTest { private static readonly DateTime T0 = new(2026, 1, 1, 12, 0, 0, DateTimeKind.Utc); /// Tests that a fresh context starts in the ownership (resting) phase. [Test] public void StartsInOwnership() { var ctx = new CastleSiegeContext(Config()); Assert.That(ctx.Phase, Is.EqualTo(CastleSiegePhase.Ownership)); } /// Tests that force-starting moves the state machine into registration. [Test] public async Task ForceStartMovesToRegistrationAsync() { var ctx = new CastleSiegeContext(Config()); await ctx.ForceStartRegistrationAsync(T0); Assert.That(ctx.Phase, Is.EqualTo(CastleSiegePhase.Registration)); } /// Tests that registration advances to preparation once its duration elapses. [Test] public async Task RegistrationAdvancesToPreparationAfterDurationAsync() { var ctx = new CastleSiegeContext(Config()); await ctx.ForceStartRegistrationAsync(T0); await ctx.TickAsync(T0.AddMinutes(4)); // still within registration Assert.That(ctx.Phase, Is.EqualTo(CastleSiegePhase.Registration)); await ctx.TickAsync(T0.AddMinutes(5)); // registration duration elapsed Assert.That(ctx.Phase, Is.EqualTo(CastleSiegePhase.Preparation)); } /// Tests a full cycle: registration -> preparation -> siege -> settlement -> ownership. [Test] public async Task FullCycleReturnsToOwnershipAsync() { var ctx = new CastleSiegeContext(Config()); await ctx.ForceStartRegistrationAsync(T0); await ctx.TickAsync(T0.AddMinutes(5)); // -> Preparation await ctx.TickAsync(T0.AddMinutes(7)); // +2 prep -> Siege Assert.That(ctx.Phase, Is.EqualTo(CastleSiegePhase.Siege)); await ctx.TickAsync(T0.AddMinutes(17)); // +10 siege -> Settlement await ctx.TickAsync(T0.AddMinutes(17)); // Settlement -> Ownership Assert.That(ctx.Phase, Is.EqualTo(CastleSiegePhase.Ownership)); } /// Tests that guilds can be registered (by name) during the registration phase. [Test] public async Task RegisterGuildCollectsNamesDuringRegistrationAsync() { var ctx = new CastleSiegeContext(Config()); await ctx.ForceStartRegistrationAsync(T0); ctx.RegisterGuild("Attackers"); Assert.That(ctx.RegisteredGuilds, Does.Contain("Attackers")); } private static CastleSiegeConfiguration Config() => new() { RegistrationDuration = TimeSpan.FromMinutes(5), PreparationDuration = TimeSpan.FromMinutes(2), SiegeDuration = TimeSpan.FromMinutes(10), }; }