diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs b/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs index 9fbb4438c..b6f08edf6 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/SelfTestWindow.cs @@ -22,40 +22,40 @@ internal class SelfTestWindow : Window private static readonly ModuleLog Log = new("AGING"); private readonly List steps = - new() - { - new LoginEventSelfTestStep(), - new WaitFramesSelfTestStep(1000), - new EnterTerritorySelfTestStep(148, "Central Shroud"), - new ItemPayloadSelfTestStep(), - new ContextMenuSelfTestStep(), - new NamePlateSelfTestStep(), - new ActorTableSelfTestStep(), - new FateTableSelfTestStep(), - new AetheryteListSelfTestStep(), - new ConditionSelfTestStep(), - new ToastSelfTestStep(), - new TargetSelfTestStep(), - new KeyStateSelfTestStep(), - new GamepadStateSelfTestStep(), - new ChatSelfTestStep(), - new HoverSelfTestStep(), - new LuminaSelfTestStep(true), - new LuminaSelfTestStep(true), - new LuminaSelfTestStep(true), - new LuminaSelfTestStep(true), - new LuminaSelfTestStep(false), - new AddonLifecycleSelfTestStep(), - new PartyFinderSelfTestStep(), - new HandledExceptionSelfTestStep(), - new DutyStateSelfTestStep(), - new GameConfigSelfTestStep(), - new MarketBoardSelfTestStep(), - new SheetRedirectResolverSelfTestStep(), - new NounProcessorSelfTestStep(), - new SeStringEvaluatorSelfTestStep(), - new LogoutEventSelfTestStep(), - }; + [ + new LoginEventSelfTestStep(), + new WaitFramesSelfTestStep(1000), + new FrameworkTaskSchedulerSelfTestStep(), + new EnterTerritorySelfTestStep(148, "Central Shroud"), + new ItemPayloadSelfTestStep(), + new ContextMenuSelfTestStep(), + new NamePlateSelfTestStep(), + new ActorTableSelfTestStep(), + new FateTableSelfTestStep(), + new AetheryteListSelfTestStep(), + new ConditionSelfTestStep(), + new ToastSelfTestStep(), + new TargetSelfTestStep(), + new KeyStateSelfTestStep(), + new GamepadStateSelfTestStep(), + new ChatSelfTestStep(), + new HoverSelfTestStep(), + new LuminaSelfTestStep(true), + new LuminaSelfTestStep(true), + new LuminaSelfTestStep(true), + new LuminaSelfTestStep(true), + new LuminaSelfTestStep(false), + new AddonLifecycleSelfTestStep(), + new PartyFinderSelfTestStep(), + new HandledExceptionSelfTestStep(), + new DutyStateSelfTestStep(), + new GameConfigSelfTestStep(), + new MarketBoardSelfTestStep(), + new SheetRedirectResolverSelfTestStep(), + new NounProcessorSelfTestStep(), + new SeStringEvaluatorSelfTestStep(), + new LogoutEventSelfTestStep() + ]; private readonly Dictionary testIndexToResult = new(); diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/Steps/FrameworkTaskSchedulerSelfTestStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/FrameworkTaskSchedulerSelfTestStep.cs new file mode 100644 index 000000000..2376de75b --- /dev/null +++ b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/FrameworkTaskSchedulerSelfTestStep.cs @@ -0,0 +1,64 @@ +using System.Threading.Tasks; + +using Dalamud.Game; +using Dalamud.Utility; + +namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps; + +/// +/// Test setup for Framework task scheduling. +/// +internal class FrameworkTaskSchedulerSelfTestStep : ISelfTestStep +{ + private bool passed = false; + private Task? task; + + /// + public string Name => "Test Framework Task Scheduler"; + + /// + public SelfTestStepResult RunStep() + { + var framework = Service.Get(); + + this.task ??= Task.Run(async () => + { + ThreadSafety.AssertNotMainThread(); + + await framework.RunOnTick(async () => + { + ThreadSafety.AssertMainThread(); + await Task.Delay(100); + + // TODO: We used to be scheduled back to the framework thread here. Is that by design? + //ThreadSafety.AssertMainThread(); + ThreadSafety.AssertNotMainThread(); + }).ConfigureAwait(false); + + ThreadSafety.AssertNotMainThread(); + + await framework.RunOnTick(() => + { + ThreadSafety.AssertMainThread(); + }); + + ThreadSafety.AssertMainThread(); + + this.passed = true; + }); + + if (this.task is { IsFaulted: true } or { IsCanceled: true }) + { + return SelfTestStepResult.Fail; + } + + return this.passed ? SelfTestStepResult.Pass : SelfTestStepResult.Waiting; + } + + /// + public void CleanUp() + { + this.passed = false; + this.task = null; + } +}