acdream/tests/AcDream.Core.Tests/Selection/SelectionStateTests.cs
Erik 8a5d77f7f4 feat(net): port retail physics spawn and event timestamps
Parse the complete PhysicsDesc plus F754/F755 packets, correct every PhysicsState bit, and gate all nine retail update channels with generation-safe immutable snapshots. Preserve ForcePosition, teleport, placement, velocity, parent, pickup, delete, and same-generation CreateObject ordering from the named client.

Separate accepted logical lifecycle notifications from retained UI qualities, make GUID replacement and session reset clear every projection exactly once, and add packet, wraparound, malformed-input, parent FIFO, canonical-position, reconnect, and GUID-reuse conformance coverage.

Co-Authored-By: Codex <noreply@openai.com>
2026-07-14 00:22:17 +02:00

119 lines
4.1 KiB
C#

using AcDream.Core.Selection;
using AcDream.Plugin.Abstractions;
namespace AcDream.Core.Tests.Selection;
public sealed class SelectionStateTests
{
[Fact]
public void ResetClearsCurrentAndSelectionHistoryForNextSession()
{
var state = new SelectionState();
state.Select(0x50000001u, SelectionChangeSource.World);
state.Select(0x50000002u, SelectionChangeSource.World);
SelectionTransition transition = default;
state.Changed += value => transition = value;
Assert.True(state.Reset());
Assert.Null(state.SelectedObjectId);
Assert.Null(state.PreviousObjectId);
Assert.Null(state.PreviousValidObjectId);
Assert.Equal(0x50000002u, transition.PreviousObjectId);
Assert.Equal(SelectionChangeReason.SessionReset, transition.Reason);
Assert.False(state.SelectPrevious());
}
[Fact]
public void Select_CommitsOneTransitionAndTracksPreviousLikeRetail()
{
var state = new SelectionState();
var transitions = new List<SelectionTransition>();
state.Changed += transitions.Add;
Assert.True(state.Select(0x50000001u, SelectionChangeSource.World));
Assert.True(state.Select(0x50000002u, SelectionChangeSource.Radar));
Assert.Equal(0x50000002u, state.SelectedObjectId);
Assert.Equal(0x50000001u, state.PreviousObjectId);
Assert.Equal(0x50000001u, state.PreviousValidObjectId);
Assert.Equal(2, transitions.Count);
Assert.Equal(SelectionChangeSource.Radar, transitions[1].Source);
Assert.Equal(SelectionChangeReason.Selected, transitions[1].Reason);
}
[Fact]
public void Select_SameObject_IsDeduplicated()
{
var state = new SelectionState();
int changed = 0;
state.Changed += _ => changed++;
Assert.True(state.Select(0x50000001u, SelectionChangeSource.World));
Assert.False(state.Select(0x50000001u, SelectionChangeSource.Inventory));
Assert.Equal(1, changed);
Assert.Null(state.PreviousObjectId);
}
[Fact]
public void SelectPrevious_SwapsCurrentAndPrevious()
{
var state = new SelectionState();
state.Select(0x50000001u, SelectionChangeSource.World);
state.Select(0x50000002u, SelectionChangeSource.World);
Assert.True(state.SelectPrevious());
Assert.Equal(0x50000001u, state.SelectedObjectId);
Assert.Equal(0x50000002u, state.PreviousObjectId);
}
[Fact]
public void ClearRemoved_PreservesRemovedObjectAsPreviousValid()
{
var state = new SelectionState();
SelectionTransition transition = default;
state.Changed += value => transition = value;
state.Select(0x50000001u, SelectionChangeSource.World);
Assert.True(state.Clear(
SelectionChangeSource.System,
SelectionChangeReason.SelectedObjectRemoved));
Assert.Null(state.SelectedObjectId);
Assert.Equal(0x50000001u, state.PreviousObjectId);
Assert.Equal(0x50000001u, state.PreviousValidObjectId);
Assert.Equal(SelectionChangeReason.SelectedObjectRemoved, transition.Reason);
}
[Fact]
public void PluginService_UsesSameStateAndEventStream()
{
var state = new SelectionState();
ISelectionService plugin = state;
SelectionChangedEvent change = default;
plugin.Changed += value => change = value;
Assert.True(plugin.Select(0x50000001u));
Assert.Equal(0x50000001u, state.SelectedObjectId);
Assert.Equal(0x50000001u, plugin.SelectedObjectId);
Assert.Null(change.PreviousObjectId);
Assert.Equal(0x50000001u, change.SelectedObjectId);
}
[Fact]
public void PluginListenerFailure_DoesNotEscapeOrBlockOtherPlugins()
{
var state = new SelectionState();
ISelectionService plugin = state;
int delivered = 0;
plugin.Changed += _ => throw new InvalidOperationException("plugin failure");
plugin.Changed += _ => delivered++;
Assert.Null(Record.Exception(() => plugin.Select(0x50000001u)));
Assert.Equal(1, delivered);
Assert.Equal(0x50000001u, state.SelectedObjectId);
}
}