Skip to content

Commit 5b8cedd

Browse files
committed
Add support for the --useDefaultBaseline option and improve baseline selection logic
1 parent ac3dd96 commit 5b8cedd

8 files changed

Lines changed: 181 additions & 14 deletions

File tree

src/ModVerify.CliApp/App/VerifyAction.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ protected override VerificationBaseline GetBaseline(VerificationTarget verificat
6161
{
6262
Console.WriteLine();
6363
ModVerifyConsoleUtilities.WriteBaselineInfo(baseline, baselinePath);
64-
Logger?.LogDebug("Using baseline {Baseline} from location '{Path}'", baseline.ToString(), baselinePath);
64+
Logger?.LogDebug("Using baseline {Baseline} from location '{Path}'",
65+
baseline.ToString(), baselinePath ?? "Embedded");
6566
Console.WriteLine();
6667
}
6768
return baseline;

src/ModVerify.CliApp/Reporting/BaselineSelector.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public VerificationBaseline SelectBaseline(VerificationTarget verificationTarget
4242
}
4343
}
4444

45-
if (!settings.ReportSettings.SearchBaselineLocally)
45+
if (settings.ReportSettings is { SearchBaselineLocally: false, UseDefaultBaseline: false })
4646
{
4747
_logger?.LogDebug(ModVerifyConstants.ConsoleEventId,
4848
"No baseline path specified and local search is not enabled. Using empty baseline.");
@@ -134,7 +134,7 @@ internal static VerificationBaseline LoadEmbeddedBaseline(GameEngineType engineT
134134
private VerificationBaseline FindBaselineNonInteractive(VerificationTarget target, out string? usedPath)
135135
{
136136
if (_baselineFactory.TryFindBaselineInDirectory(
137-
target.Location.TargetPath,
137+
target.Location.TargetPath,
138138
b => IsBaselineCompatible(b, target),
139139
out var baseline,
140140
out usedPath))
@@ -144,6 +144,20 @@ private VerificationBaseline FindBaselineNonInteractive(VerificationTarget targe
144144
}
145145
_logger?.LogTrace("No baseline file found in taget path '{TargetPath}'.", target.Location.TargetPath);
146146
usedPath = null;
147+
if (settings.ReportSettings.UseDefaultBaseline)
148+
{
149+
try
150+
{
151+
var defaultBaseline = LoadEmbeddedBaseline(target.Engine);
152+
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Automatically applying default embedded baseline for engine '{Engine}'.", target.Engine);
153+
return defaultBaseline;
154+
}
155+
catch (InvalidBaselineException)
156+
{
157+
throw new InvalidOperationException(
158+
"Invalid baseline packed along ModVerify App. Please reach out to the creators. Thanks!");
159+
}
160+
}
147161
return VerificationBaseline.Empty;
148162
}
149163

src/ModVerify.CliApp/Settings/CommandLine/VerifyVerbOption.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ internal sealed class VerifyVerbOption : BaseModVerifyOptions
2929
public bool IgnoreAsserts { get; init; }
3030

3131

32-
[Option("baseline", SetName = "baselineSelection", Required = false,
33-
HelpText = "Path to a JSON baseline file. Cannot be used together with --searchBaseline.")]
32+
[Option("baseline", Required = false,
33+
HelpText = "Path to a JSON baseline file. Cannot be used together with --searchBaseline or --useDefaultBaseline.")]
3434
public string? Baseline { get; init; }
3535

36-
[Option("searchBaseline", SetName = "baselineSelection", Required = false,
37-
HelpText = "When set, the application will search for baseline files and use them for verification. Cannot be used together with --baseline")]
36+
[Option("searchBaseline", Required = false,
37+
HelpText = "When set, the application will search for baseline files and use them for verification. Cannot be used together with --baseline or --useDefaultBaseline")]
3838
public bool SearchBaselineLocally { get; init; }
3939

40+
[Option("useDefaultBaseline", Required = false,
41+
HelpText = "When set, the application will use the default embedded baseline for the detected game engine. Cannot be used together with --baseline or --searchBaseline.")]
42+
public bool UseDefaultBaseline { get; init; }
43+
4044
public bool IsRunningWithoutArguments { get; init; }
4145
}

src/ModVerify.CliApp/Settings/ModVerifyAppSettings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public sealed class VerifyReportSettings : AppReportSettings
1717
{
1818
public string? BaselinePath { get; init; }
1919
public bool SearchBaselineLocally { get; init; }
20+
public bool UseDefaultBaseline { get; init; }
2021
}
2122

2223
internal abstract class AppSettingsBase(AppReportSettings reportSettings)

src/ModVerify.CliApp/Settings/SettingsBuilder.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ void ValidateVerb()
5757
throw new AppArgumentException($"Options {searchOption} and {baselineOption} cannot be used together.");
5858
}
5959

