Files
AI-Studio/app/Tests/Tools/PluginSystem/PluginTimeoutTests.cs
T

38 lines
1.7 KiB
C#

using AIStudio.Tools.PluginSystem;
namespace AIStudio.Tests.Tools.PluginSystem;
/// <summary>
/// Checks that a plugin whose code never finishes can be stopped.
/// </summary>
/// <remarks>
/// Every plugin gets a time limit of its own while it is loaded and started, so that one plugin
/// cannot keep all the others from starting. That limit is only worth something when the Lua
/// runtime gives up on a cancelled token, even in the middle of a loop which never yields. If it
/// did not, a single plugin like that would hang the start of AI Studio for good.
/// </remarks>
[TestFixture]
public sealed class PluginTimeoutTests
{
private const string ENDLESS_PLUGIN = """
ID = "0b7e5c3a-4f1d-4e8b-9a6c-2d3f4e5a6b7c"
while true do end
""";
[Test]
public async Task ALoopWhichNeverEndsIsStopped()
{
//
// The loop runs on its own, and when the runtime ignores the token, it outlives this test.
// It therefore gets the token alone, never the source, which is disposed at the end:
//
using var timeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(200));
var token = timeout.Token;
var loading = Task.Run(() => PluginFactory.Load(null, ENDLESS_PLUGIN, cancellationToken: token));
var finishedInTime = await Task.WhenAny(loading, Task.Delay(TimeSpan.FromSeconds(10))) == loading;
Assert.That(finishedInTime, Is.True, "The Lua runtime ignored the cancelled token.");
Assert.That(async () => await loading, Throws.InstanceOf<OperationCanceledException>(), "Only a cancellation tells a time limit apart from a broken plugin.");
}
}