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

XFESystem

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

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Runtime.CompilerServices;
using XFESystem.Collections;

namespace XFESystem.Browser.Tests;

[Collection("Browser lifetime ownership")]
public sealed class EngineWeakCacheTests
{
    [Fact]
    public void ShapeFactoryMatchesOriginalConditionalWeakTableReentrancyNullAndFailureSemantics()
    {
        var original=new ConditionalWeakTable<object,object>();var scope=new WeakCollectionScope();
        var owned=new OwnedWeakTable<object,object>(scope);var key=new object();var existing=new object();var discarded=new object();
        Assert.Same(existing,original.GetValue(key,k=>{original.Add(k,existing);return discarded;}));
        Assert.Same(existing,owned.GetValue(key,k=>{owned.Add(k,existing);return discarded;}));
        Assert.Throws<ArgumentNullException>(()=>original.GetValue(key,null!));
        Assert.Throws<ArgumentNullException>(()=>owned.GetValue(key,null!));
        Assert.Equal(Assert.Throws<ArgumentNullException>(()=>original.GetValue(null!,null!)).ParamName,
            Assert.Throws<ArgumentNullException>(()=>owned.GetValue(null!,null!)).ParamName);
        Assert.Throws<ArgumentNullException>(()=>original.GetValue(null!,_=>new object()));
        Assert.Throws<ArgumentNullException>(()=>owned.GetValue(null!,_=>new object()));
        var nullKey=new object();Assert.Null(original.GetValue(nullKey,_=>null!));Assert.Null(owned.GetValue(nullKey,_=>null!));
        Assert.True(original.TryGetValue(nullKey,out var nullOriginal));Assert.Null(nullOriginal);
        Assert.True(owned.TryGetValue(nullKey,out var nullOwned));Assert.Null(nullOwned);
        int calls=0;Assert.Null(owned.GetValue(nullKey,_=>{calls++;return new();}));Assert.Equal(0,calls);
        var failedKey=new object();var known=new InvalidOperationException("factory failed");
        Assert.Same(known,Assert.Throws<InvalidOperationException>(()=>owned.GetValue(failedKey,_=>throw known)));
        Assert.False(owned.TryGetValue(failedKey,out _));
        Assert.Same(existing,owned.GetOrCreateValue(failedKey,()=>{owned.Add(failedKey,existing);return discarded;}));
        scope.Release();var released=scope.Lifetime;
        Assert.Throws<ObjectDisposedException>(()=>owned.GetValue(key,_=>new()));
        Assert.Throws<ObjectDisposedException>(()=>owned.GetOrCreateValue(key,()=>new()));
        Assert.Equal(released,scope.Lifetime);Assert.Equal(released.Created,released.Disposed);
    }

    [Fact]
    public void ActualShapeAndPrivateClassIntrinsicsReleaseEveryOwnedCacheWithoutGarbageCollection()
    {
        for(int iteration=0;iteration<4;iteration++)
        {
            var result=BrowserWeakCollectionsRegression.Run();
            Assert.True(result.Passed,System.Text.Json.JsonSerializer.Serialize(result));Assert.True(result.EngineCachesExercised);
            Assert.True(result.ConstructorExceptionPreserved);Assert.True(result.ConstructorFailureReleased);
            Assert.Equal(result.ConstructorAfterRelease.Created,result.ConstructorAfterRelease.Disposed);
            Assert.Equal(result.ConstructorAfterRelease.TableHandlesCreated,result.ConstructorAfterRelease.TableHandlesDisposed);
            Assert.InRange(result.BeforeRelease.Created,130,long.MaxValue);
        }
    }

    [Fact]
    public void OriginalMonacoShapeCacheIsIncludedInExplicitPageRelease()
    {
        var browser=new BrowserService();browser.ResizeViewport(796,404);
        browser.NavigateEditor("using System;\nConsole.WriteLine(\"XFESystem\");\n","Hello.cs");
        for(int step=0;step<4;step++)browser.AdvanceTime(step*100);
        Assert.Contains("XFESystem",browser.ReadEditorText(),StringComparison.Ordinal);
        var runtime=(JavaScriptRuntime)typeof(BrowserService).GetField("runtime",System.Reflection.BindingFlags.NonPublic|System.Reflection.BindingFlags.Instance)!.GetValue(browser)!;
        var scope=((IWeakCollectionOwner)(object)runtime.Engine).WeakCollections;
        var table=typeof(Jint.Engine).GetField("_emptyShapes",System.Reflection.BindingFlags.NonPublic|System.Reflection.BindingFlags.Instance)!.GetValue(runtime.Engine);
        Assert.NotNull(table);Assert.Equal(typeof(OwnedWeakTable<,>),table.GetType().GetGenericTypeDefinition());
        var before=scope.Lifetime;Assert.InRange(before.Created,190,long.MaxValue);
        browser.Release();var after=scope.Lifetime;
        Assert.Equal(0,after.Tables);Assert.Equal(0,after.Entries);Assert.Equal(after.Created,after.Disposed);
        Assert.Equal(after.TableHandlesCreated,after.TableHandlesDisposed);
        GC.KeepAlive(runtime);GC.KeepAlive(table);
    }
}