XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Navigation;
using XFEExtension.NetCore.XUnit.Attributes;

namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class GameJournalClockTests
{
    private static readonly DateTimeOffset Now=DateTimeOffset.Parse("2026-10-26T05:49:28.536Z");
    private static PlayerState Ahead=>new(){InGame=true,Status=new(16777232,0,32,1,0,null,null,null,null,[]),
        LoadGameAt=Now.AddMinutes(-2),StatusAt=Now.AddSeconds(6.464),StatusWrittenAt=Now,StatusReadAt=Now.AddMilliseconds(10)};
    [Test]public void AVerifiedLocalWriteExplainsTheRealSixSecondGameClockLead()
    {
        var now=Now.AddMilliseconds(20);Check.That(TravelPreparation.StatusConfirmed(Ahead,now));
        Check.Equal(TimeSpan.FromSeconds(6.464),GameJournalClock.Offset(Ahead,now)!.Value);
        Check.That(!TravelPreparation.StatusConfirmed(Ahead with{StatusWrittenAt=null},now));
        Check.That(!TravelPreparation.StatusConfirmed(Ahead with{StatusAt=Now.AddSeconds(31)},now));
        Check.That(!TravelPreparation.StatusConfirmed(Ahead with{StatusReadAt=Now.AddSeconds(-3)},now));
        Check.That(!TravelPreparation.StatusConfirmed(Ahead with{StatusWrittenAt=Now.AddSeconds(1)},now));
        Check.That(!TravelPreparation.StatusConfirmed(Ahead with{LoadGameAt=Now.AddSeconds(7)},now));
    }
    [Test]public void MatchingFinalJumpClearUsesTheJournalClockWithoutWeakeningWallClockFreshness()
    {
        NavWaypoint Point(long id)=>new(id,"System "+id,new(id,0,0),"K");
        var player=Ahead with{CommanderId="F1",Navigation=new(){CurrentSystemAddress=1,Route=[Point(1),Point(2)],RouteAt=Now.AddMinutes(-1)}};
        var mirror=new GameRouteMirror(()=>Now.AddMilliseconds(20));mirror.Observe(player);
        var jumping=player with{Navigation=player.Navigation with{Route=[],RouteAt=Now.AddSeconds(6.464),JumpStartedAt=Now.AddSeconds(3),
            JumpInProgress=true,JumpTargetSystemAddress=2,JumpTargetSystem="System 2"}};
        Check.That(!mirror.Observe(jumping).Cleared);
        var arrived=jumping with{Navigation=jumping.Navigation with{CurrentSystemAddress=2,JumpInProgress=false,LastJumpAt=Now.AddSeconds(7)}};
        Check.That(mirror.Observe(arrived).Arrived);
    }
    [Test]public void ArrivalTailWindowsUseOnlyTheVerifiedJournalClockCorrection()
    {
        var player=Ahead with{Navigation=new(){LastJumpAt=Now.AddSeconds(6.464)}};var now=Now.AddMilliseconds(20);
        Check.That(GameJournalClock.IsRecentArrival(player,now));
        Check.That(!GameJournalClock.IsRecentArrival(player with{StatusWrittenAt=null},now));
        Check.That(!GameJournalClock.IsRecentArrival(player with{Navigation=player.Navigation with{LastJumpAt=Now.AddSeconds(-25)}},now));
        Check.That(!GameJournalClock.IsRecentArrival(player with{Navigation=player.Navigation with{LastJumpAt=Now.AddMinutes(1)}},now));
    }
    [Test]public async Task StableFileMetadataIsRetainedAcrossUnchangedReadsWithoutInventingStatusEvents()
    {
        using var directory=new TemporaryDirectory();var path=directory.File("Status.json");var written=DateTimeOffset.UtcNow;
        await File.WriteAllTextAsync(path,JsonSerializer.Serialize(new{timestamp=written.AddSeconds(6.5),@event="Status",Flags=16777232}));
        File.SetLastWriteTimeUtc(path,written.UtcDateTime);await using var monitor=new JournalMonitor(directory.Path);await monitor.StartAsync();
        var original=monitor.State.StatusWrittenAt;Check.Equal(written,original!.Value);Check.That(TravelPreparation.StatusConfirmed(monitor.State,DateTimeOffset.UtcNow));
        await Task.Delay(850);Check.Equal(original,monitor.State.StatusWrittenAt);Check.That(TravelPreparation.StatusConfirmed(monitor.State,DateTimeOffset.UtcNow));
    }
}