fix(plugins): close LA5 ownership races
This commit is contained in:
parent
fbe9c8a288
commit
f820eb258d
14 changed files with 467 additions and 107 deletions
|
|
@ -15,6 +15,8 @@ public sealed class GraphicalPluginSessionTests
|
|||
{
|
||||
private const string FixtureId = "acdream.test.host-fixture";
|
||||
private const string ThrowingId = "acdream.test.throwing-fixture";
|
||||
private const string InitializeThrowingId =
|
||||
"acdream.test.initialize-throwing-fixture";
|
||||
|
||||
[Fact]
|
||||
public void ConfiguredSetLoadsOnlyAllowedPluginAndReportsBothOutcomes()
|
||||
|
|
@ -114,12 +116,13 @@ public sealed class GraphicalPluginSessionTests
|
|||
string.Empty);
|
||||
string statusPath = Path.Combine(temporary.Path, "status.jsonl");
|
||||
var events = new WorldEvents();
|
||||
var selection = new SelectionState();
|
||||
var ui = new BufferedUiRegistry();
|
||||
var host = new AppPluginHost(
|
||||
new CapturingLogger(),
|
||||
new WorldGameState(),
|
||||
events,
|
||||
new SelectionState(),
|
||||
selection,
|
||||
ui);
|
||||
|
||||
using GraphicalPluginSession plugins = GraphicalPluginSession.Create(
|
||||
|
|
@ -138,6 +141,65 @@ public sealed class GraphicalPluginSessionTests
|
|||
2u,
|
||||
default,
|
||||
System.Numerics.Quaternion.Identity));
|
||||
Assert.True(((ISelectionService)selection).Select(7u));
|
||||
Assert.False(File.Exists(
|
||||
Path.Combine(pluginDirectory, "unexpected-callback")));
|
||||
Assert.Equal(
|
||||
["started", "pluginFailed"],
|
||||
EventNames(ReadStatuses(statusPath)));
|
||||
|
||||
WeakReference context = Assert.Single(
|
||||
plugins.CaptureLoadContextWeakReferences());
|
||||
plugins.Dispose();
|
||||
Collect(context);
|
||||
Assert.False(context.IsAlive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InitializeFailureRollsBackEveryRegistrationBeforeUnload()
|
||||
{
|
||||
using var temporary = new TemporaryDirectory();
|
||||
ApplicationPathSet paths = Paths(temporary.Path);
|
||||
string pluginDirectory = InstallFixture(
|
||||
paths.PluginsDirectory,
|
||||
InitializeThrowingId,
|
||||
"initialize-throwing-fixture");
|
||||
File.WriteAllText(
|
||||
Path.Combine(pluginDirectory, "throw-during-initialize"),
|
||||
string.Empty);
|
||||
string statusPath = Path.Combine(temporary.Path, "status.jsonl");
|
||||
var events = new WorldEvents();
|
||||
var selection = new SelectionState();
|
||||
var ui = new BufferedUiRegistry();
|
||||
var host = new AppPluginHost(
|
||||
new CapturingLogger(),
|
||||
new WorldGameState(),
|
||||
events,
|
||||
selection,
|
||||
ui);
|
||||
|
||||
using GraphicalPluginSession plugins = GraphicalPluginSession.Create(
|
||||
paths,
|
||||
[InitializeThrowingId],
|
||||
"gui-session",
|
||||
host,
|
||||
new SessionStatusWriter(statusPath));
|
||||
plugins.Start();
|
||||
|
||||
Assert.Equal(0, plugins.LoadedCount);
|
||||
Assert.Empty(ui.Drain());
|
||||
Assert.Equal(0, ui.RegistrationCount);
|
||||
Assert.Equal(
|
||||
"ui=True;events=True;selection=True",
|
||||
File.ReadAllText(Path.Combine(
|
||||
pluginDirectory,
|
||||
"unload-observation")));
|
||||
events.FireEntitySpawned(new WorldEntitySnapshot(
|
||||
1u,
|
||||
2u,
|
||||
default,
|
||||
System.Numerics.Quaternion.Identity));
|
||||
Assert.True(((ISelectionService)selection).Select(9u));
|
||||
Assert.False(File.Exists(
|
||||
Path.Combine(pluginDirectory, "unexpected-callback")));
|
||||
Assert.Equal(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue