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

XFESystem

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

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

namespace XFESystem.Desktop.Tests;

public sealed class DesktopWebFrameCacheTests
{
    private static DesktopWebFrameKey Key(long page = 1, long revision = 2, long layout = 3, int width = 4, int height = 3,
        int scale = 200, double scrollX = 0, double scrollY = 0) => new(page, revision, layout, width, height, scale, scrollX, scrollY);

    [Fact]
    public void BackgroundRestoreCannotOverwriteProtectedForegroundMotionPixels()
    {
        var cache=new DesktopWebFrameCache();var pixels=Enumerable.Range(0,120).ToArray();var original=(int[])pixels.Clone();
        Assert.True(cache.Store(Key(),pixels,12,10,1,2,new(0,0,12,10)));Array.Fill(pixels,-1);
        Assert.True(cache.TryRestore(Key(),pixels,12,10,7,6,new(0,0,12,10),new(8,7,2,1)));
        for(int y=0;y<10;y++)for(int x=0;x<12;x++)
        {
            bool viewport=x>=7&&x<11&&y>=6&&y<9,protectedPixel=x>=8&&x<10&&y==7;
            Assert.Equal(viewport&&!protectedPixel?original[(y-6+2)*12+x-7+1]:-1,pixels[y*12+x]);
        }
        Assert.Equal(10,cache.PixelsRestored);
        Assert.True(cache.TryRestore(Key(),pixels,12,10,7,6,new(0,0,12,10),new(0,0,12,10)));
        Assert.Equal(10,cache.PixelsRestored);
    }

    [Fact]
    public void CaptureRejectsAnyForegroundPreservationIntersectionWithoutEvictingGoodFrames()
    {
        var cache=new DesktopWebFrameCache(maximumBytes:48,maximumEntries:1);var pixels=Enumerable.Range(0,48).ToArray();
        Assert.True(cache.Store(Key(),pixels,8,6,1,1,new(0,0,8,6)));
        Assert.False(cache.Store(Key(page:2),pixels,8,6,1,1,new(0,0,8,6),new(4,2,1,1)));
        Assert.Equal(1,cache.Count);Assert.Equal(0,cache.Evictions);Assert.Equal(1,cache.Captures);
        Assert.True(cache.TryRestore(Key(),pixels,8,6,1,1,new(0,0,8,6)));
        Assert.True(cache.Store(Key(page:2),pixels,8,6,1,1,new(0,0,8,6),new(5,2,1,1)));
    }

    [Fact]
    public void ProtectedRestoreKeepsExactPixelsAndAccountingForClippedAndOffscreenDestinations()
    {
        var cache=new DesktopWebFrameCache();var original=Enumerable.Range(0,120).ToArray();var pixels=new int[120];
        Assert.True(cache.Store(Key(),original,12,10,1,2,new(0,0,12,10)));
        foreach(int destinationX in new[]{-3,0,7,10})foreach(int destinationY in new[]{-2,0,6,9})
        foreach(var clip in new[]{new DesktopBounds(0,0,12,10),new DesktopBounds(2,1,7,5)})
        foreach(var preserved in new[]{new DesktopBounds(8,7,2,1),new DesktopBounds(-2,-2,4,5),new DesktopBounds(11,9,100,100),
            new DesktopBounds(0,0,0,0),new DesktopBounds(int.MinValue,0,int.MaxValue,10),new DesktopBounds(0,int.MinValue,12,int.MaxValue)})
        {
            Array.Fill(pixels,-1);long before=cache.PixelsRestored;int copied=0;
            Assert.True(cache.TryRestore(Key(),pixels,12,10,destinationX,destinationY,clip,preserved));
            for(int y=0;y<10;y++)for(int x=0;x<12;x++)
            {
                bool viewport=x>=destinationX&&x<destinationX+4&&y>=destinationY&&y<destinationY+3;
                bool inClip=x>=clip.X&&x<clip.X+clip.Width&&y>=clip.Y&&y<clip.Y+clip.Height;
                bool protect=x>=preserved.X&&(long)x<(long)preserved.X+preserved.Width&&y>=preserved.Y&&(long)y<(long)preserved.Y+preserved.Height;
                bool copy=viewport&&inClip&&!protect;if(copy)copied++;
                Assert.Equal(copy?original[(2+y-destinationY)*12+1+x-destinationX]:-1,pixels[y*12+x]);
            }
            Assert.Equal(copied,cache.PixelsRestored-before);
        }
    }

