35efdd4628
Preflight Block E (`dotnet csharpier check`) flagged two reflows in the v1.5.2 code: the ForgeBronzeDim Vector4 constant needed multi-line form, and a handful of switch arms / long Plugin.Config chains in WizardStateSmokeStep needed line-breaks at csharpier's print-width. Pure formatting — zero functional change. Block D build stays clean, Block E now passes.
136 lines
6.2 KiB
C#
136 lines
6.2 KiB
C#
using System.Collections.Generic;
|
|
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Plugin.SelfTest;
|
|
using HellionChat.Code;
|
|
using HellionChat.Ui;
|
|
|
|
namespace HellionChat.SelfTests;
|
|
|
|
// Drives the FirstRunWizard state machine through every step and
|
|
// commits a no-op pending state (Variant 1), then re-runs picking
|
|
// Roleplay on Step 2 and skipping Step 3 (Variant 2). Verifies
|
|
// that the staged-commit path does not throw under any combination
|
|
// of Pending* values and that CommitPending leaves Config in a
|
|
// readable shape. Variant 2's Roleplay commit would normally
|
|
// mutate the six PrivacyFilter / Retention fields ApplyRoleplay
|
|
// touches, so the step snapshots them before Variant 2 runs and
|
|
// CleanUp() restores them — the self-test stays idempotent across
|
|
// repeated /xlperf runs and does not overwrite an active privacy
|
|
// profile.
|
|
internal sealed class WizardStateSmokeStep : ISelfTestStep
|
|
{
|
|
private readonly Plugin plugin;
|
|
|
|
// Snapshot slots for the six Configuration fields ApplyRoleplay
|
|
// writes in Variant 2. Populated right before Variant 2 mutates
|
|
// Config, consumed by CleanUp(). Reference-typed snapshots
|
|
// (HashSet, Dictionary) capture the existing slot by reference,
|
|
// which is safe because ApplyRoleplay reassigns the slot with
|
|
// a fresh instance instead of mutating in place.
|
|
private bool? snapshotPrivacyFilterEnabled;
|
|
private HashSet<ChatType>? snapshotPrivacyPersistChannels;
|
|
private bool? snapshotPrivacyPersistUnknownChannels;
|
|
private bool? snapshotRetentionEnabled;
|
|
private int? snapshotRetentionDefaultDays;
|
|
private Dictionary<ChatType, int>? snapshotRetentionPerChannelDays;
|
|
|
|
public WizardStateSmokeStep(Plugin plugin)
|
|
{
|
|
this.plugin = plugin;
|
|
}
|
|
|
|
public string Name => "Hellion Chat - FirstRunWizard state smoke";
|
|
|
|
public SelfTestStepResult RunStep()
|
|
{
|
|
var wizard = this.plugin.FirstRunWizard;
|
|
if (wizard is null)
|
|
{
|
|
ImGui.Text("Plugin.FirstRunWizard is null");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Variant 1: no-op CommitPending. Walks the state machine and
|
|
// verifies the empty-pending write-back path does not throw.
|
|
wizard.TestOnly_AdvanceTo(1);
|
|
wizard.TestOnly_AdvanceTo(2);
|
|
wizard.TestOnly_AdvanceTo(3);
|
|
wizard.TestOnly_AdvanceTo(4);
|
|
wizard.CommitPending();
|
|
|
|
// Variant 2: skip Step 3 explicitly. Picks Roleplay on Step 2,
|
|
// jumps straight to Step 4 (no Step-3 entry → no seed for
|
|
// LoadPreviousSession / FilterIncludePreviousSessions), commits,
|
|
// and asserts the two coupled history toggles remained on their
|
|
// pre-test value. Pins the null-semantics from Spec Z.176 so a
|
|
// regression in CommitPending that started writing seeded
|
|
// recommendations unconditionally would surface here.
|
|
// CommitPending → ApplyRoleplay overwrites six privacy /
|
|
// retention fields, so snapshot them first and let CleanUp
|
|
// restore them after the assert. Keeps /xlperf idempotent.
|
|
this.snapshotPrivacyFilterEnabled = Plugin.Config.PrivacyFilterEnabled;
|
|
this.snapshotPrivacyPersistChannels = Plugin.Config.PrivacyPersistChannels;
|
|
this.snapshotPrivacyPersistUnknownChannels = Plugin
|
|
.Config
|
|
.PrivacyPersistUnknownChannels;
|
|
this.snapshotRetentionEnabled = Plugin.Config.RetentionEnabled;
|
|
this.snapshotRetentionDefaultDays = Plugin.Config.RetentionDefaultDays;
|
|
this.snapshotRetentionPerChannelDays = Plugin.Config.RetentionPerChannelDays;
|
|
|
|
var loadPrevBefore = Plugin.Config.LoadPreviousSession;
|
|
var filterPrevBefore = Plugin.Config.FilterIncludePreviousSessions;
|
|
wizard.TestOnly_AdvanceTo(2);
|
|
wizard.TestOnly_SetPendingProfile(FirstRunWizard.PrivacyProfile.Roleplay);
|
|
wizard.TestOnly_AdvanceTo(4);
|
|
wizard.CommitPending();
|
|
if (Plugin.Config.LoadPreviousSession != loadPrevBefore)
|
|
{
|
|
ImGui.Text("Skip-Step-3 path overwrote LoadPreviousSession");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
if (Plugin.Config.FilterIncludePreviousSessions != filterPrevBefore)
|
|
{
|
|
ImGui.Text("Skip-Step-3 path overwrote FilterIncludePreviousSessions");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ImGui.Text($"Wizard state smoke threw: {ex.GetType().Name}: {ex.Message}");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
return SelfTestStepResult.Pass;
|
|
}
|
|
|
|
public void CleanUp()
|
|
{
|
|
// Restore the six Variant-2 snapshots so back-to-back /xlperf
|
|
// runs don't drift the active privacy profile. If Variant 2
|
|
// never ran (Variant 1 threw early), the slots stay null and
|
|
// restore is a no-op. After restore the slots are nulled so a
|
|
// future RunStep starts fresh.
|
|
if (this.snapshotPrivacyFilterEnabled is { } privacyFilter)
|
|
Plugin.Config.PrivacyFilterEnabled = privacyFilter;
|
|
if (this.snapshotPrivacyPersistChannels is { } persistChannels)
|
|
Plugin.Config.PrivacyPersistChannels = persistChannels;
|
|
if (this.snapshotPrivacyPersistUnknownChannels is { } persistUnknown)
|
|
Plugin.Config.PrivacyPersistUnknownChannels = persistUnknown;
|
|
if (this.snapshotRetentionEnabled is { } retentionEnabled)
|
|
Plugin.Config.RetentionEnabled = retentionEnabled;
|
|
if (this.snapshotRetentionDefaultDays is { } retentionDays)
|
|
Plugin.Config.RetentionDefaultDays = retentionDays;
|
|
if (this.snapshotRetentionPerChannelDays is { } retentionPolicy)
|
|
Plugin.Config.RetentionPerChannelDays = retentionPolicy;
|
|
|
|
this.snapshotPrivacyFilterEnabled = null;
|
|
this.snapshotPrivacyPersistChannels = null;
|
|
this.snapshotPrivacyPersistUnknownChannels = null;
|
|
this.snapshotRetentionEnabled = null;
|
|
this.snapshotRetentionDefaultDays = null;
|
|
this.snapshotRetentionPerChannelDays = null;
|
|
}
|
|
}
|