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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

namespace XFEEDToolBox.Test;

[TestFixture]
public sealed class GalaxyPointOverridesTests
{
    static JsonElement Page(long generation=9,int offset=0,int navOffset=0,int total=1,int navTotal=1,bool known=true,long id=1,int process=42)=>JsonSerializer.SerializeToElement(new{
        processId=process,sourceGeneration=generation,capturedAtTick=123UL,scope="published-renderer-d50+local-navroute",navRouteViewMode=(int?)1,
        d50Complete=known,navRouteComplete=known,overrideOffset=offset,overrideTotal=total,navRouteOffset=navOffset,navRouteTotal=navTotal,
        overrides=total>offset?new[]{new{systemAddress=id.ToString(),minimumExtra=1f,farFade=false,pending=false,position=new[]{5d,5d,1005d},name=(string?)null,starClass="G",originalAppearance=(object?)null}}:[],
        navRouteMembers=navTotal>navOffset?new[]{id.ToString()}:[]});

    [Test] public void CurrentPublishedPresenceIsIndependentOfTheConsumedPendingBitAndUnknownIsNotAbsent()
    {
        var known=NativeGalaxyCatalog.ReadPointOverridesPages([Page()]);
        Check.Equal(true,known.OverridePresence(1)!.Value);Check.Equal(false,known.OverridePresence(2)!.Value);
        Check.Equal(true,known.Membership(1)!.Value);Check.Equal(false,known.Membership(2)!.Value);
        Check.That(known.TryGetOverride(1,out var row)&&row is{Pending:false,MinimumExtra:1,FarFade:false,Name:null,System:null});
        var unknown=NativeGalaxyCatalog.ReadPointOverridesPages([Page(total:0,navTotal:0,known:false)]);
        Check.That(unknown.OverridePresence(1) is null&&unknown.Membership(1) is null&&unknown.OverridePresence(0) is null);
    }

    [Test] public void PagesRetainOneSnapshotAndNeverUsePartialArraysToProveAbsence()
    {
        var first=Page(total:2,navTotal:2);var partial=NativeGalaxyCatalog.ReadPointOverridesPages([first]);
        Check.That(!partial.D50Complete&&!partial.NavRouteComplete&&partial.OverridePresence(2) is null&&partial.Membership(2) is null);
        var all=NativeGalaxyCatalog.ReadPointOverridesPages([first,Page(offset:1,navOffset:1,total:2,navTotal:2,id:2)]);
        Check.That(all.D50Complete&&all.NavRouteComplete&&all.Membership(2)==true&&all.Membership(3)==false);
        Check.Throws<InvalidDataException>(()=>NativeGalaxyCatalog.ReadPointOverridesPages([first,Page(generation:10,offset:1,navOffset:1,total:2,navTotal:2,id:2)]));
        Check.Throws<InvalidDataException>(()=>NativeGalaxyCatalog.ReadPointOverridesPages([first,Page(offset:1,navOffset:1,total:2,navTotal:2,id:1)]));
    }

    [Test] public void D50ForcesOnlyItsExactPublishedPositionAndDoesNotBypassStrictFilter()
    {
        var row=new GalaxyOriginalPointOverride((long)(GalaxyCellQueryPlan.Encode(0,0,0,100)|(1UL<<44)),1,false,false,new(5,5,1005),"Recorded","G",null);
        var points=new GalaxyOriginalPointOverrides(42,9,123,0,true,true,[row],[]);
        var system=row.System!;var camera=GalaxyCamera.Create(new(5,5,5),1600,900,0,0,4);
        var selection=new GalaxyCatalogueSelection(GalaxyOriginalCatalogueLod.Create(new(5,5,5),1,10,.001,1,0),new(0,0,0)){PointOverrides=points};
        Check.That(selection.Contains(system)&&selection.IsForced(system));
        Check.That(!selection.Contains(system with{Position=new(6,5,1005)}));
        Check.That(!camera.ProjectForCatalogue(system.Position).IsVisible&&selection.ApplyTo(camera).ProjectForCatalogue(system.Position).IsVisible);
        var physical=system with{OriginalAppearance=new(0xffffffff,null,null,0,4,.4f,.2f,false)};
        Check.Equal(.4f,(selection with{SmallMode=false}).OriginalSize(physical)!.Value);
        var strict=GalaxyMapFilter.Default with{Mode=GalaxyMapMode.Map,Values=new HashSet<string>(),IncludeUnknown=false};
        Check.That(!strict.Matches(system));
        Check.Equal(.4f,(selection with{PointOverrides=null,SmallMode=false}).OriginalSize(physical)!.Value);
    }

