020a945843
Probes UNMASKED_RENDERER_WEBGL once per page via a throwaway WebGL context; defaults the lava subsystem off on a positive software-renderer match or total WebGL failure; releases the throwaway context via WEBGL_lose_context after reading the renderer string to avoid exhausting the browser's per-page context limit.
181 lines
6.0 KiB
C#
181 lines
6.0 KiB
C#
using DeepDrftPublic.Client.Services;
|
|
|
|
namespace DeepDrftTests;
|
|
|
|
/// <summary>
|
|
/// Unit tests for the Theater-Mode auto-exit invariant on <see cref="WaveformVisualizerControlState"/>
|
|
/// (Phase 20 bug fix): when both subsystems are disabled, <see cref="WaveformVisualizerControlState.CoerceTheaterMode"/>
|
|
/// must force <c>TheaterMode = false</c> so observers never see a stranded-theater state.
|
|
/// </summary>
|
|
[TestFixture]
|
|
public class WaveformVisualizerControlStateTests
|
|
{
|
|
private WaveformVisualizerControlState _state = null!;
|
|
|
|
[SetUp]
|
|
public void SetUp() => _state = new WaveformVisualizerControlState();
|
|
|
|
// ── CoerceTheaterMode guard ──
|
|
|
|
// Both off + Theater on → coerce exits theater.
|
|
[Test]
|
|
public void CoerceTheaterMode_BothOff_TheaterBecomesFalse()
|
|
{
|
|
_state.TheaterMode = true;
|
|
_state.LavaEnabled = false;
|
|
_state.WaveformEnabled = false;
|
|
|
|
_state.CoerceTheaterMode();
|
|
|
|
Assert.That(_state.TheaterMode, Is.False);
|
|
}
|
|
|
|
// Lava still on → theater is left alone even if waveform is off.
|
|
[Test]
|
|
public void CoerceTheaterMode_LavaOnWaveformOff_TheaterPreserved()
|
|
{
|
|
_state.TheaterMode = true;
|
|
_state.LavaEnabled = true;
|
|
_state.WaveformEnabled = false;
|
|
|
|
_state.CoerceTheaterMode();
|
|
|
|
Assert.That(_state.TheaterMode, Is.True);
|
|
}
|
|
|
|
// Waveform still on → theater is left alone even if lava is off.
|
|
[Test]
|
|
public void CoerceTheaterMode_WaveformOnLavaOff_TheaterPreserved()
|
|
{
|
|
_state.TheaterMode = true;
|
|
_state.LavaEnabled = false;
|
|
_state.WaveformEnabled = true;
|
|
|
|
_state.CoerceTheaterMode();
|
|
|
|
Assert.That(_state.TheaterMode, Is.True);
|
|
}
|
|
|
|
// Theater already false + both off → no change (no false-positive write).
|
|
[Test]
|
|
public void CoerceTheaterMode_TheaterAlreadyFalse_NoChange()
|
|
{
|
|
_state.TheaterMode = false;
|
|
_state.LavaEnabled = false;
|
|
_state.WaveformEnabled = false;
|
|
|
|
_state.CoerceTheaterMode();
|
|
|
|
Assert.That(_state.TheaterMode, Is.False);
|
|
}
|
|
|
|
// ── Changed event fires once with coerced state visible ──
|
|
|
|
// Verify that after coercion, the Changed notification carries the already-corrected TheaterMode
|
|
// value — all observers see a consistent state in the single Changed cycle.
|
|
[Test]
|
|
public void NotifyChanged_AfterCoerce_ObserverSeesTheaterFalse()
|
|
{
|
|
_state.TheaterMode = true;
|
|
_state.LavaEnabled = false;
|
|
_state.WaveformEnabled = false;
|
|
|
|
bool? observedTheaterMode = null;
|
|
_state.Changed += () => observedTheaterMode = _state.TheaterMode;
|
|
|
|
_state.CoerceTheaterMode();
|
|
_state.NotifyChanged();
|
|
|
|
Assert.That(observedTheaterMode, Is.False);
|
|
}
|
|
|
|
// ── ApplyCapabilityDefault: the one-time HW-accel default-set ──
|
|
|
|
// No HW accel → lava defaults off, waveform stays on (the whole point of the feature).
|
|
[Test]
|
|
public void ApplyCapabilityDefault_NoHardwareAccel_LavaOffWaveformOn()
|
|
{
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: false);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(_state.LavaEnabled, Is.False);
|
|
Assert.That(_state.WaveformEnabled, Is.True);
|
|
});
|
|
}
|
|
|
|
// HW accel present → no change; lava keeps its shipped on-default (the common case is untouched).
|
|
[Test]
|
|
public void ApplyCapabilityDefault_HardwareAccelerated_LavaStaysOn()
|
|
{
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: true);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(_state.LavaEnabled, Is.True);
|
|
Assert.That(_state.WaveformEnabled, Is.True);
|
|
});
|
|
}
|
|
|
|
// No HW accel raises Changed once so the controls UI / bridge / theater observers all react.
|
|
[Test]
|
|
public void ApplyCapabilityDefault_NoHardwareAccel_RaisesChanged()
|
|
{
|
|
var raised = 0;
|
|
_state.Changed += () => raised++;
|
|
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: false);
|
|
|
|
Assert.That(raised, Is.EqualTo(1));
|
|
}
|
|
|
|
// HW accel present must not churn observers — no Changed when nothing changed.
|
|
[Test]
|
|
public void ApplyCapabilityDefault_HardwareAccelerated_DoesNotRaiseChanged()
|
|
{
|
|
var raised = 0;
|
|
_state.Changed += () => raised++;
|
|
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: true);
|
|
|
|
Assert.That(raised, Is.Zero);
|
|
}
|
|
|
|
// Guarded to once per session: a second call cannot re-clobber, even with a different verdict.
|
|
[Test]
|
|
public void ApplyCapabilityDefault_SecondCall_IsNoOp()
|
|
{
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: true); // first call wins (accelerated → on)
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: false); // must be ignored
|
|
|
|
Assert.That(_state.LavaEnabled, Is.True);
|
|
}
|
|
|
|
// Must not override an explicit in-session toggle: once applied, a user re-enabling lava on a
|
|
// software renderer sticks — a later (guarded) call never reverts it.
|
|
[Test]
|
|
public void ApplyCapabilityDefault_DoesNotOverrideExplicitUserToggle()
|
|
{
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: false); // default: lava off
|
|
_state.LavaEnabled = true; // user re-enables at their own risk
|
|
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: false); // guarded → no-op
|
|
|
|
Assert.That(_state.LavaEnabled, Is.True);
|
|
}
|
|
|
|
// No HW accel while Theater Mode is on with only lava active → coercion exits theater in the same
|
|
// cycle (lava off + waveform off would strand theater; here waveform stays on, but verify the
|
|
// coercion path is exercised when it WOULD strand).
|
|
[Test]
|
|
public void ApplyCapabilityDefault_NoHardwareAccel_CoercesStrandedTheater()
|
|
{
|
|
_state.WaveformEnabled = false; // only lava active
|
|
_state.TheaterMode = true;
|
|
|
|
_state.ApplyCapabilityDefault(hardwareAccelerated: false); // lava off → both off → strand
|
|
|
|
Assert.That(_state.TheaterMode, Is.False);
|
|
}
|
|
}
|