Skip to content

Commit 48d1ba2

Browse files
committed
Refactor Prime95 to use changes made in internal repo.
1 parent 8b050c0 commit 48d1ba2

5 files changed

Lines changed: 56 additions & 73 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.1.44
1+
2.1.45

src/VirtualClient/VirtualClient.Actions.UnitTests/Prime95/Prime95ExecutorTests.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public void Prime95ExecutorThrowsWhenTheWorkloadDoesNotProduceValidResults(Platf
153153
{
154154
this.SetupTest(platform);
155155
this.mockFixture.File.Setup(fe => fe.ReadAllTextAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
156-
.ReturnsAsync("");
156+
.ReturnsAsync("Invalid results");
157157

158158
using (TestPrime95Executor executor = new TestPrime95Executor(this.mockFixture))
159159
{
@@ -162,14 +162,14 @@ public void Prime95ExecutorThrowsWhenTheWorkloadDoesNotProduceValidResults(Platf
162162
WorkloadResultsException exception = Assert.ThrowsAsync<WorkloadResultsException>(
163163
() => executor.ExecuteAsync(CancellationToken.None));
164164

165-
Assert.AreEqual(ErrorReason.WorkloadResultsNotFound, exception.Reason);
165+
Assert.AreEqual(ErrorReason.InvalidResults, exception.Reason);
166166
}
167167
}
168168

169169
[Test]
170170
[TestCase(PlatformID.Win32NT)]
171171
[TestCase(PlatformID.Unix)]
172-
public void Prime95ExecutorThrowsWhenWorkloadResultsFileNotFound(PlatformID platform)
172+
public void Prime95ExecutorHandlesCasesWhereTheResultsFileIsNotProduced(PlatformID platform)
173173
{
174174
this.SetupTest(platform);
175175
this.mockFixture.File.Setup(fe => fe.Exists(It.Is<string>(file => file.EndsWith("results.txt"))))
@@ -178,11 +178,7 @@ public void Prime95ExecutorThrowsWhenWorkloadResultsFileNotFound(PlatformID plat
178178
using (TestPrime95Executor executor = new TestPrime95Executor(this.mockFixture))
179179
{
180180
this.mockFixture.ProcessManager.OnCreateProcess = (command, arguments, directory) => this.mockFixture.Process;
181-
182-
WorkloadResultsException exception = Assert.ThrowsAsync<WorkloadResultsException>(
183-
() => executor.ExecuteAsync(CancellationToken.None));
184-
185-
Assert.AreEqual(ErrorReason.WorkloadResultsNotFound, exception.Reason);
181+
Assert.DoesNotThrowAsync(() => executor.ExecuteAsync(CancellationToken.None));
186182
}
187183
}
188184

src/VirtualClient/VirtualClient.Actions.UnitTests/Prime95/Prime95MetricsParserTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ public void Prime95ParserVerifyMetricsForPassResults()
3434
IList<Metric> metrics = this.testParser.Parse();
3535

3636
Assert.AreEqual(2, metrics.Count);
37-
MetricAssert.Exists(metrics, "passTestCount", 200);
38-
MetricAssert.Exists(metrics, "failTestCount", 0);
37+
MetricAssert.Exists(metrics, "Test Pass", 200);
38+
MetricAssert.Exists(metrics, "Test Fail", 0);
3939
}
4040

4141
[Test]
@@ -47,8 +47,8 @@ public void Prime95ParserVerifyMetricsForFailedResults()
4747
IList<Metric> metrics = this.testParser.Parse();
4848

4949
Assert.AreEqual(2, metrics.Count);
50-
MetricAssert.Exists(metrics, "passTestCount", 7);
51-
MetricAssert.Exists(metrics, "failTestCount", 3);
50+
MetricAssert.Exists(metrics, "Test Pass", 7);
51+
MetricAssert.Exists(metrics, "Test Fail", 3);
5252
}
5353
}
5454
}

src/VirtualClient/VirtualClient.Actions/Prime95/Prime95Executor.cs

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,14 @@ namespace VirtualClient.Actions
88
using System.IO;
99
using System.IO.Abstractions;
1010
using System.Linq;
11-
using System.Runtime.InteropServices;
1211
using System.Threading;
1312
using System.Threading.Tasks;
14-
using Microsoft.AspNetCore.Http;
15-
using Microsoft.AspNetCore.Http.HttpResults;
1613
using Microsoft.Extensions.DependencyInjection;
14+
using Microsoft.Extensions.Logging;
1715
using VirtualClient.Common;
1816
using VirtualClient.Common.Extensions;
1917
using VirtualClient.Common.Telemetry;
2018
using VirtualClient.Contracts;
21-
using VirtualClient.Contracts.Metadata;
2219

