using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Session;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class NativeFlightHealthGapPolicyTests
{
private static readonly DateTimeOffset Now=DateTimeOffset.Parse("2026-10-27T07:41:46+08:00");
[Test]public void AReleasedInputJumpMayOutlastThirtySecondsButNeverExceedsItsBoundedReadOnlyWindow()
{
var gap=new NativeFlightHealthGapPolicy();var error=new InvalidOperationException("Native main-ship health unavailable or stale");
Check.That(!gap.Observe(error,Now,false).PauseMonitoring);
Check.Equal("health-gap",gap.Observe(error,Now.AddSeconds(29),true).Phase);
var loading=gap.Observe(error,Now.AddSeconds(30),true);
Check.That(!loading.PauseMonitoring&&!loading.SafetyStop&&loading.ExpectedInputFreeJumpLoading);
Check.Equal("input-free-jump-loading",loading.Phase);Check.Equal(Now,loading.UnavailableSince!.Value);
Check.That(!gap.Observe(error,Now.AddMilliseconds(74999),true).PauseMonitoring);
Check.That(gap.Observe(error,Now.AddSeconds(75),true).PauseMonitoring);
}
[Test]public void MissingReleaseEvidenceAndTheOriginalJumpDeadlineNeverBorrowTheLoadingExemption()
{
var gap=new NativeFlightHealthGapPolicy();var error=new IOException("health transport");
gap.Observe(error,Now,false);
Check.That(gap.Observe(error,Now.AddSeconds(30),false).PauseMonitoring);
var witnessed=new NativeFlightHealthGapPolicy();witnessed.Observe(error,Now,true);
Check.That(!witnessed.Observe(error,Now.AddSeconds(31),true).PauseMonitoring);
// The coordinator withdraws its witness at the original jump's 75s,
// independent of this gap's later start or any intermediate polling.
Check.That(witnessed.Observe(error,Now.AddSeconds(60),false).PauseMonitoring);
}
[Test]public void UnknownIdentityAndWrappedProtocolErrorsNeverBecomeExpectedLoading()
{
foreach(var error in new Exception[]{new InvalidDataException("wrong ship"),new InvalidOperationException("Another controller owns navigation"),
new IOException("transport wrapper",new InvalidDataException("wrong build")),new IOException("unknown inner",new InvalidOperationException("unverified interface")),
new AggregateException(new IOException("pipe"),new InvalidDataException("reordered entity")),new FormatException("bad native value")})
{
Check.That(!NativeFlightHealthGapPolicy.RecoverableGap(error,default));
var result=new NativeFlightHealthGapPolicy().Observe(error,Now,true);
Check.That(result.PauseMonitoring&&!result.SafetyStop&&!result.ExpectedInputFreeJumpLoading);
}
}
[Test]public void OnlyKnownMissingHealthAndTransportErrorsReceiveReadOnlyGrace()
{
foreach(var error in new Exception[]{new FlightTelemetryUnavailableException("stale health"),new IOException("broken pipe"),new TimeoutException("read timeout"),
new OperationCanceledException("IPC read deadline"),new InvalidOperationException("Native player telemetry unavailable or stale"),
new AggregateException(new IOException("pipe"),new FlightTelemetryUnavailableException("stale"))})
Check.That(NativeFlightHealthGapPolicy.RecoverableGap(error,default));
using var stop=new CancellationTokenSource();stop.Cancel();
Check.That(!NativeFlightHealthGapPolicy.RecoverableGap(new IOException("pipe"),stop.Token));
var cancelled=false;try{new NativeFlightHealthGapPolicy().Observe(new IOException("pipe"),Now,true,stop.Token);}catch(OperationCanceledException){cancelled=true;}
Check.That(cancelled);
}
[Test]public void ALoadingWitnessNeverRenewsHealthInputAuthorityAndRecoveryNeedsAnActualNewSample()
{
var gap=new NativeFlightHealthGapPolicy();var sampled=Now;var error=new FlightTelemetryUnavailableException("stale");
Check.That(NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddMilliseconds(500)));
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddMilliseconds(501)));
gap.Observe(error,Now,true);Check.That(!gap.Observe(error,Now.AddSeconds(31),true).PauseMonitoring);
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddSeconds(31)));
gap.Recovered();Check.That(gap.UnavailableSince is null);
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddSeconds(32)));
Check.That(NativeFlightHealthGapPolicy.InputSampleFresh(Now.AddSeconds(32),Now.AddSeconds(32)));
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(Now.AddSeconds(33),Now.AddSeconds(32)));
}
[Test]public void RealHealthAndThreatProtectionPreemptsAnyLoadingWitness()
{
foreach(var error in new Exception[]{new FlightHealthPauseException(),new FlightThreatPauseException(),new AggregateException(new IOException("pipe"),new FlightHealthPauseException())})
{
var result=new NativeFlightHealthGapPolicy().Observe(error,Now,true);
Check.That(result.SafetyStop&&!result.PauseMonitoring&&!result.ExpectedInputFreeJumpLoading);Check.Equal("safety-stop",result.Phase);
}
}
}
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Session;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public sealed class NativeFlightHealthGapPolicyTests
{
private static readonly DateTimeOffset Now=DateTimeOffset.Parse("2026-10-27T07:41:46+08:00");
[Test]public void AReleasedInputJumpMayOutlastThirtySecondsButNeverExceedsItsBoundedReadOnlyWindow()
{
var gap=new NativeFlightHealthGapPolicy();var error=new InvalidOperationException("Native main-ship health unavailable or stale");
Check.That(!gap.Observe(error,Now,false).PauseMonitoring);
Check.Equal("health-gap",gap.Observe(error,Now.AddSeconds(29),true).Phase);
var loading=gap.Observe(error,Now.AddSeconds(30),true);
Check.That(!loading.PauseMonitoring&&!loading.SafetyStop&&loading.ExpectedInputFreeJumpLoading);
Check.Equal("input-free-jump-loading",loading.Phase);Check.Equal(Now,loading.UnavailableSince!.Value);
Check.That(!gap.Observe(error,Now.AddMilliseconds(74999),true).PauseMonitoring);
Check.That(gap.Observe(error,Now.AddSeconds(75),true).PauseMonitoring);
}
[Test]public void MissingReleaseEvidenceAndTheOriginalJumpDeadlineNeverBorrowTheLoadingExemption()
{
var gap=new NativeFlightHealthGapPolicy();var error=new IOException("health transport");
gap.Observe(error,Now,false);
Check.That(gap.Observe(error,Now.AddSeconds(30),false).PauseMonitoring);
var witnessed=new NativeFlightHealthGapPolicy();witnessed.Observe(error,Now,true);
Check.That(!witnessed.Observe(error,Now.AddSeconds(31),true).PauseMonitoring);
// The coordinator withdraws its witness at the original jump's 75s,
// independent of this gap's later start or any intermediate polling.
Check.That(witnessed.Observe(error,Now.AddSeconds(60),false).PauseMonitoring);
}
[Test]public void UnknownIdentityAndWrappedProtocolErrorsNeverBecomeExpectedLoading()
{
foreach(var error in new Exception[]{new InvalidDataException("wrong ship"),new InvalidOperationException("Another controller owns navigation"),
new IOException("transport wrapper",new InvalidDataException("wrong build")),new IOException("unknown inner",new InvalidOperationException("unverified interface")),
new AggregateException(new IOException("pipe"),new InvalidDataException("reordered entity")),new FormatException("bad native value")})
{
Check.That(!NativeFlightHealthGapPolicy.RecoverableGap(error,default));
var result=new NativeFlightHealthGapPolicy().Observe(error,Now,true);
Check.That(result.PauseMonitoring&&!result.SafetyStop&&!result.ExpectedInputFreeJumpLoading);
}
}
[Test]public void OnlyKnownMissingHealthAndTransportErrorsReceiveReadOnlyGrace()
{
foreach(var error in new Exception[]{new FlightTelemetryUnavailableException("stale health"),new IOException("broken pipe"),new TimeoutException("read timeout"),
new OperationCanceledException("IPC read deadline"),new InvalidOperationException("Native player telemetry unavailable or stale"),
new AggregateException(new IOException("pipe"),new FlightTelemetryUnavailableException("stale"))})
Check.That(NativeFlightHealthGapPolicy.RecoverableGap(error,default));
using var stop=new CancellationTokenSource();stop.Cancel();
Check.That(!NativeFlightHealthGapPolicy.RecoverableGap(new IOException("pipe"),stop.Token));
var cancelled=false;try{new NativeFlightHealthGapPolicy().Observe(new IOException("pipe"),Now,true,stop.Token);}catch(OperationCanceledException){cancelled=true;}
Check.That(cancelled);
}
[Test]public void ALoadingWitnessNeverRenewsHealthInputAuthorityAndRecoveryNeedsAnActualNewSample()
{
var gap=new NativeFlightHealthGapPolicy();var sampled=Now;var error=new FlightTelemetryUnavailableException("stale");
Check.That(NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddMilliseconds(500)));
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddMilliseconds(501)));
gap.Observe(error,Now,true);Check.That(!gap.Observe(error,Now.AddSeconds(31),true).PauseMonitoring);
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddSeconds(31)));
gap.Recovered();Check.That(gap.UnavailableSince is null);
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(sampled,Now.AddSeconds(32)));
Check.That(NativeFlightHealthGapPolicy.InputSampleFresh(Now.AddSeconds(32),Now.AddSeconds(32)));
Check.That(!NativeFlightHealthGapPolicy.InputSampleFresh(Now.AddSeconds(33),Now.AddSeconds(32)));
}
[Test]public void RealHealthAndThreatProtectionPreemptsAnyLoadingWitness()
{
foreach(var error in new Exception[]{new FlightHealthPauseException(),new FlightThreatPauseException(),new AggregateException(new IOException("pipe"),new FlightHealthPauseException())})
{
var result=new NativeFlightHealthGapPolicy().Observe(error,Now,true);
Check.That(result.SafetyStop&&!result.PauseMonitoring&&!result.ExpectedInputFreeJumpLoading);Check.Equal("safety-stop",result.Phase);
}
}
}