104 lines
3.1 KiB
C#
104 lines
3.1 KiB
C#
using AcDream.Core.Items;
|
|
|
|
namespace AcDream.Core.Tests.Items;
|
|
|
|
public sealed class ExternalContainerStateTests
|
|
{
|
|
[Fact]
|
|
public void ViewContents_onlyCommitsTheExpectedRoot()
|
|
{
|
|
var state = new ExternalContainerState();
|
|
state.RequestOpen(0x70000001u);
|
|
|
|
Assert.False(state.ApplyViewContents(0x70000002u));
|
|
Assert.Equal(0u, state.CurrentContainerId);
|
|
Assert.True(state.ApplyViewContents(0x70000001u));
|
|
Assert.Equal(0x70000001u, state.CurrentContainerId);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReplacementRetiresOldImmediatelyThenOpensNewOnViewContents()
|
|
{
|
|
var state = new ExternalContainerState();
|
|
var changes = new List<ExternalContainerTransition>();
|
|
state.Changed += changes.Add;
|
|
state.RequestOpen(1u);
|
|
state.ApplyViewContents(1u);
|
|
state.RequestOpen(2u);
|
|
|
|
Assert.Equal(0u, state.CurrentContainerId);
|
|
Assert.Equal(2u, state.RequestedContainerId);
|
|
|
|
state.ApplyViewContents(2u);
|
|
state.ApplyViewContents(2u);
|
|
|
|
Assert.Equal(3, changes.Count);
|
|
Assert.Equal(ExternalContainerTransitionKind.Opened, changes[0].Kind);
|
|
Assert.Equal(
|
|
new ExternalContainerTransition(
|
|
ExternalContainerTransitionKind.ReplacementRequested, 1u, 2u),
|
|
changes[1]);
|
|
Assert.Equal(
|
|
new ExternalContainerTransition(
|
|
ExternalContainerTransitionKind.Opened, 0u, 2u),
|
|
changes[2]);
|
|
}
|
|
|
|
[Fact]
|
|
public void CloseIgnoresStaleContainerAndClosesCurrent()
|
|
{
|
|
var state = Open(2u);
|
|
|
|
Assert.False(state.ApplyClose(1u));
|
|
Assert.Equal(2u, state.CurrentContainerId);
|
|
Assert.True(state.ApplyClose(2u));
|
|
Assert.Equal(0u, state.CurrentContainerId);
|
|
Assert.Equal(0u, state.RequestedContainerId);
|
|
}
|
|
|
|
[Fact]
|
|
public void RefusedReplacementLeavesTheRetiredRootClosed()
|
|
{
|
|
var state = Open(1u);
|
|
state.RequestOpen(2u);
|
|
|
|
Assert.True(state.ApplyUseDone(0x550u));
|
|
Assert.Equal(0u, state.CurrentContainerId);
|
|
Assert.Equal(0u, state.RequestedContainerId);
|
|
Assert.False(state.ApplyViewContents(2u));
|
|
}
|
|
|
|
[Fact]
|
|
public void Reset_RetryRepublishesAndOneObserverCannotStarveAnother()
|
|
{
|
|
var state = Open(1u);
|
|
bool fail = true;
|
|
int delivered = 0;
|
|
state.Changed += _ =>
|
|
{
|
|
if (fail)
|
|
{
|
|
fail = false;
|
|
throw new InvalidOperationException("transient");
|
|
}
|
|
};
|
|
state.Changed += transition =>
|
|
{
|
|
Assert.Equal(ExternalContainerTransitionKind.Reset, transition.Kind);
|
|
delivered++;
|
|
};
|
|
|
|
Assert.Throws<AggregateException>(() => state.Reset());
|
|
Assert.Equal(1, delivered);
|
|
Assert.False(state.Reset());
|
|
Assert.Equal(2, delivered);
|
|
}
|
|
|
|
private static ExternalContainerState Open(uint id)
|
|
{
|
|
var state = new ExternalContainerState();
|
|
state.RequestOpen(id);
|
|
state.ApplyViewContents(id);
|
|
return state;
|
|
}
|
|
}
|