|
6 | 6 | using CAO.Infrastructure.Overclock; |
7 | 7 | using CAO.Infrastructure.Overclock.Gaming; |
8 | 8 | using CAO.Shared; |
| 9 | +using CAO.UI; |
9 | 10 | using CAO.UI.ViewModels; |
10 | 11 | using Xunit; |
11 | 12 |
|
@@ -117,6 +118,41 @@ public async Task AutoTuning_BlockedByPendingRecovery_WritesNothing() |
117 | 118 | Assert.False(vm.IsBusy); |
118 | 119 | } |
119 | 120 |
|
| 121 | + [Fact] |
| 122 | + public async Task AutoTuning_BlockedByPendingRecovery_NamesThem_AndTellsHowToResolve() |
| 123 | + { |
| 124 | + var backend = new TuningBackend(writable: true); |
| 125 | + var stores = new TuningStores(); |
| 126 | + var vm = OverclockTestHarness.Create( |
| 127 | + new OverclockReadOnlyRegistry(backend), |
| 128 | + [backend], |
| 129 | + openRuns: [OpenRun("amd.gpu.powerLimit"), OpenRun("amd.gpu.memoryClock")], |
| 130 | + probe: new ScriptedProbe(), |
| 131 | + profileStore: stores.ProfileStore, |
| 132 | + checkpointStore: stores.CheckpointStore, |
| 133 | + journal: stores.Journal); |
| 134 | + |
| 135 | + await vm.RefreshCommand.ExecuteAsync(null); |
| 136 | + Assert.Equal(2, vm.PendingRecoveries.Count); |
| 137 | + |
| 138 | + await vm.StartAutoTuningCommand.ExecuteAsync(null); |
| 139 | + |
| 140 | + Assert.Empty(stores.Profiles); |
| 141 | + Assert.Empty(stores.Journal.Phases); |
| 142 | + Assert.Equal(vm.ApplySummary, vm.StatusLine); |
| 143 | + foreach (var row in vm.PendingRecoveries) |
| 144 | + { |
| 145 | + Assert.Contains(row.Knob, vm.ApplySummary, StringComparison.Ordinal); |
| 146 | + } |
| 147 | + |
| 148 | + Assert.Contains("05", vm.ApplySummary, StringComparison.Ordinal); |
| 149 | + Assert.Contains("ESTABILIDAD", vm.ApplySummary, StringComparison.Ordinal); |
| 150 | + Assert.Contains(Localizer.Get("overclock-recovery-revert"), vm.ApplySummary, StringComparison.Ordinal); |
| 151 | + Assert.Contains(Localizer.Get("overclock-recovery-keep"), vm.ApplySummary, StringComparison.Ordinal); |
| 152 | + Assert.Contains(Localizer.Get("overclock-recovery-discard"), vm.ApplySummary, StringComparison.Ordinal); |
| 153 | + Assert.False(vm.IsBusy); |
| 154 | + } |
| 155 | + |
120 | 156 | [Fact] |
121 | 157 | public async Task AutoTuning_Cancel_LeavesCleanState_AndResumes() |
122 | 158 | { |
@@ -212,6 +248,18 @@ private static (OverclockViewModel ViewModel, TuningStores Stores) BuildAuto(boo |
212 | 248 | return (vm, stores); |
213 | 249 | } |
214 | 250 |
|
| 251 | + private static TuningCheckpoint OpenRun(string knob) => new() |
| 252 | + { |
| 253 | + RunId = Guid.NewGuid(), |
| 254 | + BackendId = "ghost-backend", |
| 255 | + Knob = knob, |
| 256 | + Component = nameof(OverclockComponent.Gpu), |
| 257 | + AppliedValue = 110d, |
| 258 | + LastKnownGoodValue = 100d, |
| 259 | + Phase = CheckpointPhase.Started, |
| 260 | + UpdatedAtUtc = DateTimeOffset.UtcNow.AddHours(-1), |
| 261 | + }; |
| 262 | + |
215 | 263 | private sealed class TuningStores |
216 | 264 | { |
217 | 265 | public List<ValidatedOverclockProfile> Profiles { get; } = []; |
|
0 commit comments