Files
AtomUI/tests/AtomUI.Core.Tests/Theme/ControlCompilationCacheTests.cs

112 lines
4.3 KiB
C#

using System.Reflection;
using AtomUI.Theme;
using AtomUI.Theme.Compilation;
using AtomUI.Theme.Configuration;
using AtomUI.Theme.Schema;
using AtomUI.Theme.DesignTokens;
using Shouldly;
using Xunit;
namespace AtomUI.Core.Tests.Theme;
public class ControlCompilationCacheTests
{
[Fact]
public void Control_Keys_Share_The_Precomputed_Global_Key()
{
var button = CreateControl("Button");
var input = CreateControl("Input");
var registry = TypedThemeSnapshotCacheTests.CreateRegistry([button, input]);
registry.TryGetControl(button.Identity, out button).ShouldBeTrue();
registry.TryGetControl(input.Identity, out input).ShouldBeTrue();
var compileInput = TypedThemeSnapshotCacheTests.CreateInput(registry);
var globalKey = GlobalCompilationCacheKey.Create(compileInput);
var buttonKey = ControlCompilationCacheKey.Create(
globalKey,
button,
null,
ThemeAppearance.Light);
var inputKey = ControlCompilationCacheKey.Create(
globalKey,
input,
null,
ThemeAppearance.Light);
var field = typeof(ControlCompilationCacheKey).GetField(
"_global",
BindingFlags.Instance | BindingFlags.NonPublic)!;
field.GetValue(buttonKey).ShouldBeSameAs(globalKey);
field.GetValue(inputKey).ShouldBeSameAs(globalKey);
}
[Fact]
public async Task Different_Snapshots_Reuse_Only_Equivalent_Control_Compilations()
{
var button = CreateControl("Button");
var input = CreateControl("Input");
var registry = TypedThemeSnapshotCacheTests.CreateRegistry([button, input]);
registry.TryGetControl(button.Identity, out button).ShouldBeTrue();
registry.TryGetControl(input.Identity, out input).ShouldBeTrue();
var buttonConfig = new NormalizedControlThemeConfig(
button.Identity,
ControlAlgorithmMode.Disabled,
Array.Empty<ThemeAlgorithmDescriptor>(),
Array.Empty<NormalizedTokenValue>(),
[CreateControlToken(button, "48")]);
var cache = new ThemeSnapshotCache();
var compiler = new ThemeCompiler();
var baseline = await TypedThemeSnapshotCacheTests.CompileAsync(cache,
TypedThemeSnapshotCacheTests.CreateInput(registry),
compiler);
var changed = await TypedThemeSnapshotCacheTests.CompileAsync(cache,
TypedThemeSnapshotCacheTests.CreateInput(registry, controls: [buttonConfig]),
compiler);
baseline.Success.ShouldBeTrue();
changed.Success.ShouldBeTrue();
changed.Snapshot!.Controls[button.Slot]
.ShouldNotBeSameAs(baseline.Snapshot!.Controls[button.Slot]);
changed.Snapshot.Controls[input.Slot]
.ShouldBeSameAs(baseline.Snapshot.Controls[input.Slot]);
cache.ControlCount.ShouldBe(3);
cache.ControlRetainedBytes.ShouldBeGreaterThan(0);
}
private static NormalizedTokenValue CreateControlToken(
ControlTokenDescriptor control,
string value)
{
var descriptor = control.OwnTokens.ShouldHaveSingleItem();
var parsed = descriptor.Parse(value);
return new NormalizedTokenValue(descriptor, parsed, descriptor.Format(parsed));
}
private static ControlTokenDescriptor CreateControl(string id)
{
var token = new TokenDescriptor(
"Height",
0,
TokenStage.Control,
typeof(double),
$"{id}.Height",
static value => ThemeTokenValueParser.Parse<double>(value),
static value => ThemeTokenValueFormatter.Format((double)value!),
static builder => ((CacheControlToken)builder).Height,
static (builder, value) => ((CacheControlToken)builder).Height = (double)value!,
static builder => ((CacheControlToken)builder).Height);
return new ControlTokenDescriptor(
ThemeTestControlTypes.For("AtomUI", id),
new ControlTokenIdentity("AtomUI", id),
[token],
static () => new CacheControlToken(),
static (builder, _) => ((CacheControlToken)builder).Height = 40);
}
private sealed class CacheControlToken : AbstractControlDesignToken
{
public double Height { get; set; }
}
}