using System.IO.Pipes;
using System.Text.Json;
using XFEEDToolBox.Core.Galaxy;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class NativeGalaxyCommodityFilterFactsTests
{
private const long First=9007199254740993;
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 buffer=new byte[8192];var count=await server.ReadAsync(buffer,token);
using(var request=JsonDocument.Parse(buffer.AsMemory(0,count)))inspect?.Invoke(request.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 Commodity(uint uid,int mode,uint? revision=0,int? category=0,float? opacity=.5f,float? size=1,int? sprite=12,float[]? rgba=null)=>new
{commodityUid=uid,priceMode=mode,revision,category,opacity,size,sprite,rgba=rgba??(revision is null?null:new[]{2f,.2f,.3f,.8f})};
private static object Row(long id,object? commodity)=>new{systemAddress=id.ToString(),commodity};
private static object Page(int count,bool done,params object[] rows)=>new{generation=17UL,contextSystemAddress="42",total=count,done,error="",items=rows};
[Test] public async Task ActualPipeKeepsZeroAndHighUidsBothModesHdrAndExplicitUnknownBindings()
{
foreach(var selected in new[]{new GalaxyNativeCommodityRequest(0,0),new GalaxyNativeCommodityRequest(uint.MaxValue-1,3)})
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(pid,Page(2,true,Row(First,Commodity(selected.CommodityUid,selected.PriceMode,size:0,rgba:[100,2,.3f,0])),
Row(First+1,Commodity(selected.CommodityUid,selected.PriceMode,null,null,null,null,null))),stop.Token,r=>
{Check.That(r.GetProperty("includeCommodity").GetBoolean());Check.Equal(selected.CommodityUid,r.GetProperty("commodityUid").GetUInt32());Check.Equal(selected.PriceMode,r.GetProperty("commodityPriceMode").GetInt32());Check.Equal(First.ToString(),r.GetProperty("systemAddresses")[0].GetString());}));
var result=await new NativeGalaxyFilterFactsCatalog(pid).ReadAsync([First,First+1],stop.Token,commodity:selected);await server;
Check.Equal(selected,result.Rows[0].Commodity!.Request);Check.That(result.Rows[0].Commodity!.Style is{Revision:0,Size:0});
Check.Equal(100f,result.Rows[0].Commodity!.Style!.Rgba[0]);Check.Equal(0f,result.Rows[0].Commodity!.Style!.Rgba[3]);Check.That(result.Rows[1].Commodity is{Style:null});
}
}
[Test] public async Task WrongUidModePartialStyleAndUnsolicitedCommodityReleaseTheOwningQueue()
{
var wanted=new GalaxyNativeCommodityRequest(0xF0000001,1);
foreach(var sample in new[]{(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(0xF0000002,1)),
(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(wanted.CommodityUid,2)),
(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(wanted.CommodityUid,1,category:null)),
(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(wanted.CommodityUid,1,sprite:28)),
(request:(GalaxyNativeCommodityRequest?)null,value:Commodity(wanted.CommodityUid,1))})
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>{await Serve(pid,Page(1,true,Row(First,sample.value)),stop.Token);await Serve(pid,new{cancelled=true},stop.Token,r=>Check.Equal("galaxy.facts.cancel",r.GetProperty("op").GetString()));});
var rejected=false;try{await new NativeGalaxyFilterFactsCatalog(pid).ReadAsync([First],stop.Token,commodity:sample.request);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
}
[Test] public async Task CommodityRebuildBetweenPagesCannotPublishMixedRevisions()
{
var request=new GalaxyNativeCommodityRequest(123,3);var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(pid,Page(1,false,Row(First,Commodity(123,3,7))),stop.Token);
await Serve(pid,Page(2,true,Row(First+1,Commodity(123,3,8))),stop.Token,r=>Check.Equal("galaxy.facts.result",r.GetProperty("op").GetString()));
await Serve(pid,new{cancelled=true},stop.Token,r=>Check.Equal("galaxy.facts.cancel",r.GetProperty("op").GetString()));
});
var rejected=false;try{await new NativeGalaxyFilterFactsCatalog(pid).ReadAsync([First,First+1],stop.Token,commodity:request);}catch(InvalidDataException){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 NativeGalaxyCommodityFilterFactsTests
{
private const long First=9007199254740993;
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 buffer=new byte[8192];var count=await server.ReadAsync(buffer,token);
using(var request=JsonDocument.Parse(buffer.AsMemory(0,count)))inspect?.Invoke(request.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 Commodity(uint uid,int mode,uint? revision=0,int? category=0,float? opacity=.5f,float? size=1,int? sprite=12,float[]? rgba=null)=>new
{commodityUid=uid,priceMode=mode,revision,category,opacity,size,sprite,rgba=rgba??(revision is null?null:new[]{2f,.2f,.3f,.8f})};
private static object Row(long id,object? commodity)=>new{systemAddress=id.ToString(),commodity};
private static object Page(int count,bool done,params object[] rows)=>new{generation=17UL,contextSystemAddress="42",total=count,done,error="",items=rows};
[Test] public async Task ActualPipeKeepsZeroAndHighUidsBothModesHdrAndExplicitUnknownBindings()
{
foreach(var selected in new[]{new GalaxyNativeCommodityRequest(0,0),new GalaxyNativeCommodityRequest(uint.MaxValue-1,3)})
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(()=>Serve(pid,Page(2,true,Row(First,Commodity(selected.CommodityUid,selected.PriceMode,size:0,rgba:[100,2,.3f,0])),
Row(First+1,Commodity(selected.CommodityUid,selected.PriceMode,null,null,null,null,null))),stop.Token,r=>
{Check.That(r.GetProperty("includeCommodity").GetBoolean());Check.Equal(selected.CommodityUid,r.GetProperty("commodityUid").GetUInt32());Check.Equal(selected.PriceMode,r.GetProperty("commodityPriceMode").GetInt32());Check.Equal(First.ToString(),r.GetProperty("systemAddresses")[0].GetString());}));
var result=await new NativeGalaxyFilterFactsCatalog(pid).ReadAsync([First,First+1],stop.Token,commodity:selected);await server;
Check.Equal(selected,result.Rows[0].Commodity!.Request);Check.That(result.Rows[0].Commodity!.Style is{Revision:0,Size:0});
Check.Equal(100f,result.Rows[0].Commodity!.Style!.Rgba[0]);Check.Equal(0f,result.Rows[0].Commodity!.Style!.Rgba[3]);Check.That(result.Rows[1].Commodity is{Style:null});
}
}
[Test] public async Task WrongUidModePartialStyleAndUnsolicitedCommodityReleaseTheOwningQueue()
{
var wanted=new GalaxyNativeCommodityRequest(0xF0000001,1);
foreach(var sample in new[]{(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(0xF0000002,1)),
(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(wanted.CommodityUid,2)),
(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(wanted.CommodityUid,1,category:null)),
(request:(GalaxyNativeCommodityRequest?)wanted,value:Commodity(wanted.CommodityUid,1,sprite:28)),
(request:(GalaxyNativeCommodityRequest?)null,value:Commodity(wanted.CommodityUid,1))})
{
var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>{await Serve(pid,Page(1,true,Row(First,sample.value)),stop.Token);await Serve(pid,new{cancelled=true},stop.Token,r=>Check.Equal("galaxy.facts.cancel",r.GetProperty("op").GetString()));});
var rejected=false;try{await new NativeGalaxyFilterFactsCatalog(pid).ReadAsync([First],stop.Token,commodity:sample.request);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
}
[Test] public async Task CommodityRebuildBetweenPagesCannotPublishMixedRevisions()
{
var request=new GalaxyNativeCommodityRequest(123,3);var pid=Random.Shared.Next(180000000,190000000);using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(5));
var server=Task.Run(async()=>
{
await Serve(pid,Page(1,false,Row(First,Commodity(123,3,7))),stop.Token);
await Serve(pid,Page(2,true,Row(First+1,Commodity(123,3,8))),stop.Token,r=>Check.Equal("galaxy.facts.result",r.GetProperty("op").GetString()));
await Serve(pid,new{cancelled=true},stop.Token,r=>Check.Equal("galaxy.facts.cancel",r.GetProperty("op").GetString()));
});
var rejected=false;try{await new NativeGalaxyFilterFactsCatalog(pid).ReadAsync([First,First+1],stop.Token,commodity:request);}catch(InvalidDataException){rejected=true;}
await server;Check.That(rejected);
}
}