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

XFESystem

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

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

namespace XFESystem.Core.Tests;

public sealed class RenderBackendSelectionTests
{
    private static RenderBackendProbeResult Software() => new(
        new("CPU framebuffer", RenderAdapterKind.Software, RenderBackendKind.CpuFramebuffer, RenderExecutionScope.XFESystemGuest),
        true, true, true, false, false, "Initialized framebuffer; pixel write and presentation verified.");

    private static RenderBackendProbeResult Gpu(RenderAdapterKind adapter, RenderBackendKind kind = RenderBackendKind.NativeGpu,
        RenderExecutionScope scope = RenderExecutionScope.XFESystemGuest, ushort vendor = 0x10DE) => new(
        new(adapter.ToString(), adapter, kind, scope, vendor), true, true, true, true,
        kind == RenderBackendKind.Cuda, "Actual driver/context, submission result and presentation verified by owning runtime.");

    [Fact]
    public void VerifiedDiscreteGpuIsPreferredRegardlessOfEnumerationOrder()
    {
        var discrete = Gpu(RenderAdapterKind.Discrete);
        var selection = RenderBackendSelection.Select([Software(), Gpu(RenderAdapterKind.Integrated), discrete]);
        Assert.Equal(discrete, selection.Selected);
        Assert.True(selection.GpuAccelerationActive);
        Assert.False(selection.CudaAccelerationActive);
    }

    [Fact]
    public void FailedDiscreteInitializationFallsBackToVerifiedIntegratedGpu()
    {
        var integrated = Gpu(RenderAdapterKind.Integrated);
        var failed = Gpu(RenderAdapterKind.Discrete) with { InitializationPassed = false, Evidence = "No native NVIDIA driver." };
        var selection = RenderBackendSelection.Select([Software(), failed, integrated]);
        Assert.Equal(integrated, selection.Selected);
        Assert.Contains("No native NVIDIA driver.", selection.Attempts[1].Reason);
    }

    [Fact]
    public void HostCudaSuccessCannotEnableCudaInTheGuest()
    {
        var selection = RenderBackendSelection.Select([Gpu(RenderAdapterKind.Discrete, RenderBackendKind.Cuda, RenderExecutionScope.Host), Software()]);
        Assert.Equal(Software(), selection.Selected);
        Assert.False(selection.GpuAccelerationActive);
        Assert.False(selection.CudaAccelerationActive);
        Assert.Contains("host hardware is not a guest backend", selection.Attempts[0].Reason);
    }

    [Fact]
    public void VerifiedCudaIsOnlySelectableInItsActualExecutionScope()
    {
        var host = Gpu(RenderAdapterKind.Discrete, RenderBackendKind.Cuda, RenderExecutionScope.Host);
        var selection = RenderBackendSelection.Select([host], RenderExecutionScope.Host);
        Assert.Equal(host, selection.Selected);
        Assert.True(selection.CudaAccelerationActive);
    }

    [Theory]
    [InlineData(false, true, true)]
    [InlineData(true, false, true)]
    [InlineData(true, true, false)]
    public void UnverifiedGpuNeverSupplantsAWorkingCpuRenderer(bool initialization, bool rendering, bool presentation)
    {
        var pending = Gpu(RenderAdapterKind.Discrete) with
        { InitializationPassed = initialization, RenderSelfTestPassed = rendering, PresentationSelfTestPassed = presentation };
        var selection = RenderBackendSelection.Select([pending, Software()]);
        Assert.Equal(Software(), selection.Selected);
        Assert.False(selection.GpuAccelerationActive);
    }

    [Fact]
    public void EnumeratedCudaAdapterWithoutCudaSubmissionIsRejected()
    {
        var cuda = Gpu(RenderAdapterKind.Discrete, RenderBackendKind.Cuda) with { CudaSubmissionVerified = false };
        var selection = RenderBackendSelection.Select([cuda, Software()]);
        Assert.False(selection.CudaAccelerationActive);
        Assert.False(selection.Attempts[0].Eligible);
        Assert.Contains("No CUDA kernel submission", selection.Attempts[0].Reason);
    }

