using System.Buffers.Binary;
using System.Text;
using XFEEDToolBox.Core.Galaxy;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class OriginalGalaxyAccountCacheTests
{
private static byte[] Visited(params long[] addresses)
{
var bytes=new byte[48+addresses.Length*16+8];"VisitedStars"u8.CopyTo(bytes);
void U32(int at,uint value)=>BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(at,4),value);
void U64(int at,ulong value)=>BinaryPrimitives.WriteUInt64LittleEndian(bytes.AsSpan(at,8),value);
U32(12,0x100);U32(16,200);U32(20,48);U32(24,(uint)addresses.Length);U32(28,16);U64(32,10415381);U64(40,12142437);
for(var i=0;i<addresses.Length;i++){U64(48+i*16,(ulong)addresses[i]);U32(56+i*16,1);U32(60+i*16,155516);}
U64(bytes.Length-8,OriginalVisitedStarsCache.Terminator);return bytes;
}
[Test] public void VisitedCacheBindsBothOriginalAccountIdsAndOnlyProvesPositiveMembership()
{
var snapshot=OriginalVisitedStarsCache.Parse(Visited(10477373803,1458242097866),10415381,12142437);
Check.Equal(2,snapshot.Count);Check.Equal(12142437ul,snapshot.CommanderId);
Check.Equal<bool?>(true,snapshot.Visited(1458242097866));Check.Equal<bool?>(null,snapshot.Visited(999));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(1),10415382));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(1),10415381,12142438));
Check.Throws<ArgumentException>(()=>OriginalVisitedStarsCache.ReadForUser("unused","../10415381"));
}
[Test] public void PartialOrUnsupportedOriginalCachesCannotProduceAccountFacts()
{
var bytes=Visited(1,2);Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes.AsSpan(0,bytes.Length-1),10415381));
bytes[^1]=0;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
bytes=Visited(1);bytes[12]=1;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(1,1),10415381));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(0),10415381));
bytes=Visited(1);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(16,4),201);
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
bytes=Visited(1);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(20,4),64);
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
bytes=Visited(1);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(28,4),8);
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
}
[Test]public void ObservedOriginalHeadersBothUseNullTerminatedMagicAndDecimalVersion200()
{
// Two original installed-client headers/first-record bytes, observed
// before/after session reentry. Only count is reduced to one here.
foreach(var actual in new[]{
"56697369746564537461727300010000c800000030000000010000001000000015ed9e00000000006547b9000000000053897f7082010000010000007c5f0200dec0fe5adec0fe5a",
"56697369746564537461727300020000c800000030000000010000001000000015ed9e00000000006547b9000000000053897f7082010000010000007c5f0200dec0fe5adec0fe5a"})
{
var bytes=Convert.FromHexString(actual);var snapshot=OriginalVisitedStarsCache.Parse(bytes,10415381,12142437);
Check.Equal(1,snapshot.Count);Check.Equal<bool?>(true,snapshot.Visited(0x182707f8953));
bytes[16]=201;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
}
}
[Test]public void UninitializedMagicPaddingIsOpaqueButTheNullTerminatorIsRequired()
{
foreach(var padding in new[]{0u,0x100u,0x200u,0xffffff00u,0xa5ff8000u})
{
var bytes=Visited(11,22);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(12,4),padding);
var snapshot=OriginalVisitedStarsCache.Parse(bytes,10415381,12142437);Check.Equal(2,snapshot.Count);Check.That(snapshot.Contains(11)&&snapshot.Contains(22));
bytes[12]=1;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
}
}
[Test] public void OriginalTradeCacheUsesItsExactSystemAndTimestampWithoutInventingMissingFacts()
{
var bytes=Encoding.UTF8.GetBytes("""{"version":4,"systemaddress":123,"timestamp":1792756933,"traderoutes":[{"FromStarID":123,"ToStarID":456,"name":"water","npcamount":"0.000006"},{"FromStarID":789,"ToStarID":123,"name":"biowaste","playeramount":"0.000028"}]}""");
var snapshot=OriginalTradeDataCache.Parse(bytes,12142437,123);
Check.That(snapshot.HasRecordedTradeData);Check.Equal(2,snapshot.Routes.Count);Check.Equal(12142437ul,snapshot.CommanderId);
Check.Equal(1792756933L,snapshot.Timestamp.ToUnixTimeSeconds());Check.Equal(.000006,snapshot.Routes[0].NpcAmount);Check.Equal(0d,snapshot.Routes[0].PlayerAmount);
Check.Throws<InvalidDataException>(()=>OriginalTradeDataCache.Parse(bytes,12142437,999));
var invalid=Encoding.UTF8.GetBytes("""{"version":4,"systemaddress":123,"timestamp":1792756933,"traderoutes":[{"FromStarID":123,"ToStarID":456,"name":"water","npcamount":"NaN"}]}""");
Check.Throws<InvalidDataException>(()=>OriginalTradeDataCache.Parse(invalid,12142437,123));
}
}
using System.Buffers.Binary;
using System.Text;
using XFEEDToolBox.Core.Galaxy;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class OriginalGalaxyAccountCacheTests
{
private static byte[] Visited(params long[] addresses)
{
var bytes=new byte[48+addresses.Length*16+8];"VisitedStars"u8.CopyTo(bytes);
void U32(int at,uint value)=>BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(at,4),value);
void U64(int at,ulong value)=>BinaryPrimitives.WriteUInt64LittleEndian(bytes.AsSpan(at,8),value);
U32(12,0x100);U32(16,200);U32(20,48);U32(24,(uint)addresses.Length);U32(28,16);U64(32,10415381);U64(40,12142437);
for(var i=0;i<addresses.Length;i++){U64(48+i*16,(ulong)addresses[i]);U32(56+i*16,1);U32(60+i*16,155516);}
U64(bytes.Length-8,OriginalVisitedStarsCache.Terminator);return bytes;
}
[Test] public void VisitedCacheBindsBothOriginalAccountIdsAndOnlyProvesPositiveMembership()
{
var snapshot=OriginalVisitedStarsCache.Parse(Visited(10477373803,1458242097866),10415381,12142437);
Check.Equal(2,snapshot.Count);Check.Equal(12142437ul,snapshot.CommanderId);
Check.Equal<bool?>(true,snapshot.Visited(1458242097866));Check.Equal<bool?>(null,snapshot.Visited(999));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(1),10415382));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(1),10415381,12142438));
Check.Throws<ArgumentException>(()=>OriginalVisitedStarsCache.ReadForUser("unused","../10415381"));
}
[Test] public void PartialOrUnsupportedOriginalCachesCannotProduceAccountFacts()
{
var bytes=Visited(1,2);Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes.AsSpan(0,bytes.Length-1),10415381));
bytes[^1]=0;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
bytes=Visited(1);bytes[12]=1;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(1,1),10415381));
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(Visited(0),10415381));
bytes=Visited(1);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(16,4),201);
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
bytes=Visited(1);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(20,4),64);
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
bytes=Visited(1);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(28,4),8);
Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
}
[Test]public void ObservedOriginalHeadersBothUseNullTerminatedMagicAndDecimalVersion200()
{
// Two original installed-client headers/first-record bytes, observed
// before/after session reentry. Only count is reduced to one here.
foreach(var actual in new[]{
"56697369746564537461727300010000c800000030000000010000001000000015ed9e00000000006547b9000000000053897f7082010000010000007c5f0200dec0fe5adec0fe5a",
"56697369746564537461727300020000c800000030000000010000001000000015ed9e00000000006547b9000000000053897f7082010000010000007c5f0200dec0fe5adec0fe5a"})
{
var bytes=Convert.FromHexString(actual);var snapshot=OriginalVisitedStarsCache.Parse(bytes,10415381,12142437);
Check.Equal(1,snapshot.Count);Check.Equal<bool?>(true,snapshot.Visited(0x182707f8953));
bytes[16]=201;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
}
}
[Test]public void UninitializedMagicPaddingIsOpaqueButTheNullTerminatorIsRequired()
{
foreach(var padding in new[]{0u,0x100u,0x200u,0xffffff00u,0xa5ff8000u})
{
var bytes=Visited(11,22);BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(12,4),padding);
var snapshot=OriginalVisitedStarsCache.Parse(bytes,10415381,12142437);Check.Equal(2,snapshot.Count);Check.That(snapshot.Contains(11)&&snapshot.Contains(22));
bytes[12]=1;Check.Throws<InvalidDataException>(()=>OriginalVisitedStarsCache.Parse(bytes,10415381));
}
}
[Test] public void OriginalTradeCacheUsesItsExactSystemAndTimestampWithoutInventingMissingFacts()
{
var bytes=Encoding.UTF8.GetBytes("""{"version":4,"systemaddress":123,"timestamp":1792756933,"traderoutes":[{"FromStarID":123,"ToStarID":456,"name":"water","npcamount":"0.000006"},{"FromStarID":789,"ToStarID":123,"name":"biowaste","playeramount":"0.000028"}]}""");
var snapshot=OriginalTradeDataCache.Parse(bytes,12142437,123);
Check.That(snapshot.HasRecordedTradeData);Check.Equal(2,snapshot.Routes.Count);Check.Equal(12142437ul,snapshot.CommanderId);
Check.Equal(1792756933L,snapshot.Timestamp.ToUnixTimeSeconds());Check.Equal(.000006,snapshot.Routes[0].NpcAmount);Check.Equal(0d,snapshot.Routes[0].PlayerAmount);
Check.Throws<InvalidDataException>(()=>OriginalTradeDataCache.Parse(bytes,12142437,999));
var invalid=Encoding.UTF8.GetBytes("""{"version":4,"systemaddress":123,"timestamp":1792756933,"traderoutes":[{"FromStarID":123,"ToStarID":456,"name":"water","npcamount":"NaN"}]}""");
Check.Throws<InvalidDataException>(()=>OriginalTradeDataCache.Parse(invalid,12142437,123));
}
}