60+
if (verifyOptions.UseDefaultBaseline && !string.IsNullOrEmpty(verifyOptions.Baseline))
61+
{
62+
var useDefaultOption = typeof(VerifyVerbOption).GetOptionName(nameof(VerifyVerbOption.UseDefaultBaseline));
63+
var baselineOption = typeof(VerifyVerbOption).GetOptionName(nameof(VerifyVerbOption.Baseline));
64+
throw new AppArgumentException($"Options {useDefaultOption} and {baselineOption} cannot be used together.");
65+
}
66+
67+
if (verifyOptions is { UseDefaultBaseline: true, SearchBaselineLocally: true })
68+
{
69+
var useDefaultOption = typeof(VerifyVerbOption).GetOptionName(nameof(VerifyVerbOption.UseDefaultBaseline));
70+
var searchOption = typeof(VerifyVerbOption).GetOptionName(nameof(VerifyVerbOption.SearchBaselineLocally));
71+
throw new AppArgumentException($"Options {useDefaultOption} and {searchOption} cannot be used together.");
72+
}
73+
6074
if (verifyOptions is { FailFast: true, MinimumFailureSeverity: null })
6175
{
6276
var failFast = typeof(VerifyVerbOption).GetOptionName(nameof(VerifyVerbOption.FailFast));
@@ -86,6 +100,7 @@ VerifyReportSettings BuildReportSettings()
86100
BaselinePath = verifyOptions.Baseline,
87101
MinimumReportSeverity = verifyOptions.MinimumSeverity,
88102
SearchBaselineLocally = verifyOptions.SearchBaselineLocally,
103+
UseDefaultBaseline = verifyOptions.UseDefaultBaseline,
89104
SuppressionsPath = verifyOptions.Suppressions,
90105
Verbose = verifyOptions.Verbose
91106
};

src/ModVerify/Verifiers/Commons/SingleModelVerifier.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,14 @@ private void VerifyParticle(IAloParticleFile file, IReadOnlyCollection<string> c
250250

251251
if (!fileName.Equals(name, StringComparison.OrdinalIgnoreCase))
252252
{
253-
AddError(VerificationError.Create(
254-
this,
255-
VerifierErrorCodes.InvalidParticleName,
256-
$"The particle name '{file.Content.Name}' does not match file name '{file.FileName}'",
257-
VerificationSeverity.Error,
258-
[file.FileName.ToUpperInvariant()],
259-
file.Content.Name));
253+
// TODO: Re-enable
254+
// AddError(VerificationError.Create(
255+
// this,
256+
// VerifierErrorCodes.InvalidParticleName,
257+
// $"The particle name '{file.Content.Name}' does not match file name '{file.FileName}'",
258+
// VerificationSeverity.Error,
259+
// [file.FileName.ToUpperInvariant()],
260+
// file.Content.Name));
260261
}
261262

262263
}

