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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

namespace XFEEDToolBox.Test;

[TestFixture]
public sealed class NativeTargetSelectionRecoveryTests
{
    private static readonly DateTimeOffset Now=DateTimeOffset.Parse("2026-10-27T07:06:03+08:00");
    private static JsonObject Raw()=>new()
    {
        ["sequence"]=7,["observedAtUnixMilliseconds"]=Now.ToUnixTimeMilliseconds(),["entityId"]="42",["referenceWorldAddress"]="1",
        ["localPlayerShipVerified"]=true,["inGame"]=true,["playerOverride"]=false,["rawFsdState"]=2,
        ["shipHealth"]=new JsonObject{["verified"]=true,["entityId"]="42",["sequence"]=7,["observedAtUnixMilliseconds"]=Now.ToUnixTimeMilliseconds(),
            ["hullFraction"]=1,["emergency"]=false,["damageObserved"]=false}
    };
    private static JsonObject Fsd()=>new(){["fresh"]=true,["entityId"]="42",["ownedCharging"]=false,["state"]=2,["targetValid"]=true,["targetAddress"]="2"};
    private static NativeTargetSelectionReadiness Inspect(JsonObject raw,JsonObject fsd)=>NativeTargetSelectionRecovery.Inspect(JsonSerializer.SerializeToElement(raw),JsonSerializer.SerializeToElement(fsd),2,1,Now);
    private static PlayerState Arrived=>new(){InGame=true,CommanderId="F1",CurrentShipId=8,GameMode="Solo",LoadGameAt=Now.AddHours(-1),CargoCount=1200,
        Navigation=new(){CurrentSystemAddress=1,TargetSystemAddress=2,CurrentSystemAt=Now.AddSeconds(-6),LastJumpAt=Now.AddSeconds(-6),Route=[new(1,"Here",new(0,0,0),"M"),new(2,"Next",new(1,0,0),"M")]}};
    [Test]public void FreshIdleCanRequestButDoesNotItselfAcknowledgeADestination()
    {
        var check=Inspect(Raw(),Fsd());Check.That(check.CanRequest&&!check.Reject);
        var raw=Raw();var fsd=Fsd();raw["rawFsdState"]=1;fsd["state"]=1;
        Check.That(Inspect(raw,fsd).CanRequest);fsd["targetAddress"]="3";Check.That(!Inspect(raw,fsd).CanRequest);
    }
    [Test]public void OwnedChargingJumpingAndDifferentNativePhasesOnlyWaitWithoutRetargeting()
    {
        foreach(var (rawState,state,owned) in new[]{(3,3,false),(4,4,false),(2,2,true),(4,2,false),(2,4,false),(99,99,false)})
        {
            var raw=Raw();var fsd=Fsd();raw["rawFsdState"]=rawState;fsd["state"]=state;fsd["ownedCharging"]=owned;
            var check=Inspect(raw,fsd);Check.That(!check.CanRequest&&!check.Reject);
        }
    }
    [Test]public void SourceIdentityWorldFreshnessAndHealthMustAllMatchTheSameRawFrame()
    {
        foreach(Action<JsonObject,JsonObject> alter in new Action<JsonObject,JsonObject>[]
        {
            (r,f)=>f["entityId"]="43",(r,f)=>r["referenceWorldAddress"]="3",(r,f)=>f["fresh"]=false,
            (r,f)=>r["observedAtUnixMilliseconds"]=Now.AddSeconds(-1).ToUnixTimeMilliseconds(),
            (r,f)=>r["shipHealth"]!["sequence"]=6,(r,f)=>r["shipHealth"]!["observedAtUnixMilliseconds"]=Now.AddMilliseconds(-1).ToUnixTimeMilliseconds(),
            (r,f)=>r["shipHealth"]!["entityId"]="43",(r,f)=>r["localPlayerShipVerified"]=false
        })
        {var raw=Raw();var fsd=Fsd();alter(raw,fsd);Check.That(!Inspect(raw,fsd).CanRequest);}
    }
    [Test]public void ExplicitManualDamageHealthAndSessionEndRemainImmediateRejections()
    {
        foreach(Action<JsonObject> alter in new Action<JsonObject>[]
        {r=>r["playerOverride"]=true,r=>r["shipHealth"]!["emergency"]=true,r=>r["shipHealth"]!["damageObserved"]=true,r=>r["shipHealth"]!["hullFraction"]=0,r=>r["inGame"]=false})
        {var raw=Raw();alter(raw);var result=Inspect(raw,Fsd());Check.That(result.Reject&&!result.CanRequest);}
    }
    [Test]public void MissingSafetyOrOwnershipFieldsNeverDefaultToFalse()
    {
        foreach(var field in new[]{"playerOverride","inGame","localPlayerShipVerified","shipHealth"})
        {var raw=Raw();raw.Remove(field);Check.That(!Inspect(raw,Fsd()).CanRequest);}
        var fsd=Fsd();fsd.Remove("ownedCharging");Check.That(!Inspect(Raw(),fsd).CanRequest);
        foreach(var field in new[]{"emergency","damageObserved","sequence","observedAtUnixMilliseconds"})
        {var raw=Raw();raw["shipHealth"]!.AsObject().Remove(field);Check.That(!Inspect(raw,Fsd()).CanRequest);}
    }
    [Test]public void RecentArrivalMustBelongToTheSameLoadedSessionAndCurrentSystemEvent()
    {
        var initial=Arrived;Check.That(NativeTargetSelectionRecovery.ContextFailure(initial,initial,2,Now,TimeSpan.Zero) is null);
        var zero=initial with{CurrentShipId=0};Check.That(NativeTargetSelectionRecovery.ContextFailure(zero,zero,2,Now,TimeSpan.Zero) is null);
        foreach(var altered in new[]{initial with{LoadGameAt=Now},initial with{Navigation=initial.Navigation with{CurrentSystemAt=Now.AddSeconds(-5)}},
            initial with{Navigation=initial.Navigation with{JumpInProgress=true}},initial with{CommanderId=""}})
            Check.That(NativeTargetSelectionRecovery.ContextFailure(altered,altered,2,Now,TimeSpan.Zero) is not null);
    }
    [Test]public void TenSecondDeadlineAndChangesToCargoRouteShipSessionOrSystemAreTerminalContextFailures()
    {
        var initial=Arrived;Check.That(NativeTargetSelectionRecovery.ContextFailure(initial,initial,2,Now,TimeSpan.FromMilliseconds(9999)) is null);
        Check.Equal("arrival-target-selection-deadline",NativeTargetSelectionRecovery.ContextFailure(initial,initial,2,Now,TimeSpan.FromSeconds(10))!);
        foreach(var current in new[]{initial with{CurrentShipId=9},initial with{CommanderId="F2"},initial with{CargoCount=1199},initial with{GameMode="Open"},
            initial with{LoadGameAt=Now},initial with{Docked=true},initial with{Navigation=initial.Navigation with{CurrentSystemAddress=3}},
            initial with{Navigation=initial.Navigation with{TargetSystemAddress=3}},
            initial with{Navigation=initial.Navigation with{Route=[new(3,"Other",new(1,0,0),"M")]}}})
            Check.That(NativeTargetSelectionRecovery.ContextFailure(initial,current,2,Now,TimeSpan.FromSeconds(1)) is not null);
    }
    [Test]public void FailureDiagnosticsAreBoundedAndKeepBothNativePhasesInsteadOfCopyingFullTelemetry()
    {
        var raw=Raw();raw["unrelatedLargePayload"]=new string('x',100000);raw["rawFsdState"]=4;
        var result=Inspect(raw,Fsd());Check.That(!result.CanRequest&&result.Diagnostics.GetRawText().Length<2048);
        Check.Equal(4L,result.Diagnostics.GetProperty("rawState").GetInt64());Check.Equal(2L,result.Diagnostics.GetProperty("fsdState").GetInt64());
        Check.Equal(0,result.Diagnostics.GetProperty("mutationsSent").GetInt32());
    }
}