    [Fact]
    public void RestoreCopiesOnlyCurrentDamageAndReusesPixelsAtAnotherPosition()
    {
        var cache = new DesktopWebFrameCache(); var pixels = Enumerable.Range(0, 120).ToArray();
        Assert.True(cache.Store(Key(), pixels, 12, 10, 1, 2, new(1, 2, 4, 3)));
        var stored = (int[])pixels.Clone(); Array.Fill(pixels, -1);
        Assert.True(cache.TryRestore(Key(), pixels, 12, 10, 7, 6, new(8, 7, 2, 1)));
        for (int y = 0; y < 10; y++) for (int x = 0; x < 12; x++)
            Assert.Equal(y == 7 && x is >= 8 and < 10 ? stored[(2 + y - 6) * 12 + 1 + x - 7] : -1, pixels[y * 12 + x]);
        Assert.Equal(2, cache.PixelsRestored); Assert.Equal(1, cache.RestoreHits); Assert.Equal(48, cache.CachedBytes);
    }

    [Fact]
    public void RestoreClipsNegativeDestinationToTheRealFramebuffer()
    {
        var cache = new DesktopWebFrameCache(); var pixels = Enumerable.Range(0, 48).ToArray();
        Assert.True(cache.Store(Key(), pixels, 8, 6, 2, 1, new(0, 0, 8, 6))); var stored = (int[])pixels.Clone(); Array.Fill(pixels, -1);
        Assert.True(cache.TryRestore(Key(), pixels, 8, 6, -2, -1, new(0, 0, 8, 6)));
        for (int y = 0; y < 6; y++) for (int x = 0; x < 8; x++)
            Assert.Equal(y < 2 && x < 2 ? stored[(1 + y + 1) * 8 + 2 + x + 2] : -1, pixels[y * 8 + x]);
    }

    [Fact]
    public void PartialOrOffscreenCaptureCannotReplaceAnExistingFullFrame()
    {
        var cache = new DesktopWebFrameCache(); var pixels = Enumerable.Range(0, 48).ToArray();
        Assert.True(cache.Store(Key(), pixels, 8, 6, 2, 1, new(0, 0, 8, 6))); var stored = (int[])pixels.Clone(); Array.Fill(pixels, -1);
        Assert.False(cache.Store(Key(), pixels, 8, 6, 2, 1, new(2, 1, 3, 3)));
        Assert.False(cache.Store(Key(page: 2), pixels, 8, 6, -1, 0, new(0, 0, 8, 6)));
        Assert.False(cache.Store(Key(page: 3), pixels, 8, 6, 5, 4, new(0, 0, 8, 6)));
        Assert.Equal(1, cache.Count); Assert.Equal(1, cache.Captures);
        Assert.True(cache.TryRestore(Key(), pixels, 8, 6, 2, 1, new(0, 0, 8, 6)));
        for (int y = 1; y < 4; y++) for (int x = 2; x < 6; x++) Assert.Equal(stored[y * 8 + x], pixels[y * 8 + x]);
    }

