using AcDream.App.Input; using AcDream.Core.Physics; namespace AcDream.App.Tests.Input; public sealed class LocalPlayerControllerSlotTests { [Fact] public void MotionPreparation_RoutesCompletionWithoutPublishingController() { var slot = new LocalPlayerControllerSlot(); ILocalPlayerMotionSource source = slot; var controller = new PlayerMovementController(new PhysicsEngine()); controller.Motion.AddToQueue(0, MotionCommand.Ready, 0); using (slot.BeginMotionPreparation(controller)) { Assert.Null(slot.Controller); MotionInterpreter? owner = source.Motion; Assert.Same(controller.Motion, owner); owner!.MotionDone(MotionCommand.Ready, success: true); Assert.False(controller.Motion.MotionsPending()); } Assert.Null(source.Motion); } [Fact] public void MotionPreparation_HandsOffToCommittedControllerOnDispose() { var slot = new LocalPlayerControllerSlot(); ILocalPlayerMotionSource source = slot; var controller = new PlayerMovementController(new PhysicsEngine()); using (slot.BeginMotionPreparation(controller)) { slot.Controller = controller; Assert.Same(controller.Motion, source.Motion); } Assert.Same(controller.Motion, source.Motion); } [Fact] public void MotionPreparation_RejectsConcurrentCandidate() { var slot = new LocalPlayerControllerSlot(); var first = new PlayerMovementController(new PhysicsEngine()); var second = new PlayerMovementController(new PhysicsEngine()); using IDisposable preparation = slot.BeginMotionPreparation(first); Assert.Throws( () => slot.BeginMotionPreparation(second)); } }