    [Test] public void OnlyCurrentKnownD50AbsenceCanReachFreshNavRouteFlags()
    {
        var row=new GalaxyOriginalPointOverride(1,1,false,false,new(0,0,0),"Recorded","G",null);
        var system=row.System! with{OriginalAppearance=new(0xffffffff,null,null,0,4,.4f,.2f,false)
            {NavRouteMembership=false,NavRouteMembershipMode=0,NavRouteViewMode=0}};
        var descriptor=GalaxyOriginalCatalogueLod.Create(new(0,0,0),1,10,.001,1,0);
        GalaxyCatalogueSelection Selection(bool d50,bool nav,IEnumerable<GalaxyOriginalPointOverride> rows,IEnumerable<long> members,int view=0)=>
            new(descriptor,new(0,0,0)){NavRouteViewMode=0,NavRouteMembershipMode=0,
                PointOverrides=new(42,9,123,view,d50,nav,rows,members)};
        Check.That(Selection(true,true,[row],[]).TryFrameFadeFlags(system,out var bypass,out var far)&&!bypass&&!far);
        Check.That(Selection(true,true,[],[]).TryFrameFadeFlags(system,out bypass,out far)&&bypass&&far);
        // Fresh member=true wins over the cached row's explicit false flag.
        Check.That(Selection(true,true,[],[1]).TryFrameFadeFlags(system,out bypass,out far)&&!bypass&&far);
        Check.That(!Selection(false,true,[],[1]).TryFrameFadeFlags(system,out _,out _));
        Check.That(!Selection(true,false,[],[]).TryFrameFadeFlags(system,out _,out _));
        Check.That(!Selection(true,true,[],[],1).TryFrameFadeFlags(system,out _,out _));
        Check.That(!Selection(true,true,[row],[]).TryFrameFadeFlags(system with{Position=new(1,0,0)},out _,out _));
    }

