#nullable enable
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using NUnit.Framework;
using ShrinkContext;
namespace ShrinkContext.Tests
{
///
/// 余效应操作与介导访问(论文 3.2 / 算法 2、6):
/// set 是可逆效应;代理介导的 get 拒绝未声明/未激活访问;隔离域派生独立绑定。
///
public class CoeffectAccessTests
{
private ShrinkContextRuntime _runtime = null!;
private ShrinkCtx _ctx = null!;
[SetUp]
public void SetUp()
{
_runtime = new ShrinkContextRuntime();
_ctx = _runtime.RootContext;
}
[Test]
public void Set_IsReversibleEffect_EarlyWithdrawAndContextDispose()
{
var handle = _ctx.Set("cfg", 42);
Assert.IsTrue(_runtime.TryGetRaw(_ctx, "cfg", out var v1));
Assert.AreEqual(42, v1);
// 早期手动撤回
TestAwait.Run(handle.DisposeAsync());
Assert.IsFalse(_runtime.TryGetRaw(_ctx, "cfg", out _));
// 再次安装后随上下文卸载自动撤回
_ctx.Set("cfg", 43);
Assert.IsTrue(_runtime.TryGetRaw(_ctx, "cfg", out var v2));
Assert.AreEqual(43, v2);
TestAwait.Run(_ctx.DisposeAsync());
Assert.IsFalse(_runtime.TryGetRaw(_ctx, "cfg", out _), "set 的逆操作必须移除绑定");
}
[Test]
public void MediatedGet_RejectsUndeclaredKey_InApply()
{
var provider = new ProviderComponent("provider", "real", "v");
var fiber = _runtime.Use(provider);
Assert.AreEqual(ShrinkFiberState.Active, fiber.State);
var greedy = new GreedyConsumerComponent("greedy", "real", "undeclared");
var greedyFiber = _runtime.Use(greedy);
Assert.AreEqual(ShrinkFiberState.Inactive, greedyFiber.State);
Assert.IsInstanceOf(greedyFiber.LastError,
"未声明的依赖访问在访问点被拒绝,并使装载失败(算法 6 UNDECLARED_ACCESS)");
}
[Test]
public void MediatedGet_ThrowsWhenOwnKeyNotActivated()
{
var consumer = new ConsumerComponent("consumer", "missing");
var fiber = _runtime.Use(consumer);
Assert.AreEqual(ShrinkFiberState.Inactive, fiber.State,
"依赖缺失时组件保持非活动,而不是抛错(响应式余效应)");
Assert.Throws(() => fiber.Ctx.Get