XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using XFEExtension.NetCore.XUnit.Attributes;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Services;

namespace XFEEDToolBox.Test;

[TestFixture]
public class NearbyMarketCacheTests
{
    [Test]public void RadiusAndUnknownPositionsDoNotAdmitTheGalaxy()
    {
        var player=new PlayerState{SystemName="Home",MarketId=1,Position=new(0,0,0)};
        Check.That(NearbyMarketCachePolicy.Accepts(player,Check.Station(2,500)));
        Check.That(!NearbyMarketCachePolicy.Accepts(player,Check.Station(2,500.001)));
        Check.That(!NearbyMarketCachePolicy.Accepts(player,Check.Station(2) with{Position=null}));
        Check.That(NearbyMarketCachePolicy.Accepts(player,Check.Station(2) with{Position=null},Check.Station(2,149)));
        Check.That(!NearbyMarketCachePolicy.Accepts(player,Check.Station(2) with{Position=null,SystemName="Moved carrier"},Check.Station(2,1)));
        Check.That(!NearbyMarketCachePolicy.Accepts(player with{Position=null},Check.Station(2,1)));
        Check.That(NearbyMarketCachePolicy.Accepts(player with{Position=null},Check.Station(2) with{SystemName="home",Position=null}));
        Check.That(NearbyMarketCachePolicy.Accepts(player with{Position=null},Check.Station(1) with{Position=null}));
        Check.That(!NearbyMarketCachePolicy.Accepts(new(),Check.Station(2,0)));
        Check.That(!NearbyMarketCachePolicy.Accepts(player,Check.Station(2) with{Position=new(double.NaN,0,0)}));
    }

    private static JsonElement Eddn(long id,string system,DateTimeOffset time)=>Check.Event(new
    {
        // Attribute names on the wire include a dollar sign.
        header=new{gameversion="4.0"},message=new{timestamp=time,marketId=id,systemName=system,stationName="Station "+id,
            commodities=new[]{new{name="water",buyPrice=10,sellPrice=9,stock=100,demand=100}}}
    });

    private static JsonElement Message(long id,string system,DateTimeOffset time)
    {
        using var document=JsonDocument.Parse(Eddn(id,system,time).GetRawText());
        var values=new Dictionary<string,object>{{"$schemaRef","https://eddn.edcd.io/schemas/commodity/3"},
            {"header",document.RootElement.GetProperty("header").Clone()},{"message",document.RootElement.GetProperty("message").Clone()}};
        return JsonSerializer.SerializeToElement(values);
    }

    [Test]public async Task RealFeedPathKeepsOnlyCurrentOrLocatedNearbyDataAndAlwaysKeepsJournal()
    {
        using var temporary=new TemporaryDirectory();var repository=new MarketRepository(temporary.File("markets.db"));repository.InitializeCheap();
        await repository.SaveStationAsync(Check.Station(2,149),localObservation:true);
        await repository.SaveStationAsync(Check.Station(3,501),localObservation:true);
        var player=new PlayerState{SystemName="Home",Position=new(0,0,0),MarketId=1};
        repository.PublicDataFilter=station=>NearbyMarketCachePolicy.Accepts(player,station,repository.GetStation(station.MarketId));
        await using var feed=new EddnSubscriber(repository);var at=DateTimeOffset.UtcNow.AddMinutes(-1);
        Check.That(await feed.ProcessMessageAsync(Message(2,"System 2",at)));
        Check.That(!await feed.ProcessMessageAsync(Message(3,"System 3",at)));
        Check.That(!await feed.ProcessMessageAsync(Message(4,"Unknown position",at)));
        Check.That(await feed.ProcessMessageAsync(Message(5,"Home",at)));
        await feed.ProcessMessageAsync(JsonSerializer.SerializeToElement(new Dictionary<string,object>
        {{"$schemaRef","https://eddn.edcd.io/schemas/journal/1"},{"header",new{gameversion="4.0"}},
         {"message",new{StarSystem="New nearby system",StarPos=new[]{100,0,0}}}}));
        Check.That(await feed.ProcessMessageAsync(Message(6,"New nearby system",at)));
        Check.That(await repository.SaveSnapshotAsync(new(Check.Station(9,5000),[Check.Quote(9,"food",20,19)],at,DataSource.Journal)));
        Check.Equal(4L,repository.Statistics().Quotes);Check.Equal(3L,feed.MarketsAccepted);
        Check.That(repository.GetStation(4) is null);Check.That(repository.GetStation(9) is not null);
        player=player with{Position=null,SystemName="Home"};
        Check.That(!await feed.ProcessMessageAsync(Message(2,"System 2",at.AddSeconds(1))));
        Check.That(await feed.ProcessMessageAsync(Message(5,"Home",at.AddSeconds(1))));
    }

    [Test]public async Task NormalRuntimeLeavesAnInvalidLegacyReceiptForExplicitMaintenanceWithoutScanning()
    {
        using var temporary=new TemporaryDirectory();var seed=temporary.Repository();
        await seed.SaveSnapshotAsync(new(Check.Station(1),[Check.Quote(1,"water",10,9)],DateTimeOffset.UtcNow,DataSource.Journal));
        var proof=seed.DatabasePath+".verified-generation.json";File.WriteAllText(proof,"{\"old\":true}");
        var diagnostic=seed.DatabasePath+".diagnostics.jsonl";var before=File.Exists(diagnostic)?File.ReadAllText(diagnostic):"";
        var backupTime=File.GetLastWriteTimeUtc(seed.VerifiedBackupPath);
        await using(var runtime=new ToolboxRuntime(temporary.Path))
        {
            await runtime.InitializeAsync(offline:true);
            await runtime.Markets.SaveSnapshotAsync(new(Check.Station(1),[Check.Quote(1,"water",11,10)],DateTimeOffset.UtcNow,DataSource.Journal));
            var additional=File.ReadAllText(diagnostic)[before.Length..];
            Check.That(!additional.Contains("full-integrity"));Check.That(!additional.Contains("verified-generation-rebuilt"));
            Check.Equal("{\"old\":true}",File.ReadAllText(proof));
            Check.Equal(backupTime,File.GetLastWriteTimeUtc(seed.VerifiedBackupPath));
            runtime.ClearMarketCacheBlockReason=()=>"请先停止当前任务。";
            var refusal=await runtime.ClearMarketCacheAsync();Check.That(!refusal.Succeeded);Check.Equal("请先停止当前任务。",refusal.Message);
            Check.Equal(1L,runtime.Markets.Statistics().Quotes);
        }
        Check.Equal("{\"old\":true}",File.ReadAllText(proof));
    }
}