Moves the hardware-change debounce/coalescing worker (the dirty/queued flags and re-queue logic) into a dedicated class with an injectable delay, so the concurrency behavior can be unit-tested deterministically instead of living as an untestable fire-and-forget block in the service. Behavior is unchanged. Adds 3 tests (single rebuild after delay, burst coalesced to one, no rebuild when closed) driven by a controllable delay gate. 199 tests pass (was 196). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
1.8 KiB
C#
61 lines
1.8 KiB
C#
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
// Copyright (C) LibreHardwareMonitor and Contributors.
|
|
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using LibreHardwareMonitor.Windows.WinUI.Services;
|
|
using Xunit;
|
|
|
|
namespace LibreHardwareMonitor.Windows.WinUI.Tests.Services;
|
|
|
|
public class TreeRebuildCoalescerTests
|
|
{
|
|
[Fact]
|
|
public async Task Request_RebuildsOnceAfterDelay()
|
|
{
|
|
var gate = new TaskCompletionSource();
|
|
int rebuilds = 0;
|
|
var coalescer = new TreeRebuildCoalescer(() => Interlocked.Increment(ref rebuilds), () => true, () => gate.Task);
|
|
|
|
coalescer.Request();
|
|
Assert.Equal(0, rebuilds); // worker is blocked on the (not-yet-completed) delay
|
|
|
|
gate.SetResult();
|
|
await coalescer.RebuildLoopTask;
|
|
|
|
Assert.Equal(1, rebuilds);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Request_CoalescesBurstIntoSingleRebuild()
|
|
{
|
|
var gate = new TaskCompletionSource();
|
|
int rebuilds = 0;
|
|
var coalescer = new TreeRebuildCoalescer(() => Interlocked.Increment(ref rebuilds), () => true, () => gate.Task);
|
|
|
|
coalescer.Request();
|
|
coalescer.Request();
|
|
coalescer.Request();
|
|
|
|
gate.SetResult();
|
|
await coalescer.RebuildLoopTask;
|
|
|
|
Assert.Equal(1, rebuilds);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Request_DoesNotRebuildWhenCannotRebuild()
|
|
{
|
|
var gate = new TaskCompletionSource();
|
|
int rebuilds = 0;
|
|
var coalescer = new TreeRebuildCoalescer(() => Interlocked.Increment(ref rebuilds), () => false, () => gate.Task);
|
|
|
|
coalescer.Request();
|
|
gate.SetResult();
|
|
await coalescer.RebuildLoopTask;
|
|
|
|
Assert.Equal(0, rebuilds);
|
|
}
|
|
}
|