using System.IO.Pipes;
using System.Text.Json;
using XFEEDToolBox.Core.Galaxy;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class NativeGalaxyFleetCatalogTests
{
private static async Task Serve(int pid,object result,CancellationToken token,Action<JsonElement>? inspect=null)
{
await using var server=new NamedPipeServerStream($"XFEEDToolBox.Navigation.{pid}",PipeDirection.InOut,1,PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
await server.WaitForConnectionAsync(token);var request=new byte[4096];var count=await server.ReadAsync(request,token);
using(var json=JsonDocument.Parse(request.AsMemory(0,count)))inspect?.Invoke(json.RootElement);
await server.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),token);await server.WriteAsync(new byte[]{10},token);
if(OperatingSystem.IsWindows())server.WaitForPipeDrain();
}
private static object Row(int index)=>new{id=index+1,shipId=3000000000U+(uint)index,systemAddress=(9007199254740993L+index%2).ToString()};
[Test] public async Task FleetKeepsOriginalOrdinalShipIdAndExactAddressSeparateAcrossPages()
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)19,items=Enumerable.Range(0,96).Select(Row)},stop.Token,
r=>Check.Equal("galaxy.fleet",r.GetProperty("op").GetString()));
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)19,items=new[]{Row(96)}},stop.Token,
r=>{Check.Equal(7,r.GetProperty("generation").GetInt32());Check.Equal(96,r.GetProperty("offset").GetInt32());});
});
var result=await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);await server;
Check.That(result.Available&&!result.Complete);Check.Equal((uint?)19,result.CurrentShipId);Check.Equal(97,result.Ships.Count);
Check.Equal(1,result.Ships[0].Id);Check.Equal(3000000000U,result.Ships[0].ShipId);Check.Equal(9007199254740993L,result.Ships[0].SystemAddress);
Check.Equal(result.Ships[0].SystemAddress,result.Ships[96].SystemAddress);
}
[Test] public async Task FleetCannotMergePagesAfterCurrentShipChanges()
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)19,items=Enumerable.Range(0,96).Select(Row)},stop.Token);
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)20,items=new[]{Row(96)}},stop.Token);
});
var rejected=false;try{await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
[Test] public async Task UnavailableAndUnknownCurrentShipRemainUnknownAndUiOrdinalCannotBecomeShipId()
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(pid,new{available=false},stop.Token));var unavailable=await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);await server;
Check.That(!unavailable.Available&&!unavailable.Complete&&unavailable.CurrentShipId is null);
server=Task.Run(()=>Serve(pid,new{available=true,generation=1,total=1,entityId="42",currentShipId=(uint?)null,items=new[]{Row(0)}},stop.Token));
var unknown=await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);await server;Check.That(unknown.CurrentShipId is null&&unknown.Ships[0].Id!=unknown.Ships[0].ShipId);
server=Task.Run(()=>Serve(pid,new{available=true,generation=1,total=1,entityId="42",currentShipId=(uint?)19,items=new[]{new{id=3000000000U,shipId=1U,systemAddress="9007199254740993"}}},stop.Token));
var rejected=false;try{await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);}catch(Exception e)when(e is InvalidDataException or FormatException){rejected=true;}
await server;Check.That(rejected);
}
}
using System.IO.Pipes;
using System.Text.Json;
using XFEEDToolBox.Core.Galaxy;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class NativeGalaxyFleetCatalogTests
{
private static async Task Serve(int pid,object result,CancellationToken token,Action<JsonElement>? inspect=null)
{
await using var server=new NamedPipeServerStream($"XFEEDToolBox.Navigation.{pid}",PipeDirection.InOut,1,PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
await server.WaitForConnectionAsync(token);var request=new byte[4096];var count=await server.ReadAsync(request,token);
using(var json=JsonDocument.Parse(request.AsMemory(0,count)))inspect?.Invoke(json.RootElement);
await server.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new{ok=true,result}),token);await server.WriteAsync(new byte[]{10},token);
if(OperatingSystem.IsWindows())server.WaitForPipeDrain();
}
private static object Row(int index)=>new{id=index+1,shipId=3000000000U+(uint)index,systemAddress=(9007199254740993L+index%2).ToString()};
[Test] public async Task FleetKeepsOriginalOrdinalShipIdAndExactAddressSeparateAcrossPages()
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)19,items=Enumerable.Range(0,96).Select(Row)},stop.Token,
r=>Check.Equal("galaxy.fleet",r.GetProperty("op").GetString()));
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)19,items=new[]{Row(96)}},stop.Token,
r=>{Check.Equal(7,r.GetProperty("generation").GetInt32());Check.Equal(96,r.GetProperty("offset").GetInt32());});
});
var result=await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);await server;
Check.That(result.Available&&!result.Complete);Check.Equal((uint?)19,result.CurrentShipId);Check.Equal(97,result.Ships.Count);
Check.Equal(1,result.Ships[0].Id);Check.Equal(3000000000U,result.Ships[0].ShipId);Check.Equal(9007199254740993L,result.Ships[0].SystemAddress);
Check.Equal(result.Ships[0].SystemAddress,result.Ships[96].SystemAddress);
}
[Test] public async Task FleetCannotMergePagesAfterCurrentShipChanges()
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)19,items=Enumerable.Range(0,96).Select(Row)},stop.Token);
await Serve(pid,new{available=true,generation=7,total=97,entityId="42",currentShipId=(uint?)20,items=new[]{Row(96)}},stop.Token);
});
var rejected=false;try{await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
[Test] public async Task UnavailableAndUnknownCurrentShipRemainUnknownAndUiOrdinalCannotBecomeShipId()
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(pid,new{available=false},stop.Token));var unavailable=await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);await server;
Check.That(!unavailable.Available&&!unavailable.Complete&&unavailable.CurrentShipId is null);
server=Task.Run(()=>Serve(pid,new{available=true,generation=1,total=1,entityId="42",currentShipId=(uint?)null,items=new[]{Row(0)}},stop.Token));
var unknown=await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);await server;Check.That(unknown.CurrentShipId is null&&unknown.Ships[0].Id!=unknown.Ships[0].ShipId);
server=Task.Run(()=>Serve(pid,new{available=true,generation=1,total=1,entityId="42",currentShipId=(uint?)19,items=new[]{new{id=3000000000U,shipId=1U,systemAddress="9007199254740993"}}},stop.Token));
var rejected=false;try{await new NativeGalaxyAccountCatalog(pid).ReadFleetAsync(stop.Token);}catch(Exception e)when(e is InvalidDataException or FormatException){rejected=true;}
await server;Check.That(rejected);
}
}