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

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using XFESystem.Kernel;
using Xunit;

namespace XFESystem.Core.Tests;

public sealed class NetworkBootWaitTests
{
    [Fact]
    public void AlreadyReadyDoesNotWaitForAnyInterrupt()
    {
        Assert.True(NativeNetworkBootWait.WaitUntilReady(() => true, () => 42, 1_000,
            () => throw new InvalidOperationException("No wait expected.")));
    }

    [Fact]
    public void NeverReadyTimesOutAfterFiveSecondsWithoutPitTicks()
    {
        long now = 0;
        int lapicInterrupts = 0, polls = 0;
        Assert.False(NativeNetworkBootWait.WaitUntilReady(() => { polls++; return false; }, () => now, 1_000,
            () => { lapicInterrupts++; now += 10; }));
        Assert.Equal(5_000, now);
        Assert.Equal(500, lapicInterrupts);
        Assert.Equal(500, polls);
    }

    [Theory]
    [InlineData(4_990, true)]
    [InlineData(5_000, false)]
    [InlineData(5_010, false)]
    public void ReadinessMustArriveBeforeTheDeadline(int readyAt, bool expected)
    {
        long now = 0;
        Assert.Equal(expected, NativeNetworkBootWait.WaitUntilReady(() => now >= readyAt, () => now, 1_000,
            () => now += 10));
        Assert.Equal(expected ? readyAt : 5_000, now);
    }

    [Fact]
    public void LongInterruptWaitCountsTowardTheSameBudget()
    {
        long now = 0;
        int polls = 0, waits = 0;
        Assert.False(NativeNetworkBootWait.WaitUntilReady(() => { polls++; return false; }, () => now, 1_000,
            () => { waits++; now += 9_000; }));
        Assert.Equal(1, waits);
        Assert.Equal(1, polls);
    }

    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void PollingTimeCannotExtendTheDeadline(bool ready)
    {
        long now = 0;
        Assert.False(NativeNetworkBootWait.WaitUntilReady(() => { now += 5_000; return ready; }, () => now, 1_000,
            () => throw new InvalidOperationException("An expired poll must not wait.")));
    }

    [Theory]
    [InlineData(1)]
    [InlineData(1_000)]
    [InlineData(1_000_000_001)]
    public void UsesTheSuppliedTimestampFrequency(long frequency)
    {
        long now = 0;
        int waits = 0;
        Assert.False(NativeNetworkBootWait.WaitUntilReady(() => false, () => now, frequency,
            () => { waits++; now += frequency; }));
        Assert.Equal(5, waits);
        Assert.Equal(frequency * 5, now);
    }

    [Theory]
    [InlineData(long.MaxValue - 2_000)]
    [InlineData(-2_000)]
    public void TimestampWrapDoesNotOverflowOrSkipTheTimeout(long start)
    {
        long now = start;
        int waits = 0;
        Assert.False(NativeNetworkBootWait.WaitUntilReady(() => false, () => now, 1_000,
            () => { waits++; now = unchecked(now + 1_000); }));
        Assert.Equal(5, waits);
        Assert.Equal(unchecked(start + 5_000), now);
    }

    [Fact]
    public void LargestSupportedBudgetDoesNotOverflow()
    {
        const long frequency = long.MaxValue / 5;
        long now = 100;
        int waits = 0;
        Assert.False(NativeNetworkBootWait.WaitUntilReady(() => false, () => now, frequency,
            () => { waits++; now = unchecked(now + frequency * 5); }));
        Assert.Equal(1, waits);
    }

    [Fact]
    public void BackwardsClockFailsClosed()
    {
        long now = 100;
        int waits = 0;
        Assert.False(NativeNetworkBootWait.WaitUntilReady(() => false, () => now, 1_000,
            () => { waits++; now--; }));
        Assert.Equal(1, waits);
    }

    [Theory]
    [InlineData(0)]
    [InlineData(-1)]
    [InlineData(long.MaxValue / 5 + 1)]
    [InlineData(long.MaxValue)]
    public void InvalidOrUnrepresentableFrequencyIsRejectedBeforeWaiting(long frequency)
    {
        Assert.Throws<ArgumentOutOfRangeException>(() => NativeNetworkBootWait.WaitUntilReady(
            () => throw new InvalidOperationException("No poll expected."),
            () => throw new InvalidOperationException("No timestamp expected."), frequency,
            () => throw new InvalidOperationException("No wait expected.")));
    }
}