2320
/// <summary>
2421
/// The Prime95 workload executor.
@@ -27,7 +24,6 @@ namespace VirtualClient.Actions
2724
public class Prime95Executor : VirtualClientComponent
2825
{
2926
private IFileSystem fileSystem;
30-
private IPackageManager packageManager;
3127
private ISystemManagement systemManagement;
3228
private List<int> successExitCodes;
3329

@@ -40,7 +36,6 @@ public Prime95Executor(IServiceCollection dependencies, IDictionary<string, ICon
4036
: base(dependencies, parameters)
4137
{
4238
this.systemManagement = this.Dependencies.GetService<ISystemManagement>();
43-
this.packageManager = this.systemManagement.PackageManager;
4439
this.fileSystem = this.systemManagement.FileSystem;
4540

4641
// The exit code on SafeKill is -1 which is not a part of the default success codes.
@@ -163,7 +158,7 @@ public bool UseHyperthreading
163158
/// <summary>
164159
/// The path to the Prime95 workload package.
165160
/// </summary>
166-
protected DependencyPath Prime95Package { get; private set; }
161+
protected DependencyPath WorkloadPackage { get; private set; }
167162

168163
/// <summary>
169164
/// Executes cleanup operations.
@@ -180,33 +175,37 @@ protected override async Task CleanupAsync(EventContext telemetryContext, Cancel
180175
{
181176
foreach (IProcessProxy processProxy in runningProcesses)
182177
{
183-
processProxy.SafeKill(this.Logger);
178+
try
179+
{
180+
processProxy.SafeKill();
181+
}
182+
catch (Exception exc)
183+
{
184+
// Best effort only but we want to log the issue for debugging/triage.
185+
this.Logger.LogMessage(
186+
$"{this.TypeName}.CleanupProcessError",
187+
LogLevel.Warning,
188+
telemetryContext.Clone().AddError(exc).AddContext("process", processName));
189+
}
184190
}
185191
}
186-
187-
if (this.fileSystem.File.Exists(this.ResultsFilePath))
188-
{
189-
await this.fileSystem.File.DeleteAsync(this.ResultsFilePath, RetryPolicies.FileDelete);
190-
}
191192
}
192193

193194
/// <summary>
194195
/// Initializes the environment for execution of the Prime95 workload.
195196
/// </summary>
196197
protected override async Task InitializeAsync(EventContext telemetryContext, CancellationToken cancellationToken)
197198
{
198-
await this.EvaluateParametersAsync(cancellationToken);
199-
200-
this.Prime95Package = await this.GetPlatformSpecificPackageAsync(this.PackageName, cancellationToken);
199+
this.WorkloadPackage = await this.GetPlatformSpecificPackageAsync(this.PackageName, cancellationToken);
201200

202201
switch (this.Platform)
203202
{
204203
case PlatformID.Win32NT:
205-
this.ExecutablePath = this.Combine(this.Prime95Package.Path, "prime95.exe");
204+
this.ExecutablePath = this.Combine(this.WorkloadPackage.Path, "prime95.exe");
206205
break;
207206

208207
case PlatformID.Unix:
209-
this.ExecutablePath = this.Combine(this.Prime95Package.Path, "mprime");
208+
this.ExecutablePath = this.Combine(this.WorkloadPackage.Path, "mprime");
210209
break;
211210

212211
default:
@@ -227,8 +226,8 @@ protected override async Task InitializeAsync(EventContext telemetryContext, Can
227226
ErrorReason.DependencyNotFound);
228227
}
229228

230-
this.SettingsFilePath = this.Combine(this.GetTempPath(), "prime.txt");
231-
this.ResultsFilePath = this.Combine(this.GetTempPath(), FileContext.GetFileName("results.txt", DateTime.UtcNow));
229+
this.SettingsFilePath = this.Combine(this.WorkloadPackage.Path, "prime.txt");
230+
this.ResultsFilePath = this.Combine(this.WorkloadPackage.Path, "results.txt");
232231
}
233232

234233
/// <summary>
@@ -262,6 +261,13 @@ protected override void Validate()
262261
ErrorReason.InvalidProfileDefinition);
263262
}
264263

264+
if (this.MaxTortureFFT <= 0)
265+
{
266+
throw new WorkloadException(
267+
$"Invalid '{nameof(this.MaxTortureFFT)}' parameter value. The maximum torture FFT value must be greater than zero.",
268+
ErrorReason.InvalidProfileDefinition);
269+
}
270+
265271
if (this.MaxTortureFFT < this.MinTortureFFT)
266272
{
267273
throw new WorkloadException(
@@ -285,9 +291,9 @@ private async Task ExecuteWorkloadAsync(EventContext telemetryContext, Cancellat
285291

286292
await this.Logger.LogMessageAsync($"{this.TypeName}.ExecuteWorkload", telemetryContext, async () =>
287293
{
288-
using (IProcessProxy process = this.systemManagement.ProcessManager.CreateProcess(this.ExecutablePath, commandArguments, this.Prime95Package.Path))
294+
using (IProcessProxy process = this.systemManagement.ProcessManager.CreateProcess(this.ExecutablePath, commandArguments, this.WorkloadPackage.Path))
289295
{
290-
this.CleanupTasks.Add(() => process.SafeKill(this.Logger));
296+
this.CleanupTasks.Add(() => process.SafeKill());
291297

292298
// Prime95 does not stop on it's own. It will run until you tell it to stop.
293299
// We have to definitively stop the program.
@@ -296,36 +302,24 @@ await this.Logger.LogMessageAsync($"{this.TypeName}.ExecuteWorkload", telemetryC
296302
if (process.Start())
297303
{
298304
await this.WaitAsync(explicitTimeout, cancellationToken);
299-
process.SafeKill(this.Logger);
305+
process.SafeKill();
300306

301307
if (!cancellationToken.IsCancellationRequested)
302308
{
303309
string results = null;
304-
305-
try
310+
if (this.fileSystem.File.Exists(this.ResultsFilePath))
306311
{
307-
await RetryPolicies.FileOperations.ExecuteAsync(async () =>
308-
{
309-
if (this.fileSystem.File.Exists(this.ResultsFilePath))
310-
{
311-
results = await this.fileSystem.File.ReadAllTextAsync(this.ResultsFilePath);
312-
}
313-
});
314-
315-
if (string.IsNullOrWhiteSpace(results))
316-
{
317-
throw new WorkloadResultsException(
318-
$"Prime95 results file not found at path '{this.ResultsFilePath}'.",
319-
ErrorReason.WorkloadResultsNotFound);
320-
}
321-
322-
// The exit code on SafeKill is -1 which is not a part of the default success codes.
323-
process.ThrowIfWorkloadFailed(this.successExitCodes);
324-
this.CaptureMetrics(process, results, telemetryContext, cancellationToken);
312+
results = await this.fileSystem.File.ReadAllTextAsync(this.ResultsFilePath);
325313
}
326-
finally
314+
315+
await this.LogProcessDetailsAsync(process, telemetryContext, "Prime95", results: results?.AsArray());
316+
317+
// The exit code on SafeKill is -1 which is not a part of the default success codes.
318+
process.ThrowIfWorkloadFailed(this.successExitCodes);
319+
320+
if (!string.IsNullOrWhiteSpace(results))
327321
{
328-
await this.LogProcessDetailsAsync(process, telemetryContext, "Prime95", results?.AsArray());
322+
this.CaptureMetrics(process, results, telemetryContext, cancellationToken);
329323
}
330324
}
331325
}
@@ -362,13 +356,6 @@ private void CaptureMetrics(IProcessProxy process, string results, EventContext
362356
{
363357
if (!cancellationToken.IsCancellationRequested)
364358
{
365-
this.MetadataContract.AddForScenario(
366-
"Prime95",
367-
process.FullCommand(),
368-
toolVersion: this.Prime95Package.Version);
369-
370-
this.MetadataContract.Apply(telemetryContext);
371-
372359
Prime95MetricsParser parser = new Prime95MetricsParser(results);
373360
IList<Metric> workloadMetrics = parser.Parse();
374361

src/VirtualClient/VirtualClient.Actions/Prime95/Prime95MetricsParser.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ public class Prime95MetricsParser : MetricsParser
1616
/// <summary>
1717
/// Constructor for <see cref="Prime95MetricsParser"/>
1818
/// </summary>
19-
/// <param name="rawText">Raw text to parse.</param>
20-
public Prime95MetricsParser(string rawText)
21-
: base(rawText)
19+
/// <param name="results">Raw text to parse.</param>
20+
public Prime95MetricsParser(string results)
21+
: base(results)
2222
{
2323
}
2424

@@ -46,12 +46,12 @@ public override IList<Metric> Parse()
4646
}
4747
}
4848

49-
metrics.Add(new Metric("passTestCount", selfTestPassCount, MetricRelativity.HigherIsBetter));
50-
metrics.Add(new Metric("failTestCount", fatalErrorsCount, MetricRelativity.LowerIsBetter));
49+
metrics.Add(new Metric("Test Pass", selfTestPassCount, "count", MetricRelativity.HigherIsBetter));
50+
metrics.Add(new Metric("Test Fail", fatalErrorsCount, "count", MetricRelativity.LowerIsBetter));
5151

52-
if (metrics.Count != 2)
52+
if (selfTestPassCount <= 0 && fatalErrorsCount <= 0)
5353
{
54-
throw new WorkloadResultsException($"The Prime95 Workload did not generate valid metrics! ");
54+
throw new WorkloadResultsException($"The Prime95 Workload did not generate any valid pass/fail metrics!");
5555
}
5656

5757
return metrics;
@@ -73,6 +73,6 @@ protected override void Preprocess()
7373

7474
// Removing unnecessary starting and ending space.
7575
this.PreprocessedText = this.PreprocessedText.Trim();
76-
}
76+
}
7777
}
7878
}

0 commit comments

Comments
 (0)