    [Test] public async Task ProfileFetchJoinsPointPagesFromTheSameGenerationBeforePublishing()
    {
        var process=Random.Shared.Next(170000000,180000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(6));
        var serve=Task.Run(async()=>
        {
            for(var page=0;page<2;page++)
            {
                await using var server=new NamedPipeServerStream($"XFEEDToolBox.Navigation.{process}",PipeDirection.InOut,1,PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
                await server.WaitForConnectionAsync(stop.Token);var bytes=new byte[65536];var count=await server.ReadAsync(bytes,stop.Token);
                using var request=JsonDocument.Parse(bytes.AsMemory(0,count));
                Check.Equal(page==0?"galaxy.catalogue.profile":"galaxy.catalogue.profile.result",request.RootElement.GetProperty("op").GetString());
                if(page==1){Check.Equal(1,request.RootElement.GetProperty("overrideOffset").GetInt32());Check.Equal(1,request.RootElement.GetProperty("navRouteOffset").GetInt32());}
                var points=Page(offset:page,navOffset:page,total:2,navTotal:2,id:page+1,process:process);
                var result=new{generation=9L,done=true,cancelled=false,error="",profile=new{origin=new[]{0d,0d,0d},referenceKind="camera-eye",
                    navRouteViewMode=1,navRouteMembershipMode=1,pointOverrides=points}};
                await server.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),stop.Token);await server.WriteAsync(new byte[]{10},stop.Token);
            }
        });
        var profile=await new NativeGalaxyCatalog(process).CatalogueProfileAsync(new(0,0,0),new(0,0,0),stop.Token);await serve;
        Check.That(profile.PointOverrides is{D50Complete:true,NavRouteComplete:true,SourceGeneration:9} points&&
            points.Overrides.Count==2&&points.Membership(2)==true&&points.OverridePresence(3)==false);
    }

    [Test] public async Task SlowAuxiliaryPageDoesNotHoldBasicLodAndSupersedingViewDiscardsItsCompletion()
    {
        var process=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(6));
        var auxiliaryStarted=new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
        var releaseAuxiliary=new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
        NamedPipeServerStream Server()=>new($"XFEEDToolBox.Navigation.{process}",PipeDirection.InOut,NamedPipeServerStream.MaxAllowedServerInstances,
            PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
        async Task<JsonElement> Request(NamedPipeServerStream server)
        {
            await server.WaitForConnectionAsync(stop.Token);var bytes=new byte[65536];var count=0;
            while(count<bytes.Length)
            {
                var read=await server.ReadAsync(bytes.AsMemory(count),stop.Token);if(read==0)throw new EndOfStreamException();count+=read;
                try{using var json=JsonDocument.Parse(bytes.AsMemory(0,count));return json.RootElement.Clone();}
                catch(JsonException){}
            }
            throw new InvalidDataException("Fixture request too large.");
        }
        async Task Reply(NamedPipeServerStream server,int generation,JsonElement points)
        {
            var result=new{generation,done=true,cancelled=false,error="",profile=new{origin=new[]{0d,0d,0d},queryCentre=new[]{0d,0d,0d},
                surfaceDensity=1d,qualityStarCount=100u,runtimeRadiusMultiplier=1d,sparseExpansion=1d,smallMode=false,originalViewMode=0,
                debugEnabled=false,referenceKind="camera-eye",navRouteViewMode=1,navRouteMembershipMode=1,pointOverrides=points}};
            await server.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),stop.Token);await server.WriteAsync(new byte[]{10},stop.Token);
        }
        var initialServer=Task.Run(async()=>
        {
            await using var server=Server();var request=await Request(server);
            Check.Equal("galaxy.catalogue.profile",request.GetProperty("op").GetString());
            await Reply(server,9,Page(total:2,navTotal:2,process:process));
        });
        var client=new NativeGalaxyCatalog(process);
        var initial=await client.CatalogueProfileFirstPageAsync(new(0,0,0),new(0,0,0),stop.Token);await initialServer;
        Check.That(initial.HasLodInputs&&initial.PointOverrides is{D50Complete:false,NavRouteComplete:false});
        var slowServer=Task.Run(async()=>
        {
            await using var server=Server();var request=await Request(server);
            Check.Equal("galaxy.catalogue.profile.result",request.GetProperty("op").GetString());
            auxiliaryStarted.SetResult();await releaseAuxiliary.Task.WaitAsync(stop.Token);
            await Reply(server,9,Page(offset:1,navOffset:1,total:2,navTotal:2,id:2,process:process));
        });
        var pending=client.CompletePointOverridesAsync(initial,stop.Token);await auxiliaryStarted.Task.WaitAsync(stop.Token);
        try
        {
            var nextServer=Task.Run(async()=>
            {
                await using var server=Server();var request=await Request(server);
                Check.Equal("galaxy.catalogue.profile",request.GetProperty("op").GetString());
                await Reply(server,10,Page(generation:10,total:0,navTotal:0,process:process));
            });
            var next=await client.CatalogueProfileFirstPageAsync(new(1,0,0),new(1,0,0),stop.Token);await nextServer;
            // The slow page is still withheld. Both basic LOD results have
            // already returned, and the optional reader holds neither gate.
            Check.That(next.HasLodInputs&&next.PointOverrides?.SourceGeneration==10&&!pending.IsCompleted);
        }
        finally{releaseAuxiliary.TrySetResult();}
        Check.That(await pending is null);await slowServer;
    }
}