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

XFESystem

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

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Runtime.InteropServices;
using XFESystem.Boot;
using Xunit;

namespace XFESystem.Boot.Tests;

public unsafe class DisplayPolicyTests
{
    static DisplayMode Mode(uint id, uint width, uint height) => new()
    { Id = id, Width = width, Height = height, StridePixels = width, BitsPerPixel = 32, Flags = 1 };

    [Fact]
    public void VersionOneHandoffPreservesAllPublishedOffsets()
    {
        Assert.Equal(24, sizeof(DisplayMode));
        Assert.Equal(7520, sizeof(DisplayRecord));
        Assert.Equal(60192, sizeof(DisplayHandoff));
        Assert.Equal(96, Marshal.OffsetOf<DisplayRecord>(nameof(DisplayRecord.Modes)).ToInt32());
        Assert.Equal(3168, Marshal.OffsetOf<DisplayRecord>(nameof(DisplayRecord.Edid)).ToInt32());
        Assert.Equal(7264, Marshal.OffsetOf<DisplayRecord>(nameof(DisplayRecord.Path)).ToInt32());
        Assert.Equal(32, Marshal.OffsetOf<DisplayHandoff>(nameof(DisplayHandoff.Displays)).ToInt32());
    }

    [Fact]
    public void FirmwareProtocolLayoutsMatchUefiX64Offsets()
    {
        Type entry = typeof(EfiEntry);
        Type Table(string name) => entry.GetNestedType(name, System.Reflection.BindingFlags.NonPublic)!;
        Assert.Equal(24, Marshal.SizeOf(Table("TableHeader")));
        Assert.Equal(120, Marshal.SizeOf(Table("SystemTable")));
        Assert.Equal(96, Marshal.OffsetOf(Table("SystemTable"), "Boot").ToInt32());
        Assert.Equal(24, Marshal.OffsetOf(Table("BootServices"), "Functions").ToInt32());
        Assert.Equal(36, Marshal.SizeOf(Table("ModeInfo")));
        Assert.Equal(40, Marshal.SizeOf(Table("GopMode")));
        Assert.Equal(24, Marshal.OffsetOf(Table("GopMode"), "Base").ToInt32());
        Assert.Equal(24, Marshal.OffsetOf(Table("Graphics"), "Mode").ToInt32());
        Assert.Equal(24, Marshal.OffsetOf(Table("LoadedImage"), "Device").ToInt32());
        Assert.Equal(16, Marshal.SizeOf(Table("Edid")));
        Assert.Equal(72, Marshal.SizeOf(Table("ExitContext")));
    }

    [Fact]
    public void ChoosesMaximumValidGeometryWithoutEdid()
    {
        DisplayMode* modes = stackalloc DisplayMode[3] { Mode(4, 1024, 768), Mode(7, 3840, 2160), Mode(9, 800, 600) };
        Assert.Equal(7u, DisplayPolicy.ChooseMode(modes, 3, null, 0, 42));
        modes[1].Flags = 0;
        Assert.Equal(4u, DisplayPolicy.ChooseMode(modes, 3, null, 0, 42));
        modes[0].StridePixels = 1;
        Assert.Equal(9u, DisplayPolicy.ChooseMode(modes, 3, null, 0, 42));
    }

    [Fact]
    public void SelectsLargestMonitorFirmwareIntersection()
    {
        byte* edid = stackalloc byte[128]; InitEdid(edid);
        SetDetailed(edid + 54, 1920, 1080);
        SetDetailed(edid + 72, 3840, 2160);
        Checksum(edid);
        DisplayMode* modes = stackalloc DisplayMode[3] { Mode(1, 1920, 1080), Mode(2, 3840, 2160), Mode(3, 4096, 2160) };
        Assert.Equal(2u, DisplayPolicy.ChooseMode(modes, 3, edid, 128, 42));
        edid[12] ^= 1;
        Assert.Equal(3u, DisplayPolicy.ChooseMode(modes, 3, edid, 128, 42));
    }