    [Fact]
    public void EveryContentGeometryAndScaleKeyFieldInvalidatesTheFrame()
    {
        var cache = new DesktopWebFrameCache(); var pixels = new int[48];
        Assert.True(cache.Store(Key(), pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        foreach (var key in new[] { Key(page: 2), Key(revision: 4), Key(layout: 5), Key(width: 5), Key(height: 4),
                     Key(scale: 100), Key(scrollX: .25), Key(scrollY: 1) })
            Assert.False(cache.TryRestore(key, pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        Assert.True(cache.TryRestore(Key(), pixels, 8, 6, 100, 100, new(0, 0, 8, 6)));
        Assert.Equal(0, cache.PixelsRestored);
    }

    [Fact]
    public void EntryBoundUsesLeastRecentlyRestoredAndStoredOrder()
    {
        var cache = new DesktopWebFrameCache(maximumBytes: 96, maximumEntries: 2); var pixels = new int[12];
        Assert.True(cache.Store(Key(page: 1), pixels, 4, 3, 0, 0, new(0, 0, 4, 3)));
        Assert.True(cache.Store(Key(page: 2), pixels, 4, 3, 0, 0, new(0, 0, 4, 3)));
        Assert.True(cache.TryRestore(Key(page: 1), pixels, 4, 3, 0, 0, new(0, 0, 4, 3)));
        Assert.True(cache.Store(Key(page: 3), pixels, 4, 3, 0, 0, new(0, 0, 4, 3)));
        Assert.False(cache.TryRestore(Key(page: 2), pixels, 4, 3, 0, 0, new(0, 0, 4, 3)));
        Assert.True(cache.TryRestore(Key(page: 1), pixels, 4, 3, 0, 0, new(0, 0, 4, 3)));
        Assert.Equal(2, cache.Count); Assert.Equal(96, cache.CachedBytes); Assert.Equal(1, cache.Evictions);
    }

    [Fact]
    public void GlobalByteBoundIsThirtyTwoMiBAndEntryBoundIsSix()
    {
        var cache = new DesktopWebFrameCache(); var pixels = new int[2048 * 1024];
        for (int page = 1; page <= 7; page++)
        {
            Assert.True(cache.Store(Key(page: page, width: 2048, height: 1024), pixels, 2048, 1024, 0, 0, new(0, 0, 2048, 1024)));
            Assert.InRange(cache.Count, 1, 6); Assert.InRange(cache.CachedBytes, 1, 32L * 1024 * 1024);
        }
        Assert.Equal(4, cache.Count); Assert.Equal(32L * 1024 * 1024, cache.CachedBytes); Assert.Equal(3, cache.Evictions);
        var tiny = new DesktopWebFrameCache(); var one = new int[1];
        for (int page = 1; page <= 7; page++) Assert.True(tiny.Store(Key(page: page, width: 1, height: 1), one, 1, 1, 0, 0, new(0, 0, 1, 1)));
        Assert.Equal(6, tiny.Count); Assert.False(tiny.TryRestore(Key(page: 1, width: 1, height: 1), one, 1, 1, 0, 0, new(0, 0, 1, 1)));
    }

    [Fact]
    public void InvalidAndOversizedCapturesDoNotEvictGoodFrames()
    {
        var cache = new DesktopWebFrameCache(maximumBytes: 48); var pixels = new int[48];
        Assert.True(cache.Store(Key(), pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        Assert.False(cache.Store(Key(width: 8, height: 6), pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        Assert.False(cache.Store(Key(scrollY: double.NaN), pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        Assert.False(cache.Store(Key(scrollX: double.PositiveInfinity), pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        Assert.False(cache.Store(Key(width: int.MaxValue, height: int.MaxValue), pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        Assert.False(cache.Store(Key(), pixels, 8, 6, 0, 0, new(int.MinValue, 0, int.MaxValue, 6)));
        Assert.Equal(1, cache.Count); Assert.Equal(0, cache.Evictions);
        Assert.True(cache.TryRestore(Key(), pixels, 8, 6, 0, 0, new(0, 0, 8, 6)));
        Assert.Throws<ArgumentOutOfRangeException>(() => new DesktopWebFrameCache(maximumBytes: 32L * 1024 * 1024 + 1));
        Assert.Throws<ArgumentOutOfRangeException>(() => new DesktopWebFrameCache(maximumEntries: 7));
    }
}