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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

namespace XFEEDToolBox.Test;

[TestFixture]
public class NativeCruiseStartRefusalTests
{
    [Test]public Task ARefusedOptionalStartReturnsToPrimaryControlAndBacksOffInsteadOfSuspendingIt()=>Verify(false);
    [Test]public Task AnAcknowledgedWarmupThatTheGameStopsKeepsPrimaryControlAndRetriesOnlyAfterCooldown()=>Verify(true);
    [Test]public Task Live08NaturalSoiStopReleasesTheOldBindingBeforeWatchingTheNewWorldWithoutRestartingSco()=>Verify(true,true);
    private static async Task Verify(bool stoppedStart,bool soiChange=false)
    {
        var pid=Random.Shared.Next(500000,900000);var hash=new string('a',64);var calls=0;var starts=0;var watches=0;var moved=false;var watchedWorld="24";JsonElement? receipt=null;
        var startedAt=0L;
        using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(6));
        var server=Task.Run(async()=>
        {
            while(!timeout.IsCancellationRequested)
            {
                try
                {
                    await using var pipe=new NamedPipeServerStream($"XFEEDToolBox.{NativeCruiseControlChannel.Service}.{pid}",PipeDirection.InOut,1,PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
                    await pipe.WaitForConnectionAsync(timeout.Token);var buffer=new byte[8192];var count=await pipe.ReadAsync(buffer,timeout.Token);
                    using var parsed=JsonDocument.Parse(buffer.AsMemory(0,count));var request=parsed.RootElement;var op=request.GetProperty("op").GetString();calls++;
                    if(op=="watch"){watches++;watchedWorld=moved?"48":"24";}
                    if(op=="cruise.set")
                    {
                        starts++;startedAt=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();receipt=JsonSerializer.SerializeToElement(new{owner=request.GetProperty("owner").GetString(),requestId=request.GetProperty("requestId").GetString(),generation=1,
                            selectionGeneration=1,entityId="12",referenceWorldAddress="24",failed=!stoppedStart,applied=stoppedStart,nativeMethodCalled=stoppedStart,
                            nativeMethodRva="2eaacd0",argument=true,actualStateAfterCall=1,observedAtUnixMilliseconds=startedAt,reason="geometry-or-assist",gate=new{identityVerified=true,targetVerified=true,emergency=false,damageSeen=false,assistEnabled=false,hullFraction=1}});
                    }
                    else Check.That(op is "watch" or "read"||stoppedStart&&op=="cruise.release","An off SCO refusal must not send a primary input command.");
                    var now=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                    var gate=new{identityVerified=true,targetVerified=true,geometryVerified=true,emergency=false,damageSeen=false,assistEnabled=false,collisionCourse=false,rawFsdState=2,evaluatedAtUnixMilliseconds=now};
                    var owned=stoppedStart&&op=="cruise.set";
                    object? lastStop=stoppedStart&&starts>0&&!owned?new{owner="controller",startRequestId=receipt!.Value.GetProperty("requestId").GetString(),selectionGeneration=1,
                        entityId="12",referenceWorldAddress="24",argument=false,nativeMethodCalled=moved,nativeMethodRva=moved?"2eaacd0":null,stateBefore=moved?2:3,stateAfter=3,
                        reason=moved?"geometry-or-assist":"flight-state",observedAtUnixMilliseconds=now,gate}:null;
                    var result=new{schema=1,service=NativeCruiseControlChannel.Service,processId=pid,gameSha256=hash,enabled=true,owningThread=7,overchargeControl=true,
                        originalFuelRangeObservations=true,nativeStopReceipts=true,componentThermalModel=true,expiringOriginalControl=true,controlTelemetrySchema=1,overchargeControlQualified=false,
                        owned,generation=1,receipt,released=true,lastOriginalStop=lastStop,lastGate=gate,watchEntityId="12",watchReferenceWorld=watchedWorld,watchInterface="123456",sampleReady=true,
                        sample=new{verified=true,entityId="12",referenceWorldAddress=moved?"48":"24",@interface="123456",vtableRva="533e6e0",observedAtUnixMilliseconds=now,
                            inSupercruise=true,stableFsd=true,rawFsdState=2,state=owned?1:0,active=owned,hullFraction=1,healthEmergency=false,nativeCanEngage=true,playerOverride=false,geometryVerified=true,collisionCourse=false,nativeAssistEnabled=false,
                            heatPercent=40,fuelVerified=true,fuelMainTonnes=32,fuelCapacityTonnes=32,reserveFuelTonnes=.4,fuelBoundVerified=true,fuelRateUpperTonnesPerSecond=1,
                            thermal=new{schema=1,verified=true,entityId="12",referenceWorldAddress="24",sourceObservedAtUnixMilliseconds=now,heatObservedAtUnixMilliseconds=now,
                                heatCapacity=100,heatDisplayScale=1,scoInputUpper=10,otherInputUpper=3,coolingPassive=10,coolingMaximum=10,coolingScale=1,coolingHeatLower=0,coolingHeatUpper=1,responseDelaySeconds=.02}}};
                    await pipe.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),timeout.Token);await pipe.WriteAsync(new byte[]{10},timeout.Token);
                    if(OperatingSystem.IsWindows())pipe.WaitForPipeDrain();
                }
                catch(OperationCanceledException)when(timeout.IsCancellationRequested){break;}
            }
        });
        var channel=new NativeCruiseControlChannel(pid,hash);var target=new SystemNavigationTarget(1,24,"Station",SystemTargetKind.Station,42){NativeKey=1,NativeKind=9};
        async Task Update()
        {
            var now=DateTimeOffset.UtcNow;var frame=new SystemFlightFrame{ObservedAt=now,Sequence=1,ShipEntity=12,ReferenceWorld=moved?48UL:24UL,GameSha256=hash,InGame=true,
                Mode=LocalFlightMode.Supercruise,GeometryVerified=true,SystemAddress=1,SelectedTarget=target,Forward=new(0,0,1),TargetPosition=new(0,0,1e12),TargetDistance=1e12,Speed=1e9};
            await channel.UpdateAsync("controller",1,frame,new(SystemNavigationPhase.Supercruise,"ordinary flight",new(0,0,1),.75),target,8,now.AddMilliseconds(250),timeout.Token);
        }
        try
        {
            await Update();await Task.Delay(35,timeout.Token);await Update();Check.Equal(1,starts);
            if(soiChange)
            {
                moved=true;await Update();Check.Equal(2,watches);Check.Equal("48",watchedWorld);Check.Equal(1,starts);
                Check.That(channel.LastStatus!.Value.GetProperty("sample").GetProperty("referenceWorldAddress").GetString()=="48");
                await channel.ReleaseAsync(timeout.Token);return;
            }
            if(stoppedStart){await Update();Check.Equal(1,starts);}
            var before=calls;await Update();Check.Equal(before,calls);Check.That(channel.LastDecision?.UseOvercharge==false);
        }
        finally{timeout.Cancel();await server;}
    }
}