using System.Reflection;
using AcDream.Headless.Policies;
using AcDream.Runtime;
namespace AcDream.Headless.Tests;
public sealed class HeadlessBotPolicyTests
{
///
/// Campaign LA slice LA2: idle is a deliberately passive,
/// non-terminal policy. It must neither inspect Runtime state nor reach
/// any command surface, and no event can make it complete on its own.
/// The process scheduler therefore keeps the play session alive until
/// external cancellation/stop drives the host's ordinary teardown path.
///
[Fact]
public void IdlePolicyIsPassiveAndNeverCompletesAutonomously()
{
var policy = new IdleHeadlessBotPolicy();
IGameRuntimeView view = CreateNoTouchProxy(
out InvocationCountingProxy viewCalls);
IGameRuntimeCommands commands =
CreateNoTouchProxy(
out InvocationCountingProxy commandCalls);
for (int index = 0; index < 3; index++)
policy.Tick(view, commands);
RuntimeLifecycleDelta lifecycle = default;
RuntimeCommandDelta command = default;
RuntimeEntityDelta entity = default;
RuntimeInventoryDelta inventory = default;
RuntimeChatDelta chat = default;
RuntimeMovementDelta movement = default;
RuntimePortalDelta portal = default;
RuntimeCombatDelta combat = default;
policy.OnLifecycle(in lifecycle);
policy.OnCommand(in command);
policy.OnEntity(in entity);
policy.OnInventory(in inventory);
policy.OnChat(in chat);
policy.OnMovement(in movement);
policy.OnPortal(in portal);
policy.OnCombat(in combat);
Assert.False(policy.IsComplete);
Assert.Equal(0, viewCalls.InvocationCount);
Assert.Equal(0, commandCalls.InvocationCount);
policy.Dispose();
policy.Dispose();
Assert.False(policy.IsComplete);
}
private static T CreateNoTouchProxy(
out InvocationCountingProxy proxy)
where T : class
{
T value = DispatchProxy.Create();
proxy = (InvocationCountingProxy)(object)value;
return value;
}
public class InvocationCountingProxy : DispatchProxy
{
public int InvocationCount { get; private set; }
protected override object? Invoke(
MethodInfo? targetMethod,
object?[]? args)
{
InvocationCount++;
throw new InvalidOperationException(
$"Idle policy unexpectedly invoked {targetMethod?.Name}.");
}
}
}