using System.IO.Pipes;
using System.Text.Json;
using XFEEDToolBox.Core.Galaxy;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public class NativeGalaxyCatalogTests
{
private static async Task Serve(int id,object result,CancellationToken token,Action<JsonElement>? inspect=null)
{
await using var server=new NamedPipeServerStream($"XFEEDToolBox.Navigation.{id}",PipeDirection.InOut,1,PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
await server.WaitForConnectionAsync(token);var buffer=new byte[65536];var size=await server.ReadAsync(buffer,token);
using(var request=JsonDocument.Parse(buffer.AsMemory(0,size)))inspect?.Invoke(request.RootElement);
await server.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),token);await server.WriteAsync(new byte[]{10},token);server.WaitForPipeDrain();
}
[Test] public async Task ChangedAutocompleteReceiptCannotReturnAnotherQueriesStars()
{
var id=Random.Shared.Next(100000000,110000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(id,new{generation=7,done=false,error="",items=Array.Empty<object>()},deadline.Token);
await Serve(id,new{generation=8,done=true,error="",items=Array.Empty<object>()},deadline.Token);
});
var rejected=false;try{await new NativeGalaxyCatalog(id).SuggestAsync("Example",deadline.Token);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
[Test] public async Task OriginalAppearancePreservesPackedAlphaAndUnavailableSettingsWithoutPersistingThem()
{
var id=Random.Shared.Next(100000000,110000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(id,new{generation=7,done=true,error="",items=new[]{new{name="Recorded",systemAddress="9007199254740993",position=new[]{1d,2d,3d},starClass="TTS",
originalAppearance=new{typeRgba=0xff112233U,realisticRgba=(uint?)0x80102030,colourBlend=(float?).11,rawScale=uint.MaxValue,classification=(ushort)123,size=.3f,smallSize=.05f,smallSizeActive=(bool?)null}}}},deadline.Token));
var row=await new NativeGalaxyCatalog(id).FindAsync("Recorded",deadline.Token);await server;
var appearance=row.OriginalAppearance!;Check.Equal(0x80102030U,appearance.RealisticRgba!.Value);Check.Equal(uint.MaxValue,appearance.RawScale);Check.That(appearance.ActiveSize is null);
var colour=GalaxyOriginalStellarAppearance.Colour(appearance.RealisticRgba.Value);Check.Equal((byte)0x30,colour.R);Check.Equal((byte)0x20,colour.G);Check.Equal((byte)0x10,colour.B);
var saved=JsonSerializer.Serialize(row,XFEEDToolBox.Core.Models.ToolboxSettings.JsonOptions);Check.That(!saved.Contains("originalAppearance",StringComparison.OrdinalIgnoreCase));
}
[Test] public async Task ExactLookupCannotSubstituteAnUnrelatedSystem()
{
var id=Random.Shared.Next(120000000,130000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(id,new{generation=12,done=true,error="",items=new[]{new{name="Col 285 Sector MC-I b11-2",systemAddress="1234",position=new[]{1d,2d,3d},starClass="K"}}},deadline.Token,
request=>Check.Equal("Adnyayar",request.GetProperty("query").GetString())));
var rejected=false;try{await new NativeGalaxyCatalog(id).FindAsync("Adnyayar",deadline.Token);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
[Test] public async Task NativeRegionPagesPreserveLargeAddressesAndNeverExceedMessageBudget()
{
var id=Random.Shared.Next(110000000,120000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));var offsets=new List<int>();
var server=Task.Run(async()=>
{
await Serve(id,new{generation=9,done=false,error="",items=Array.Empty<object>()},deadline.Token,r=>Check.Equal("galaxy.region",r.GetProperty("op").GetString()));
await Serve(id,new{generation=9,done=true,error="",total=190,items=Array.Empty<object>()},deadline.Token);
for(var offset=0;offset<190;offset+=96)
{
var items=Enumerable.Range(offset,Math.Min(96,190-offset)).Select(i=>new{name="Fixture-"+i,systemAddress=(9007199254740993L+i).ToString(),position=new[]{(double)i,0d,0d},starClass="M"}).ToArray();
await Serve(id,new{generation=9,done=true,error="",total=190,items},deadline.Token,r=>offsets.Add(r.GetProperty("offset").GetInt32()));
}
});
var rows=await new NativeGalaxyCatalog(id).RegionAsync(new(0,0,0),30,deadline.Token);await server;
Check.Equal(190,rows.Count);Check.Equal(9007199254740993L,rows[0].SystemAddress);Check.Equal(9007199254741182L,rows[^1].SystemAddress);
Check.That(offsets.SequenceEqual(new[]{0,96}));Check.That(rows.All(s=>s.StarClass=="M"&&s.Position.IsValid));
}
}
using System.IO.Pipes;
using System.Text.Json;
using XFEEDToolBox.Core.Galaxy;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public class NativeGalaxyCatalogTests
{
private static async Task Serve(int id,object result,CancellationToken token,Action<JsonElement>? inspect=null)
{
await using var server=new NamedPipeServerStream($"XFEEDToolBox.Navigation.{id}",PipeDirection.InOut,1,PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
await server.WaitForConnectionAsync(token);var buffer=new byte[65536];var size=await server.ReadAsync(buffer,token);
using(var request=JsonDocument.Parse(buffer.AsMemory(0,size)))inspect?.Invoke(request.RootElement);
await server.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),token);await server.WriteAsync(new byte[]{10},token);server.WaitForPipeDrain();
}
[Test] public async Task ChangedAutocompleteReceiptCannotReturnAnotherQueriesStars()
{
var id=Random.Shared.Next(100000000,110000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(id,new{generation=7,done=false,error="",items=Array.Empty<object>()},deadline.Token);
await Serve(id,new{generation=8,done=true,error="",items=Array.Empty<object>()},deadline.Token);
});
var rejected=false;try{await new NativeGalaxyCatalog(id).SuggestAsync("Example",deadline.Token);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
[Test] public async Task OriginalAppearancePreservesPackedAlphaAndUnavailableSettingsWithoutPersistingThem()
{
var id=Random.Shared.Next(100000000,110000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(id,new{generation=7,done=true,error="",items=new[]{new{name="Recorded",systemAddress="9007199254740993",position=new[]{1d,2d,3d},starClass="TTS",
originalAppearance=new{typeRgba=0xff112233U,realisticRgba=(uint?)0x80102030,colourBlend=(float?).11,rawScale=uint.MaxValue,classification=(ushort)123,size=.3f,smallSize=.05f,smallSizeActive=(bool?)null}}}},deadline.Token));
var row=await new NativeGalaxyCatalog(id).FindAsync("Recorded",deadline.Token);await server;
var appearance=row.OriginalAppearance!;Check.Equal(0x80102030U,appearance.RealisticRgba!.Value);Check.Equal(uint.MaxValue,appearance.RawScale);Check.That(appearance.ActiveSize is null);
var colour=GalaxyOriginalStellarAppearance.Colour(appearance.RealisticRgba.Value);Check.Equal((byte)0x30,colour.R);Check.Equal((byte)0x20,colour.G);Check.Equal((byte)0x10,colour.B);
var saved=JsonSerializer.Serialize(row,XFEEDToolBox.Core.Models.ToolboxSettings.JsonOptions);Check.That(!saved.Contains("originalAppearance",StringComparison.OrdinalIgnoreCase));
}
[Test] public async Task ExactLookupCannotSubstituteAnUnrelatedSystem()
{
var id=Random.Shared.Next(120000000,130000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(id,new{generation=12,done=true,error="",items=new[]{new{name="Col 285 Sector MC-I b11-2",systemAddress="1234",position=new[]{1d,2d,3d},starClass="K"}}},deadline.Token,
request=>Check.Equal("Adnyayar",request.GetProperty("query").GetString())));
var rejected=false;try{await new NativeGalaxyCatalog(id).FindAsync("Adnyayar",deadline.Token);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
[Test] public async Task NativeRegionPagesPreserveLargeAddressesAndNeverExceedMessageBudget()
{
var id=Random.Shared.Next(110000000,120000000);using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(5));var offsets=new List<int>();
var server=Task.Run(async()=>
{
await Serve(id,new{generation=9,done=false,error="",items=Array.Empty<object>()},deadline.Token,r=>Check.Equal("galaxy.region",r.GetProperty("op").GetString()));
await Serve(id,new{generation=9,done=true,error="",total=190,items=Array.Empty<object>()},deadline.Token);
for(var offset=0;offset<190;offset+=96)
{
var items=Enumerable.Range(offset,Math.Min(96,190-offset)).Select(i=>new{name="Fixture-"+i,systemAddress=(9007199254740993L+i).ToString(),position=new[]{(double)i,0d,0d},starClass="M"}).ToArray();
await Serve(id,new{generation=9,done=true,error="",total=190,items},deadline.Token,r=>offsets.Add(r.GetProperty("offset").GetInt32()));
}
});
var rows=await new NativeGalaxyCatalog(id).RegionAsync(new(0,0,0),30,deadline.Token);await server;
Check.Equal(190,rows.Count);Check.Equal(9007199254740993L,rows[0].SystemAddress);Check.Equal(9007199254741182L,rows[^1].SystemAddress);
Check.That(offsets.SequenceEqual(new[]{0,96}));Check.That(rows.All(s=>s.StarClass=="M"&&s.Position.IsValid));
}
}