106 lines
3.4 KiB
C#
106 lines
3.4 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using SharpEmu.HLE.GpuMemory;
|
|
using Xunit;
|
|
|
|
namespace SharpEmu.Libs.Tests.Memory.GpuMemory;
|
|
|
|
public sealed class PageMaskTests
|
|
{
|
|
[Fact]
|
|
public void RangeQueryPreservesBitsAndUsesExclusiveEnd()
|
|
{
|
|
var mask = new PageMask();
|
|
Assert.False(mask.AnyInRange(0, TrackerLayout.PagesPerBlock));
|
|
for (var pageIndex = 0; pageIndex < TrackerLayout.PagesPerBlock; pageIndex++)
|
|
{
|
|
mask.Set(pageIndex);
|
|
Assert.True(mask.AnyInRange(pageIndex, pageIndex + 1));
|
|
Assert.True(mask.AnyInRange(0, TrackerLayout.PagesPerBlock));
|
|
Assert.False(mask.AnyInRange(0, pageIndex));
|
|
Assert.False(mask.AnyInRange(pageIndex + 1, TrackerLayout.PagesPerBlock));
|
|
Assert.True(mask.Get(pageIndex));
|
|
mask.Unset(pageIndex);
|
|
Assert.True(mask.None);
|
|
}
|
|
mask.Fill();
|
|
for (var pageIndex = 0; pageIndex < TrackerLayout.PagesPerBlock; pageIndex++)
|
|
Assert.True(mask.AnyInRange(pageIndex, pageIndex + 1));
|
|
}
|
|
|
|
[Fact]
|
|
public void RangeQueryMatchesCopiedMasksAcrossAllPageBoundaries()
|
|
{
|
|
var mask = new PageMask();
|
|
foreach (var page in new[] { 0, 63, 64, 127, 512, 700, 1023 }) mask.Set(page);
|
|
for (var start = 0; start <= TrackerLayout.PagesPerBlock; start++)
|
|
{
|
|
for (var end = start; end <= TrackerLayout.PagesPerBlock; end++)
|
|
Assert.Equal(new PageMask(mask, start, end).Any, mask.AnyInRange(start, end));
|
|
}
|
|
Assert.False(mask.AnyInRange(0, TrackerLayout.PagesPerBlock + 1));
|
|
Assert.False(mask.AnyInRange(-1, 1));
|
|
Assert.False(mask.AnyInRange(10, 9));
|
|
}
|
|
|
|
[Fact]
|
|
public void SetAndGet_TrackSingleBits()
|
|
{
|
|
var mask = new PageMask();
|
|
mask.Set(0);
|
|
mask.Set(63);
|
|
mask.Set(64);
|
|
mask.Set(1023);
|
|
|
|
Assert.True(mask.Get(0));
|
|
Assert.True(mask.Get(63));
|
|
Assert.True(mask.Get(64));
|
|
Assert.True(mask.Get(1023));
|
|
Assert.False(mask.Get(1));
|
|
Assert.False(mask.Get(65));
|
|
}
|
|
|
|
[Fact]
|
|
public void SetRange_CrossesWordBoundaries()
|
|
{
|
|
var mask = new PageMask();
|
|
mask.SetRange(60, 200);
|
|
|
|
Assert.False(mask.Get(59));
|
|
Assert.True(mask.Get(60));
|
|
Assert.True(mask.Get(127));
|
|
Assert.True(mask.Get(128));
|
|
Assert.True(mask.Get(199));
|
|
Assert.False(mask.Get(200));
|
|
Assert.Equal((60, 200), mask.FindFirstSetRange());
|
|
Assert.Equal((60, 200), mask.FindLastSetRange());
|
|
}
|
|
|
|
[Fact]
|
|
public void SetRange_IgnoresEmptyOrOutOfBoundsInput()
|
|
{
|
|
var mask = new PageMask();
|
|
mask.SetRange(5, 5);
|
|
mask.SetRange(10, 1025);
|
|
|
|
Assert.Equal((1024, 1024), mask.FindFirstSetRange());
|
|
Assert.Equal((0, 0), mask.FindLastSetRange());
|
|
}
|
|
|
|
[Fact]
|
|
public void FirstAndLastRange_FindSeparateRuns()
|
|
{
|
|
var mask = new PageMask();
|
|
mask.SetRange(2, 4);
|
|
mask.SetRange(700, 1024);
|
|
|
|
Assert.Equal((2, 4), mask.FindFirstSetRange());
|
|
Assert.Equal((700, 1024), mask.FindFirstSetRangeFrom(4));
|
|
Assert.Equal((700, 1024), mask.FindLastSetRange());
|
|
Assert.Equal((2, 4), mask.FindLastSetRangeBefore(700));
|
|
Assert.Equal((1024, 1024), mask.FindFirstSetRangeFrom(1024));
|
|
Assert.Equal((0, 0), mask.FindLastSetRangeBefore(2));
|
|
}
|
|
}
|