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 System.Text.Json.Nodes;
using XFEEDToolBox.Core.Navigation;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;

[TestFixture]
public class NativeCruiseThermalControlTests
{
    private const string Hash="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    private static async Task<bool> ReadProof(Action<JsonObject>? alter=null,int heatAgeMilliseconds=0)
    {
        var pid=Random.Shared.Next(200000000,290000000);using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(5));
        var now=DateTimeOffset.UtcNow;
        var result=JsonSerializer.SerializeToNode(new{schema=1,processId=pid,service=NativeCruiseControlChannel.Service,gameSha256=Hash,
            enabled=true,owningThread=8,overchargeControl=true,originalFuelRangeObservations=true,nativeStopReceipts=true,expiringOriginalControl=true,
            componentThermalModel=true,controlTelemetrySchema=1,sampleReady=true,
            sample=new{verified=true,entityId="12",referenceWorldAddress="24",observedAtUnixMilliseconds=now.ToUnixTimeMilliseconds(),
                inSupercruise=true,stableFsd=true,rawFsdState=2,state=3,nativeCanEngage=false,heatPercent=95,
                thermal=new{verified=true,entityId="12",referenceWorldAddress="24",sourceObservedAtUnixMilliseconds=now.ToUnixTimeMilliseconds(),
                    heatObservedAtUnixMilliseconds=now.ToUnixTimeMilliseconds()-heatAgeMilliseconds,
                    heatCapacity=100,heatDisplayScale=1.5,scoInputUpper=30,otherInputUpper=3,coolingPassive=5,coolingMaximum=20,coolingScale=1,
                    coolingHeatLower=.2,coolingHeatUpper=1,responseDelaySeconds=.02}}})!.AsObject();
        alter?.Invoke(result);
        await using var pipe=new NamedPipeServerStream($"XFEEDToolBox.{NativeCruiseControlChannel.Service}.{pid}",PipeDirection.InOut,1,PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
        var serve=Task.Run(async()=>
        {
            await pipe.WaitForConnectionAsync(timeout.Token);var buffer=new byte[1024];var count=await pipe.ReadAsync(buffer,timeout.Token);
            using var request=JsonDocument.Parse(buffer.AsMemory(0,count));Check.Equal("read",request.RootElement.GetProperty("op").GetString()!);
            await pipe.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),timeout.Token);await pipe.WriteAsync(new byte[]{10},timeout.Token);
            if(OperatingSystem.IsWindows())pipe.WaitForPipeDrain();
        });
        var channel=new NativeCruiseControlChannel(pid,Hash);var notifications=0;channel.Observed+=_=>notifications++;
        var frame=new SystemFlightFrame{ShipEntity=12,ReferenceWorld=24,GameSha256=Hash,InGame=true,Mode=LocalFlightMode.Supercruise,HeatPercent=95,ObservedAt=now};
        try
        {
            var expiry=await channel.ReadThermalControlExpiryAsync(frame,timeout.Token);
            Check.That(channel.LastObservation is null&&channel.LastStatus is null&&notifications==0,"The heat-envelope proof must not consume command observations or publish command events.");
            return expiry is {} end&&end>=DateTimeOffset.UtcNow&&end<=now.AddMilliseconds(200-heatAgeMilliseconds);
        }
        finally{await serve;}
    }
    [Test]public async Task VerifiedOriginalCoolingStillControlsTheEnvelopeDuringNativeCooldown()
        =>Check.That(await ReadProof());
    [Test]public async Task OtherSourcesThatKeepHeatingCannotBypassTheConventionalHeatLimit()
        =>Check.That(!await ReadProof(value=>value["sample"]!["thermal"]!["otherInputUpper"]=30));
    [Test]public async Task IndependentOlderHeatLimitsTheCoolingProofLease()
        =>Check.That(await ReadProof(heatAgeMilliseconds:100));
    [Test]public async Task UnknownFutureAndExpiredHeatCannotAuthorizeTheCoolingProof()
    {
        foreach(var age in new[]{-1000,201})Check.That(!await ReadProof(heatAgeMilliseconds:age));
        Check.That(!await ReadProof(value=>value["sample"]!["thermal"]!.AsObject().Remove("heatObservedAtUnixMilliseconds")));
        foreach(var unknown in new JsonNode?[]{null,JsonValue.Create("unknown"),JsonValue.Create(0L)})
            Check.That(!await ReadProof(value=>value["sample"]!["thermal"]!["heatObservedAtUnixMilliseconds"]=unknown));
    }
    [Test]public async Task UnknownForeignAndStaleSourcesCannotAuthorizeTheEnvelope()
    {
        foreach(var field in new[]{"verified","entityId","referenceWorldAddress","sourceObservedAtUnixMilliseconds"})
            Check.That(!await ReadProof(value=>
            {
                var model=value["sample"]!["thermal"]!;
                if(field=="verified")model[field]=false;
                else if(field=="sourceObservedAtUnixMilliseconds")model[field]=DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeMilliseconds();
                else model[field]="999";
            }));
    }
    [Test]public async Task OldModulesStaleFramesAndWrongFlightModesStayWithinTheConventionalLimit()
    {
        foreach(var mode in new[]{0,1,2,3,4})Check.That(!await ReadProof(value=>
        {
            if(mode==0)value["componentThermalModel"]=false;
            else if(mode==1)value["service"]="CruiseControl0514f";
            else if(mode==2)value["sample"]!["observedAtUnixMilliseconds"]=DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeMilliseconds();
            else if(mode==3)value["sample"]!["entityId"]="13";
            else value["sample"]!["rawFsdState"]=1;
        }));
    }
}