Skip to content

Commit f76c682

Browse files
Introduce MockToolchain (#2178)
* Introduce MockToolchain * simplify the design (#2268) --------- Co-authored-by: Adam Sitnik <[email protected]>
1 parent 59e17fc commit f76c682

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed

src/BenchmarkDotNet/Toolchains/Results/ExecuteResult.cs

+19
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ internal ExecuteResult(List<Measurement> measurements, GcStats gcStats, Threadin
6464
ExceptionFrequency = exceptionFrequency;
6565
}
6666

67+
internal ExecuteResult(List<Measurement> measurements)
68+
{
69+
FoundExecutable = true;
70+
ExitCode = 0;
71+
errors = new List<string>();
72+
PrefixedLines = Array.Empty<string>();
73+
this.measurements = measurements;
74+
GcStats = GcStats.Empty;
75+
ThreadingStats = ThreadingStats.Empty;
76+
ExceptionFrequency = 0;
77+
}
78+
6779
internal static ExecuteResult FromRunResults(RunResults runResults, int exitCode)
6880
=> exitCode != 0
6981
? CreateFailed(exitCode)
@@ -72,6 +84,13 @@ internal static ExecuteResult FromRunResults(RunResults runResults, int exitCode
7284
internal static ExecuteResult CreateFailed(int exitCode = -1)
7385
=> new ExecuteResult(false, exitCode, default, Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), 0);
7486

87+
internal static ExecuteResult CreateFailed(string error)
88+
{
89+
var result = new ExecuteResult(false, -1, default, Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), 0);
90+
result.errors.Add(error);
91+
return result;
92+
}
93+
7594
public override string ToString() => "ExecuteResult: " + (FoundExecutable ? "Found executable" : "Executable not found");
7695

7796
public void LogIssues(ILogger logger, BuildResult buildResult)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Linq;
3+
using System.Xml.Linq;
4+
using BenchmarkDotNet.Attributes;
5+
using BenchmarkDotNet.Reports;
6+
using BenchmarkDotNet.Tests.Mocks;
7+
using BenchmarkDotNet.Tests.Mocks.Toolchain;
8+
using Xunit;
9+
using Xunit.Abstractions;
10+
11+
namespace BenchmarkDotNet.Tests.Columns
12+
{
13+
public class RatioColumnTest
14+
{
15+
private readonly ITestOutputHelper output;
16+
17+
public RatioColumnTest(ITestOutputHelper output)
18+
{
19+
this.output = output;
20+
}
21+
22+
[Fact]
23+
public void RatioColumnTest01()
24+
{
25+
var summary = MockRunner.Run<BenchmarkClass>(output, name => name switch
26+
{
27+
"Foo" => new double[] { 2, 2, 2 },
28+
"Bar" => new double[] { 4, 4, 4 },
29+
_ => throw new InvalidOperationException()
30+
});
31+
32+
var ratioColumn = summary.GetColumns().FirstOrDefault(column => column.ColumnName == "Ratio");
33+
Assert.NotNull(ratioColumn);
34+
35+
var fooCase = summary.BenchmarksCases.First(c => c.Descriptor.WorkloadMethod.Name == "Foo");
36+
var barCase = summary.BenchmarksCases.First(c => c.Descriptor.WorkloadMethod.Name == "Bar");
37+
Assert.Equal("1.00", ratioColumn.GetValue(summary, fooCase));
38+
Assert.Equal("2.00", ratioColumn.GetValue(summary, barCase));
39+
}
40+
41+
public class BenchmarkClass
42+
{
43+
[Benchmark(Baseline = true)]
44+
public void Foo() { }
45+
46+
[Benchmark]
47+
public void Bar() { }
48+
}
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using BenchmarkDotNet.Configs;
2+
using BenchmarkDotNet.Engines;
3+
using BenchmarkDotNet.Exporters;
4+
using BenchmarkDotNet.Jobs;
5+
using BenchmarkDotNet.Loggers;
6+
using BenchmarkDotNet.Reports;
7+
using BenchmarkDotNet.Running;
8+
using BenchmarkDotNet.Tests.Mocks.Toolchain;
9+
using System;
10+
using System.Collections.Generic;
11+
using System.Linq;
12+
using Xunit.Abstractions;
13+
14+
namespace BenchmarkDotNet.Tests.Mocks
15+
{
16+
public static class MockRunner
17+
{
18+
public static Summary Run<T>(ITestOutputHelper output, Func<string, double[]> measurer)
19+
=> Run<T>(output, benchmarkCase => measurer(benchmarkCase.Descriptor.WorkloadMethod.Name)
20+
.Select((value, i) => new Measurement(1, IterationMode.Workload, IterationStage.Result, i, 1, value))
21+
.ToList());
22+
23+
public static Summary Run<T>(ITestOutputHelper output, Func<BenchmarkCase, List<Measurement>> measurer)
24+
{
25+
var job = new Job("MockJob")
26+
{
27+
Infrastructure =
28+
{
29+
Toolchain = new MockToolchain(measurer)
30+
}
31+
}.Freeze();
32+
33+
var logger = new AccumulationLogger();
34+
35+
var config = DefaultConfig.Instance
36+
.WithOptions(ConfigOptions.DisableOptimizationsValidator)
37+
.AddJob(job)
38+
.AddLogger(logger);
39+
var summary = BenchmarkRunner.Run<T>(config);
40+
41+
var exporter = MarkdownExporter.Mock;
42+
exporter.ExportToLog(summary, logger);
43+
output.WriteLine(logger.GetLog());
44+
45+
return summary;
46+
}
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.Immutable;
4+
using BenchmarkDotNet.Characteristics;
5+
using BenchmarkDotNet.Loggers;
6+
using BenchmarkDotNet.Reports;
7+
using BenchmarkDotNet.Running;
8+
using BenchmarkDotNet.Toolchains;
9+
using BenchmarkDotNet.Toolchains.Parameters;
10+
using BenchmarkDotNet.Toolchains.Results;
11+
using BenchmarkDotNet.Validators;
12+
13+
namespace BenchmarkDotNet.Tests.Mocks.Toolchain
14+
{
15+
public class MockToolchain : IToolchain
16+
{
17+
public MockToolchain(Func<BenchmarkCase, List<Measurement>> measurer)
18+
=> Executor = new MockExecutor(measurer);
19+
20+
public string Name => nameof(MockToolchain);
21+
public IGenerator Generator => new MockGenerator();
22+
public IBuilder Builder => new MockBuilder();
23+
public IExecutor Executor { get; private set; }
24+
public bool IsInProcess => false;
25+
public IEnumerable<ValidationError> Validate(BenchmarkCase benchmarkCase, IResolver resolver) => ImmutableArray<ValidationError>.Empty;
26+
27+
public override string ToString() => GetType().Name;
28+
29+
private class MockGenerator : IGenerator
30+
{
31+
public GenerateResult GenerateProject(BuildPartition buildPartition, ILogger logger, string rootArtifactsFolderPath)
32+
=> GenerateResult.Success(ArtifactsPaths.Empty, ImmutableArray<string>.Empty);
33+
}
34+
35+
private class MockBuilder : IBuilder
36+
{
37+
public BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger) => BuildResult.Success(generateResult);
38+
}
39+
40+
private class MockExecutor : IExecutor
41+
{
42+
private readonly Func<BenchmarkCase, List<Measurement>> measurer;
43+
44+
public MockExecutor(Func<BenchmarkCase, List<Measurement>> measurer) => this.measurer = measurer;
45+
46+
public ExecuteResult Execute(ExecuteParameters executeParameters) => new (measurer(executeParameters.BenchmarkCase));
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)