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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

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

namespace XFEEDToolBox.Test;

[TestFixture]
public sealed class StationAccessWaiterTests
{
    [Test]public async Task OneJournalPassResolvesAllKnownMarketsForThisFidAndActualPaymentRemovesTheirFineExclusion()
    {
        using var directory=new TemporaryDirectory();var rows=new List<object>{new{@event="LoadGame",FID="F1"}};
        for(var market=1;market<=100;market++)rows.Add(new{@event="Docked",MarketID=market,StationFaction=new{Name="Authority"}});
        rows.Add(new{@event="CommitCrime",Faction="Authority",Fine=400});
        rows.Add(new{@event="LoadGame",FID="F2"});rows.Add(new{@event="PayFines",Faction="Authority",Amount=400,AllFines=true});
        var path=directory.File("Journal.fines.log");await File.WriteAllLinesAsync(path,rows.Select(value=>JsonSerializer.Serialize(value)));
        var before=await StationAccessWaiter.ReadKnownFinesAsync(directory.Path,"F1",default);
        Check.Equal(1,before.JournalFilesRead);Check.Equal(100,before.Restrictions.Count);Check.Equal(400L,before.FineAt(1));Check.Equal(400L,before.FineAt(100));
        Check.Equal("Authority",before.Restrictions[1].Authority);Check.Equal(0L,before.FineAt(999));
        await File.AppendAllLinesAsync(path,new object[]{new{@event="LoadGame",FID="F1"},new{@event="PayFines",Faction="Authority",Amount=400}}.Select(value=>JsonSerializer.Serialize(value)));
        var after=await StationAccessWaiter.ReadKnownFinesAsync(directory.Path,"F1",default);
        Check.Equal(1,after.JournalFilesRead);Check.Equal(0,after.Restrictions.Count);Check.Equal(0L,after.FineAt(1));
        Check.Equal(400L,before.FineAt(1));
    }
    [Test]public void UnchangedFineReportsOnceAndBacksOffWithABoundedDelayWhileChangedAmountReportsImmediately()
    {
        var schedule=new StationAccessWaitSchedule();var reports=0;var seconds=new List<double>();
        for(var i=0;i<8;i++){var observation=schedule.Observe(400);if(observation.Report)reports++;seconds.Add(observation.Delay.TotalSeconds);}
        Check.Equal(1,reports);Check.Equal("1,2,4,8,15,30,30,30",string.Join(',',seconds));
        var changed=schedule.Observe(200);Check.That(changed.Report);Check.Equal(TimeSpan.FromSeconds(1),changed.Delay);
        Check.That(!schedule.Observe(200).Report);
    }
    [Test]public async Task AWaitingTradeNeverContinuesAfterThePlayerChangesShipSessionOrDockedMarket()
    {
        foreach(var change in new Func<PlayerState,PlayerState>[]
        {
            p=>p with{CommanderId="Other"},p=>p with{CurrentShipId=8},p=>p with{LoadGameAt=p.LoadGameAt!.Value.AddSeconds(1)},
            p=>p with{MarketId=3},p=>p with{Docked=false},p=>p with{InGame=false}
        })
        {
            using var directory=new TemporaryDirectory();var at=DateTimeOffset.UtcNow.AddMinutes(-1);
            var current=new PlayerState{InGame=true,Docked=true,MarketId=2,CommanderId="F1",CurrentShipId=7,LoadGameAt=at};
            await File.WriteAllLinesAsync(directory.File("Journal.fine.log"),new object[]
            {
                new{@event="LoadGame",FID="F1"},new{@event="Docked",MarketID=2,StationFaction=new{Name="Authority"}},
                new{@event="CommitCrime",Faction="Authority",Fine=400}
            }.Select(value=>JsonSerializer.Serialize(value)));
            using var budget=new CancellationTokenSource(TimeSpan.FromSeconds(4));var refused=false;
            try{await StationAccessWaiter.WaitAsync(directory.Path,()=>current,2,_=>current=change(current),budget.Token);}
            catch(Exception error)when(error is InvalidDataException or InvalidOperationException){refused=true;}
            Check.That(refused,"Changing the actual ship/session/port must stop the waiting order rather than clear its fine gate.");
        }
    }
}