New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adding validation errors when the benchmarks are unsupported #2148
adding validation errors when the benchmarks are unsupported #2148
Conversation
Yep, we need a specific error message in The problem is that the benchmarks are filtered by var supportedBenchmarks = GetSupportedBenchmarks(benchmarkRunInfos, compositeLogger, resolver); //filtering by Toolchain.IsSupported
if (!supportedBenchmarks.Any(benchmarks => benchmarks.BenchmarksCases.Any()))
return new[] { Summary.NothingToRun(title, resultsFolderPath, logFilePath) };
var validationErrors = Validate(supportedBenchmarks, compositeLogger);
if (validationErrors.Any(validationError => validationError.IsCritical))
return new[] { Summary.ValidationFailed(title, resultsFolderPath, logFilePath, validationErrors) };
If we replace var supportedBenchmarks = GetSupportedBenchmarks(benchmarkRunInfos, resolver, out List<ValidationErrors> validationErrors);
validationErrors.AddRange(Validate(supportedBenchmarks, compositeLogger));
if (validationErrors.Any(validationError => validationError.IsCritical))
return new[] { Summary.ValidationFailed(title, resultsFolderPath, logFilePath, validationErrors) };
if (!supportedBenchmarks.Any(benchmarks => benchmarks.BenchmarksCases.Any())) // looks redundant, validators should check it
return new[] { Summary.NothingToRun(title, resultsFolderPath, logFilePath) }; For the maintainers: |
Thanks for the feedback, changed accordingly here 524dbf9.
Please let me know if that works for you |
b08a45b
to
3863545
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emanuel-v-r big thanks for your contribution! PTAL at my comments
I guess this test won't contain [Fact]
public void BenchmarkDifferentPlatformReturnsValidationError()
{
var сonfig = new ManualConfig()
.With(Job.Dry.With(InProcessToolchain.Instance).With(Platform.X86))
.With(Job.Dry.With(InProcessToolchain.Instance).With(Platform.X64))
.With(new OutputLogger(Output))
.With(DefaultColumnProviders.Instance);
var runInfo = BenchmarkConverter.TypeToBenchmarks(typeof(BenchmarkAllCases), сonfig);
var summary = BenchmarkRunner.Run(runInfo);
Assert.NotEmpty(summary.ValidationErrors);
} Also, we need to add a specific reason to the validation errors. To fix it we need change interface to it public interface IToolchain
{
[PublicAPI] string Name { get; }
IGenerator Generator { get; }
IBuilder Builder { get; }
IExecutor Executor { get; }
bool IsInProcess { get; }
- bool IsSupported(BenchmarkCase benchmarkCase, ILogger logger, IResolver resolver);
+ bool IsSupported(BenchmarkCase benchmarkCase, IResolver resolver, List<ValidationError> validationErrors);
} and do it for each toolchain: - logger.WriteLineError("The Roslyn toolchain is only supported on .NET Framework");
+ validationErrors.Add(new ValidationError(false, "The Roslyn toolchain is only supported on .NET Framework")); But:
|
1e54eb9
to
bbc9544
Compare
I was not able to replicate the issue using your test but I do understand what the issue is, nice catch thank you! EDIT: |
src/BenchmarkDotNet/Toolchains/InProcess.NoEmit/InProcessNoEmitToolchain.cs
Outdated
Show resolved
Hide resolved
} | ||
|
||
if (InvalidCliPath(customDotNetCliPath: null, benchmarkCase, logger)) | ||
return false; | ||
{ | ||
var validationError = new ValidationError(true, $"InvalidCliPath, benchmark '{benchmarkCase.DisplayInfo}' will not be executed", benchmarkCase); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not use fast exit, collect all errors and return them.
It's better to display as much as possible errors.
If the user is not on windows AND the cli path is invalid, it displays only the first message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if we want to check all the errors, or just fail fast here, anyway I kept the existing behavior, not sure if we want to change that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can open the validators folder, all of them may display multiple errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can open the validators folder, all of them may display multiple errors.
I mean toolchains errors, currently it only prints one error and exits as you can see in the previous code for "IsSupported" method
I am ok to change it as well, but I am trying to be objective here, and change only the necessary for what is described in the issue, and try not have side effects
Maybe @adamsitnik can provide his opinion here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of returning all errors instead the first one. 👍
Currently if there are two or more errors:
- The users tries to run the benchmarks, gets a single error and fixes it.
- The users tries to run the benchmarks, gets another error and fixes it.
- The user actually runs the benchmarks.
If we provide all errors at once we can reduce the number of steps needed and hence improve the UX.
src/BenchmarkDotNet/Toolchains/CsProj/CsProjClassicNetToolchain.cs
Outdated
Show resolved
Hide resolved
4d594fc
to
86e07f5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, it looks very good, but it would be great if you could change the validator behavior to return all known errors when possible. I know that the original issue did not mention it, but since you are improving the error handling, why not make it even better when we can?
Thank you @emanuel-v-r !
} | ||
|
||
if (InvalidCliPath(customDotNetCliPath: null, benchmarkCase, logger)) | ||
return false; | ||
{ | ||
var validationError = new ValidationError(true, $"InvalidCliPath, benchmark '{benchmarkCase.DisplayInfo}' will not be executed", benchmarkCase); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of returning all errors instead the first one. 👍
Currently if there are two or more errors:
- The users tries to run the benchmarks, gets a single error and fixes it.
- The users tries to run the benchmarks, gets another error and fixes it.
- The user actually runs the benchmarks.
If we provide all errors at once we can reduce the number of steps needed and hence improve the UX.
ffa1224
to
5953396
Compare
* Replace IsSupported method by Validate which returns the errors instead of only a bool * Extract printing logic from tool chains * Remove logger dependency from IToolChain Co-authored-by: Adam Sitnik <adam.sitnik@gmail.com>
5953396
to
e3ed1e1
Compare
Thank you @adamsitnik , applied your suggestions, and also changed the validate method in the other toolchains so that it returns multiple erros. |
@@ -136,7 +136,7 @@ private static Summary RunWithExceptionHandling(Func<Summary> run) | |||
catch (InvalidBenchmarkDeclarationException e) | |||
{ | |||
ConsoleLogger.Default.WriteLineError(e.Message); | |||
return Summary.NothingToRun(e.Message, string.Empty, string.Empty); | |||
return Summary.ValidationFailed(e.Message, string.Empty, string.Empty); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks a little weird here. Maybe find a better name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any suggestion? Maybe just Summary.Failed
?
Co-authored-by: Yegor Stepanov <yegor.stepanov@outlook.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you very much for your contribution @emanuel-v-r !
|
||
namespace BenchmarkDotNet.Toolchains.MonoWasm | ||
{ | ||
[PublicAPI] | ||
public class WasmToolChain : Toolchain | ||
public class WasmToolchain : Toolchain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renaming public types is considered to be a breaking change and we avoid doing that if we can. However, this particular type is most likely not used directly by anyone, so it's OK-ish ;)
@@ -50,6 +51,7 @@ public override int GetHashCode() | |||
} | |||
} | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: redundant empty lone
Aims to fix #989, added a similar test to the one that is described in the issue.
After this PR, the summary will include validation errors and the output will look like this:
Although I believe it fits the purpose of what is described in the original issue, the error is not that specific, if we want to have something more specific we will have to introduce a new method in the IToolChain interface as the existing one returns only a bool https://github.com/dotnet/BenchmarkDotNet/blob/master/src/BenchmarkDotNet/Toolchains/IToolchain.cs#L16