test/ModVerify.CliApp.Test/ModVerifyOptionsParserTest.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using AET.ModVerify.App.Settings.CommandLine;
2+
using AET.ModVerify.Reporting;
23
using AnakinRaW.ApplicationBase.Environment;
34
using System;
45
using System.IO.Abstractions;
@@ -211,4 +212,73 @@ public void Parse_CreateBaseline_MissingRequired_Fails(string argString)
211212
Assert.Null(settings.ModVerifyOptions);
212213
Assert.Null(settings.UpdateOptions);
213214
}
215+
216+
[Theory]
217+
[InlineData("verify --mods myMod --baseline myBaseline.json", "myBaseline.json", false, false)]
218+
[InlineData("verify --mods myMod --searchBaseline", null, true, false)]
219+
[InlineData("verify --path myMod --useDefaultBaseline", null, false, true)]
220+
public void Parse_Verify_BaselineOptions(string argString, string? expectedBaseline, bool expectedSearchBaseline, bool expectedUseDefaultBaseline)
221+
{
222+
var settings = Parser.Parse(argString.Split(' ', StringSplitOptions.RemoveEmptyEntries));
223+
224+
Assert.True(settings.HasOptions);
225+
var verify = Assert.IsType<VerifyVerbOption>(settings.ModVerifyOptions);
226+
Assert.Equal(expectedBaseline, verify.Baseline);
227+
Assert.Equal(expectedSearchBaseline, verify.SearchBaselineLocally);
228+
Assert.Equal(expectedUseDefaultBaseline, verify.UseDefaultBaseline);
229+
}
230+
231+
[Fact]
232+
public void Parse_Verify_Baseline_And_SearchBaseline_CanBeParsedTogether()
233+
{
234+
// Mutual exclusivity of --baseline and --searchBaseline is enforced later by SettingsBuilder, not by the parser.
235+
const string argString = "verify --mods myMod --baseline myBaseline.json --searchBaseline";
236+
237+
var settings = Parser.Parse(argString.Split(' ', StringSplitOptions.RemoveEmptyEntries));
238+
239+
Assert.True(settings.HasOptions);
240+
var verify = Assert.IsType<VerifyVerbOption>(settings.ModVerifyOptions);
241+
Assert.Equal("myBaseline.json", verify.Baseline);
242+
Assert.True(verify.SearchBaselineLocally);
243+
}
244+
245+
[Theory]
246+
[InlineData("verify --path myMod --outDir myOut", "myOut")]
247+
[InlineData("verify --path myMod -o myOut", "myOut")]
248+
[InlineData("verify --path myMod", null)]
249+
public void Parse_Verify_OutputDirectory(string argString, string? expectedOutDir)
250+
{
251+
var settings = Parser.Parse(argString.Split(' ', StringSplitOptions.RemoveEmptyEntries));
252+
253+
Assert.True(settings.HasOptions);
254+
var verify = Assert.IsType<VerifyVerbOption>(settings.ModVerifyOptions);
255+
Assert.Equal(expectedOutDir, verify.OutputDirectory);
256+
}
257+
258+
[Theory]
259+
[InlineData("verify --path myMod --failFast --minFailSeverity Critical", true, "Critical")]
260+
[InlineData("verify --path myMod --failFast --minFailSeverity Warning", true, "Warning")]
261+
[InlineData("verify --path myMod", false, null)]
262+
public void Parse_Verify_FailFastOptions(string argString, bool expectedFailFast, string? expectedMinSeverity)
263+
{
264+
var settings = Parser.Parse(argString.Split(' ', StringSplitOptions.RemoveEmptyEntries));
265+
266+
Assert.True(settings.HasOptions);
267+
var verify = Assert.IsType<VerifyVerbOption>(settings.ModVerifyOptions);
268+
Assert.Equal(expectedFailFast, verify.FailFast);
269+
var expectedSeverity = expectedMinSeverity is null ? (VerificationSeverity?)null : Enum.Parse<VerificationSeverity>(expectedMinSeverity);
270+
Assert.Equal(expectedSeverity, verify.MinimumFailureSeverity);
271+
}
272+
273+
[Theory]
274+
[InlineData("verify --path myMod --ignoreAsserts", true)]
275+
[InlineData("verify --path myMod", false)]
276+
public void Parse_Verify_IgnoreAsserts(string argString, bool expectedIgnoreAsserts)
277+
{
278+
var settings = Parser.Parse(argString.Split(' ', StringSplitOptions.RemoveEmptyEntries));
279+
280+
Assert.True(settings.HasOptions);
281+
var verify = Assert.IsType<VerifyVerbOption>(settings.ModVerifyOptions);
282+
Assert.Equal(expectedIgnoreAsserts, verify.IgnoreAsserts);
283+
}
214284
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using AET.ModVerify.App;
2+
using AET.ModVerify.App.Settings;
3+
using AET.ModVerify.App.Settings.CommandLine;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using System.IO.Abstractions;
6+
using Testably.Abstractions;
7+
using Xunit;
8+
9+
namespace ModVerify.CliApp.Test;
10+
11+
public class SettingsBuilderTest
12+
{
13+
private readonly SettingsBuilder _builder;
14+
15+
public SettingsBuilderTest()
16+
{
17+
var services = new ServiceCollection();
18+
services.AddSingleton<IFileSystem>(new RealFileSystem());
19+
var provider = services.BuildServiceProvider();
20+
_builder = new SettingsBuilder(provider);
21+
}
22+
23+
[Fact]
24+
public void BuildSettings_UseDefaultBaseline_And_Baseline_Throws()
25+
{
26+
var options = new VerifyVerbOption
27+
{
28+
UseDefaultBaseline = true,
29+
Baseline = "myBaseline.json",
30+
TargetPath = "myPath",
31+
};
32+
33+
Assert.Throws<AppArgumentException>(() => _builder.BuildSettings(options));
34+
}
35+
36+
[Fact]
37+
public void BuildSettings_UseDefaultBaseline_And_SearchBaseline_Throws()
38+
{
39+
var options = new VerifyVerbOption
40+
{
41+
UseDefaultBaseline = true,
42+
SearchBaselineLocally = true,
43+
TargetPath = "myPath",
44+
};
45+
46+
Assert.Throws<AppArgumentException>(() => _builder.BuildSettings(options));
47+
}
48+
49+
[Fact]
50+
public void BuildSettings_UseDefaultBaseline_Alone_DoesNotThrow()
51+
{
52+
var options = new VerifyVerbOption
53+
{
54+
UseDefaultBaseline = true,
55+
TargetPath = "myPath",
56+
};
57+
58+
var settings = _builder.BuildSettings(options);
59+
Assert.NotNull(settings);
60+
}
61+
}

0 commit comments

Comments
 (0)