using XFEExtension.NetCore.XUnit.Attributes; using XFEEDToolBox.Core.Data; using XFEEDToolBox.Core.Models; namespace XFEEDToolBox.Test; [TestFixture] public class CacheRegionTests { private static async Task Seed(TemporaryDirectory directory,params Station[] stations) { var repository=new MarketRepository(directory.File("markets.db"));repository.InitializeCheap();var at=DateTimeOffset.UtcNow.AddMinutes(-1); foreach(var station in stations) await repository.SaveSnapshotAsync(new(station,[Check.Quote(station.MarketId,"commodity"+station.MarketId,10,9)],at,DataSource.Journal)); return repository; } private static string Ids(IEnumerable stations)=>string.Join(',',stations.Select(station=>station.MarketId)); [Test]public async Task NearbyStationsUseAnExactSphereAndDeterministicDistanceOrder() { using var directory=new TemporaryDirectory();var center=new Coordinates(10,20,30); var repository=await Seed(directory, Check.Station(1) with{Position=center}, Check.Station(2) with{Position=new(13,24,30)}, Check.Station(3) with{Position=new(14,24,30)}, Check.Station(4) with{Position=new(8,20,30),SystemName="A"}, Check.Station(5) with{Position=null}, Check.Station(6) with{Position=new(12,20,30),SystemName="Z"}); Check.Equal("1,4,6,2",Ids(repository.GetStationsNear(center,5))); Check.Equal("1,4",Ids(repository.GetStationsNear(center,5,limit:2))); Check.Equal(new Coordinates(13,24,30),repository.GetStationsNear(center,5).Last().Position!); } [Test]public async Task ExplicitCenterFiltersTheBookWhileKeepingTheActualOriginFirst() { using var directory=new TemporaryDirectory();var repository=await Seed(directory,Check.Station(1,15),Check.Station(2,0),Check.Station(3,-5),Check.Station(4,30)); var book=repository.LoadRegion(1,20,center:new(0,0,0)); Check.Equal("1,2,3",Ids(book.Stations));Check.Equal(new Coordinates(15,0,0),book.Stations[0].Position!); Check.Equal("1,2,3",string.Join(',',book.Quotes.Select(quote=>quote.MarketId).Order()));Check.That(!book.Truncated); Check.Equal("2,3,1",Ids(repository.GetStationsNear(new(0,0,0),20))); } [Test]public async Task OmittingTheCenterPreservesTheOriginCenteredRegion() { using var directory=new TemporaryDirectory();var repository=await Seed(directory,Check.Station(1,1000),Check.Station(2,1010),Check.Station(3,0)); var book=repository.LoadRegion(1,25);Check.Equal("1,2",Ids(book.Stations));Check.Equal(2,book.Quotes.Count); } [Test]public async Task AnOriginOutsideTheChosenCenterIsExplicitlyRejected() { using var directory=new TemporaryDirectory();var repository=await Seed(directory,Check.Station(1,21),Check.Station(2,0)); Check.Throws(()=>repository.LoadRegion(1,20,center:new(0,0,0))); // The actual route origin is never silently replaced by the center. Check.Equal(new Coordinates(21,0,0),repository.GetStation(1)!.Position!); } [Test]public async Task KnownCenterDoesNotInventAnUnknownOriginPosition() { using var directory=new TemporaryDirectory();var repository=await Seed(directory,Check.Station(1) with{Position=null},Check.Station(2,0)); Check.Throws(()=>repository.LoadRegion(1,500,center:new(0,0,0))); Check.Throws(()=>repository.LoadRegion(999,500,center:new(0,0,0))); } [Test]public async Task RadiusAndCenterMustBeFiniteAndPositive() { using var directory=new TemporaryDirectory();var repository=await Seed(directory,Check.Station(1,0));var center=new Coordinates(0,0,0); foreach(var radius in new[]{0d,-1d,double.NaN,double.PositiveInfinity,double.NegativeInfinity,double.MaxValue}) { Check.Throws(()=>repository.GetStationsNear(center,radius)); Check.Throws(()=>repository.LoadRegion(1,radius,center:center)); } Check.Throws(()=>repository.GetStationsNear(new(double.NaN,0,0),500)); Check.Throws(()=>repository.LoadRegion(1,500,center:new(0,double.PositiveInfinity,0))); } [Test]public async Task TruncatedBooksIncludeOnlySelectedStationsAndTheirQuotes() { using var directory=new TemporaryDirectory();var repository=await Seed(directory,Enumerable.Range(1,5).Select(id=>Check.Station(id,id-1)).ToArray()); var book=repository.LoadRegion(5,10,limit:2,center:new(0,0,0)); Check.That(book.Truncated);Check.Equal("5,1",Ids(book.Stations));Check.Equal(2,book.Quotes.Count); Check.That(book.Quotes.All(quote=>quote.MarketId is 5 or 1)); var full=repository.LoadRegion(5,10,limit:5,center:new(0,0,0));Check.That(!full.Truncated);Check.Equal(5,full.Quotes.Count); } }