    [Fact]
    public void CudaCannotRunOnAnAmdAdapter()
    {
        var amd = Gpu(RenderAdapterKind.Integrated, RenderBackendKind.Cuda, vendor: 0x1002);
        var selection = RenderBackendSelection.Select([amd, Software()]);
        Assert.Equal(Software(), selection.Selected);
        Assert.Contains("NVIDIA", selection.Attempts[0].Reason);
    }

    [Fact]
    public void VirtIo2DIsCpuRasterizationEvenWhenAHostGpuCompositesTheDisplay()
    {
        var virtio = Software() with { Identity = new("virtio-gpu 2D", RenderAdapterKind.Virtual, RenderBackendKind.VirtIo2D, RenderExecutionScope.XFESystemGuest) };
        var selection = RenderBackendSelection.Select([virtio]);
        Assert.Equal(virtio, selection.Selected);
        Assert.False(selection.GpuAccelerationActive);
        Assert.False(selection.CudaAccelerationActive);
        Assert.False(RenderBackendSelection.Select([virtio with { RasterizationOnGpu = true }]).HasBackend);
    }

    [Fact]
    public void MissingEvidenceOrMissingDriverCannotInventASoftwareFallback()
    {
        Assert.False(RenderBackendSelection.Select([]).HasBackend);
        Assert.False(RenderBackendSelection.Select([Software() with { Evidence = "" }]).HasBackend);
        Assert.False(RenderBackendSelection.Select([Software() with { InitializationPassed = false }]).HasBackend);
    }

    [Fact]
    public void GpuLabelAloneCannotConvertACpuFramebufferToAnAccelerator()
    {
        var mislabeled = Software() with
        { Identity = new("RTX 5090 framebuffer", RenderAdapterKind.Discrete, RenderBackendKind.CpuFramebuffer, RenderExecutionScope.XFESystemGuest, 0x10DE), RasterizationOnGpu = true };
        var selection = RenderBackendSelection.Select([mislabeled, Software()]);
        Assert.Equal(Software(), selection.Selected);
        Assert.False(selection.GpuAccelerationActive);
    }

    private sealed class Probe(RenderBackendProbeResult result) : IRenderBackendProbe
    {
        public RenderBackendIdentity Identity => result.Identity;
        public int Initializations { get; private set; }
        public RenderBackendProbeResult InitializeAndVerify() { Initializations++; return result; }
    }

    [Fact]
    public void InitializationEntryPointCallsEachOwningDriverExactlyOnce()
    {
        var software = new Probe(Software());
        var discrete = new Probe(Gpu(RenderAdapterKind.Discrete) with { InitializationPassed = false });
        var selected = RenderBackendSelection.InitializeAndSelect([discrete, software]);
        Assert.Equal(1, discrete.Initializations);
        Assert.Equal(1, software.Initializations);
        Assert.Equal(Software(), selected.Selected);
    }

    private sealed class FailingProbe : IRenderBackendProbe
    {
        public RenderBackendIdentity Identity => Gpu(RenderAdapterKind.Discrete).Identity;
        public RenderBackendProbeResult InitializeAndVerify() => throw new InvalidOperationException("Device initialization failed.");
    }

    [Fact]
    public void FailedGpuDriverExceptionStillPermitsTheWorkingCpuRenderer()
    {
        var selection = RenderBackendSelection.InitializeAndSelect([new FailingProbe(), new Probe(Software())]);
        Assert.Equal(Software(), selection.Selected);
        Assert.Contains("Device initialization failed.", selection.Attempts[0].Reason);
    }

    [Fact]
    public void UnknownEnumsAreRejectedRatherThanGivenHigherGpuPriority()
    {
        var invalid = Gpu((RenderAdapterKind)999);
        Assert.False(RenderBackendSelection.Select([invalid]).HasBackend);
        Assert.False(RenderBackendSelection.Select([invalid with { Identity = invalid.Identity with { Adapter = RenderAdapterKind.Discrete, Backend = (RenderBackendKind)999 } }]).HasBackend);
    }
}