using System.Text.Json; using XFEEDToolBox.Core.Galaxy; namespace XFEEDToolBox.ViewModels; // Execute the actual production partial; only unrelated VM presentation and // persistence are substituted. No game pipe/process or public network is used. public partial class ToolboxViewModel { private readonly Dictionary galaxyCache=[]; private readonly CancellationTokenSource lifetime=new(); private CancellationTokenSource? galaxyOverrideResolveStop; private long galaxySourceEpoch=1,galaxyViewVersion=1; private GalaxyCatalogueSelection? GalaxyCatalogueSelection; private int publishes,queued; private Action? onPublish; private GalacticSystem RememberGalaxy(GalacticSystem system,int? processId=null) {if(processId!=42)throw new Exception("Result lost its native process binding");galaxyCache[system.Name]=system;return system;} private void PublishGalaxy(){publishes++;onPublish?.Invoke();} private void QueueGalaxyFilterInformation()=>queued++; private static void Require(bool value,string message){if(!value)throw new Exception(message);} private static GalaxyCatalogueSelection Selection(int count=97,int process=42,long generation=1) { var rows=Enumerable.Range(1,count).Select(i=>new GalaxyOriginalPointOverride(i,1,false,false,new(i,2,3),null,"G",null)); return new(GalaxyOriginalCatalogueLod.Create(new(0,0,0),1,500,1,1,4),new(0,0,0)) {PointOverrides=new(process,generation,1,0,true,true,rows,[])}; } private static GalacticSystem Star(long id)=>new("Explicit resolver fixture "+id,new(id,2,3),id,"G","游戏银河目录"); private Task Run(GalaxyCatalogueSelection selection,Func> resolve, Func? current=null,CancellationToken token=default)=> ResolvePublishedGalaxyOverridesAsync(selection,42,resolve,current??(()=>true),token); private static TaskCompletionSource Signal()=>new(TaskCreationOptions.RunContinuationsAsynchronously); public static async Task Main(string[] args) { var checks=new List(); { var vm=new ToolboxViewModel();var selection=Selection();vm.GalaxyCatalogueSelection=selection; foreach(var i in Enumerable.Range(1,32)){var star=Star(i);vm.galaxyCache[star.Name]=star;} var calls=new List();var active=0;var maximum=0; await vm.Run(selection,async(id,_)=>{calls.Add(id);maximum=Math.Max(maximum,++active);await Task.Yield();active--;return Star(id);}); Require(calls.Count==65&&calls.Contains(97)&&!calls.Contains(1)&&vm.galaxyCache.Count==97, "Cached first32 must not starve later pages; every remaining exact address must progress"); Require(maximum==1&&vm.publishes is >0 and <=5,"Resolver must retain one outstanding query and batch fast UI publication"); checks.Add("cached-first32-do-not-starve-all97-single-inflight"); var repeated=0;await vm.Run(selection,(id,_)=>{repeated++;return Task.FromResult(Star(id));}); Require(repeated==0,"A later pass must reuse exact named catalogue identities");checks.Add("all-exact-cache-hits-skip-native"); } { var vm=new ToolboxViewModel();var selection=Selection();vm.GalaxyCatalogueSelection=selection;var calls=0; await vm.Run(selection,(id,_)=>{calls++;return id<=40?Task.FromException(new KeyNotFoundException()):Task.FromResult(Star(id));}); Require(calls==97&&vm.galaxyCache.Count==57&&vm.galaxyCache.ContainsKey(Star(97).Name),"Unavailable early addresses cannot end later pages"); checks.Add("failed-prefix-still-progresses-to-final-page"); } { var vm=new ToolboxViewModel();var selection=Selection(4);vm.GalaxyCatalogueSelection=selection; await vm.Run(selection,(id,_)=>Task.FromResult(id switch {1=>Star(id) with{SystemAddress=2},2=>Star(id) with{Position=new(200,2,3)},3=>Star(id) with{Name=" "},_=>Star(id)})); Require(vm.galaxyCache.Count==1&&vm.galaxyCache.ContainsKey(Star(4).Name),"Wrong address, coordinate, or empty name cannot become a published row"); checks.Add("exact-address-position-and-real-name-required"); } foreach(var kind in new[]{"token","epoch","view","selection","source","lifetime"}) { var vm=new ToolboxViewModel();var selection=Selection(1);vm.GalaxyCatalogueSelection=selection; using var cancel=new CancellationTokenSource();var entered=Signal();var result=Signal();var source=true; var task=vm.Run(selection,(_,_)=>{entered.SetResult(true);return result.Task;},()=>source,cancel.Token); await entered.Task; switch(kind) {case "token":cancel.Cancel();break;case "epoch":vm.galaxySourceEpoch++;break;case "view":vm.galaxyViewVersion++;break; case "selection":vm.GalaxyCatalogueSelection=selection with{};break;case "source":source=false;break;case "lifetime":vm.lifetime.Cancel();break;} // Deliberately return a successful response after ignoring cancellation. result.SetResult(Star(1));await task; Require(vm.galaxyCache.Count==0&&vm.publishes==0&&vm.queued==0,"Stale "+kind+" response was published");checks.Add("late-"+kind+"-response-rejected"); } { var vm=new ToolboxViewModel();var selection=Selection(1,43);vm.GalaxyCatalogueSelection=selection;var calls=0; await vm.Run(selection,(id,_)=>{calls++;return Task.FromResult(Star(id));}); Require(calls==0&&vm.galaxyCache.Count==0,"Another process's published table must not issue or accept resolves");checks.Add("snapshot-process-mismatch-rejected"); } { var vm=new ToolboxViewModel();var attempted=new List(); for(var i=0;i<50;i++) { var selection=Selection(50,generation:i+1);vm.GalaxyCatalogueSelection=selection;vm.galaxyViewVersion++; using var stop=new CancellationTokenSource(); await vm.Run(selection,(id,_)=>{attempted.Add(id);stop.Cancel();return Task.FromResult(Star(id));},token:stop.Token); } Require(attempted.Count==50&&attempted.Distinct().Count()==50&&vm.galaxyCache.Count==0&&vm.publishes==0, "Repeated cancelled views must fairly rotate every unresolved address without publishing old results"); checks.Add("continuous-cancelled-views-fairly-advance-all50"); } { var vm=new ToolboxViewModel();var first=Selection(1);vm.GalaxyCatalogueSelection=first; var oldEntered=Signal();var oldResult=Signal(); var oldTask=vm.Run(first,(_,_)=>{oldEntered.SetResult(true);return oldResult.Task;});await oldEntered.Task; var next=Selection(1,generation:2);vm.GalaxyCatalogueSelection=next;vm.galaxyViewVersion++; var newEntered=Signal();var newResult=Signal(); var nextTask=vm.Run(next,(_,_)=>{newEntered.SetResult(true);return newResult.Task;});await newEntered.Task; var latestStop=vm.galaxyOverrideResolveStop;oldResult.SetResult(Star(1));await oldTask; Require(ReferenceEquals(latestStop,vm.galaxyOverrideResolveStop)&&latestStop?.IsCancellationRequested==false, "An old completion must not clear or cancel the new worker"); newResult.SetResult(Star(1));await nextTask; Require(vm.galaxyCache.Count==1&&vm.publishes==1,"Only the newest selection can publish");checks.Add("old-finally-cannot-clear-new-worker"); } { var vm=new ToolboxViewModel();var selection=Selection();vm.GalaxyCatalogueSelection=selection; vm.onPublish=()=>vm.GalaxyCatalogueSelection=selection with{};var calls=0; await vm.Run(selection,(id,_)=>{calls++;return Task.FromResult(Star(id));}); Require(calls==1&&vm.publishes==1&&vm.queued==0,"Reentrant view changes during publish must stop the old worker and its fact queue"); checks.Add("reentrant-publication-change-stops-old-queue"); } var core=typeof(GalaxyCatalogueSelection).Assembly.Location; var json=JsonSerializer.Serialize(new{passed=checks.Count,failed=0,checks,productionSource="XFEEDToolBox/ViewModels/GalaxyViewModel.PointOverrides.cs", modelAssembly=core,modelAssemblySha256=Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(core))), gameProcessAccess=false,gameCalls=0},new JsonSerializerOptions{WriteIndented=true}); if(args.Length>0){Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(args[0]))!);File.WriteAllText(args[0],json);}Console.WriteLine(json);return 0; } }