    [Theory]
    [InlineData(0u, 0u)]
    [InlineData(319u, 480u)]
    [InlineData(640u, 199u)]
    [InlineData(16385u, 2160u)]
    [InlineData(1920u, 16385u)]
    public void RejectsInvalidDimensions(uint width, uint height) => Assert.False(Mode(0, width, height).IsValid);

    [Fact]
    public void RejectsUnsupportedDepthAndOversizedFramebuffer()
    {
        DisplayMode mode = Mode(0, 3840, 2160); mode.BitsPerPixel = 16;
        Assert.False(mode.IsValid);
        mode = Mode(0, 16384, 16384);
        Assert.False(mode.IsValid);
    }

    [Fact]
    public void DeterministicTiePrefersDepthThenLowestModeId()
    {
        DisplayMode* modes = stackalloc DisplayMode[3] { Mode(5, 1920, 1080), Mode(8, 1920, 1080), Mode(3, 1920, 1080) };
        modes[2].BitsPerPixel = 24;
        Assert.Equal(5u, DisplayPolicy.ChooseMode(modes, 3, null, 0, 42));
        modes[2].BitsPerPixel = 32;
        Assert.Equal(3u, DisplayPolicy.ChooseMode(modes, 3, null, 0, 42));
    }

    [Fact]
    public void BoundedInputAndNoValidModeReturnOriginalMode()
    {
        DisplayMode* modes = stackalloc DisplayMode[1];
        modes[0] = default;
        Assert.Equal(42u, DisplayPolicy.ChooseMode(null, 0, null, 0, 42));
        Assert.Equal(42u, DisplayPolicy.ChooseMode(modes, 129, null, 0, 42));
        Assert.Equal(42u, DisplayPolicy.ChooseMode(modes, 1, null, 0, 42));
    }

    [Fact]
    public void CtaVideoDataBlockSuppliesFourKWithCheckedExtension()
    {
        byte* edid = stackalloc byte[256]; InitEdid(edid, 256);
        edid[126] = 1; Checksum(edid);
        byte* cta = edid + 128; cta[0] = 2; cta[1] = 3; cta[2] = 6; cta[4] = 0x41; cta[5] = 97; Checksum(cta);
        Assert.True(DisplayPolicy.EdidAdvertises(edid, 256, 3840, 2160));
        Assert.False(DisplayPolicy.EdidAdvertises(edid, 128, 3840, 2160));
        cta[127] ^= 1;
        Assert.False(DisplayPolicy.EdidAdvertises(edid, 256, 3840, 2160));
    }

    [Fact]
    public void StandardTimingsAndMalformedCtaAreBounded()
    {
        byte* edid = stackalloc byte[256]; InitEdid(edid, 256);
        edid[38] = 209; edid[39] = 0xC0; edid[126] = 1; Checksum(edid);
        byte* cta = edid + 128; cta[0] = 2; cta[2] = 5; cta[4] = 0x5F; Checksum(cta);
        Assert.True(DisplayPolicy.EdidAdvertises(edid, 256, 1920, 1080));
        Assert.False(DisplayPolicy.EdidAdvertises(edid, 256, 3840, 2160));
        Assert.False(DisplayPolicy.IsEdidValid(edid, 127));
        Assert.False(DisplayPolicy.IsEdidValid(edid, 4097));
    }

    static void InitEdid(byte* bytes, int count = 128)
    {
        for (int i = 0; i < count; i++) bytes[i] = 0;
        for (int i = 1; i < 7; i++) bytes[i] = 255;
        bytes[18] = 1;
    }
    static void SetDetailed(byte* bytes, uint width, uint height)
    {
        bytes[0] = 1; bytes[2] = (byte)width; bytes[4] = (byte)((width >> 8) << 4);
        bytes[5] = (byte)height; bytes[7] = (byte)((height >> 8) << 4);
    }
    static void Checksum(byte* bytes)
    {
        byte sum = 0;
        for (int i = 0; i < 127; i++) sum = (byte)(sum + bytes[i]);
        bytes[127] = (byte)(0 - sum);
    }
}