diff --git a/src/BenchmarkDotNet/Running/BenchmarkRunnerDirty.cs b/src/BenchmarkDotNet/Running/BenchmarkRunnerDirty.cs index 2f8606b0cd..f80158e35f 100644 --- a/src/BenchmarkDotNet/Running/BenchmarkRunnerDirty.cs +++ b/src/BenchmarkDotNet/Running/BenchmarkRunnerDirty.cs @@ -86,14 +86,23 @@ public static Summary RunSource(string source, IConfig? config = null) [MethodImpl(MethodImplOptions.NoInlining)] private static Summary RunWithDirtyAssemblyResolveHelper(Type type, IConfig? config, string[]? args) - => (args == null + { + var summaries = args == null ? BenchmarkRunnerClean.Run(new[] { BenchmarkConverter.TypeToBenchmarks(type, config) }) - : new BenchmarkSwitcher(new[] { type }).RunWithDirtyAssemblyResolveHelper(args, config, false)) - .Single(); + : new BenchmarkSwitcher(new[] { type }).RunWithDirtyAssemblyResolveHelper(args, config, false); + + return summaries.SingleOrDefault() + ?? Summary.ValidationFailed($"No benchmarks found in type '{type.Name}'", string.Empty, string.Empty); + } [MethodImpl(MethodImplOptions.NoInlining)] private static Summary RunWithDirtyAssemblyResolveHelper(Type type, MethodInfo[] methods, IConfig? config = null) - => BenchmarkRunnerClean.Run(new[] { BenchmarkConverter.MethodsToBenchmarks(type, methods, config) }).Single(); + { + var summaries = BenchmarkRunnerClean.Run(new[] { BenchmarkConverter.MethodsToBenchmarks(type, methods, config) }); + + return summaries.SingleOrDefault() + ?? Summary.ValidationFailed($"No benchmarks found in type '{type.Name}'", string.Empty, string.Empty); + } [MethodImpl(MethodImplOptions.NoInlining)] private static Summary[] RunWithDirtyAssemblyResolveHelper(Assembly assembly, IConfig? config, string[]? args) diff --git a/tests/BenchmarkDotNet.Tests/Running/RunningEmptyBenchmarkTests.cs b/tests/BenchmarkDotNet.Tests/Running/RunningEmptyBenchmarkTests.cs index 3dcee47bb6..ea2836b5f3 100644 --- a/tests/BenchmarkDotNet.Tests/Running/RunningEmptyBenchmarkTests.cs +++ b/tests/BenchmarkDotNet.Tests/Running/RunningEmptyBenchmarkTests.cs @@ -42,25 +42,32 @@ public class RunningEmptyBenchmarkTests /// [Theory] [InlineData(null)] - //[InlineData(new object[] { new string[] { " " } })] + [InlineData(new object[] { new string[] { " " } })] public void GenericTypeWithoutBenchmarkAttribute_ThrowsValidationError_WhenNoBenchmarkAttribute(string[]? args) { GetConfigWithLogger(out var logger, out var config); var summary = BenchmarkRunner.Run(config, args); + if (args == null) { Assert.True(summary.HasCriticalValidationErrors); Assert.Contains(summary.ValidationErrors, validationError => validationError.Message == GetValidationErrorForType(typeof(EmptyBenchmark))); + Assert.Contains(GetValidationErrorForType(typeof(EmptyBenchmark)), logger.GetLog()); + } + else + { + // When args is provided and type is invalid, we get a ValidationFailed summary + // instead of an unhandled exception (fix for issue #2724) + Assert.NotNull(summary); + Assert.Contains("No benchmarks found", summary.Title); } - - Assert.Contains(GetValidationErrorForType(typeof(EmptyBenchmark)), logger.GetLog()); } #pragma warning restore BDN1000 [Theory] [InlineData(null)] - //[InlineData(new object[] { new string[] { " " } })] + [InlineData(new object[] { new string[] { " " } })] public void GenericTypeWithBenchmarkAttribute_RunsSuccessfully(string[]? args) { GetConfigWithLogger(out var logger, out var config); @@ -79,16 +86,26 @@ public void GenericTypeWithBenchmarkAttribute_RunsSuccessfully(string[]? args) /// [Theory] [InlineData(null)] - //[InlineData(new object[] { new string[] { " " } })] + [InlineData(new object[] { new string[] { " " } })] public void TypeWithoutBenchmarkAttribute_ThrowsValidationError_WhenNoBenchmarkAttribute(string[]? args) { GetConfigWithLogger(out var logger, out var config); - var summary = BenchmarkRunner.Run(typeof(EmptyBenchmark), config, args); - Assert.True(summary.HasCriticalValidationErrors); - Assert.Contains(summary.ValidationErrors, validationError => validationError.Message == GetValidationErrorForType(typeof(EmptyBenchmark))); - Assert.Contains(GetValidationErrorForType(typeof(EmptyBenchmark)), logger.GetLog()); + + if (args == null) + { + Assert.True(summary.HasCriticalValidationErrors); + Assert.Contains(summary.ValidationErrors, validationError => validationError.Message == GetValidationErrorForType(typeof(EmptyBenchmark))); + Assert.Contains(GetValidationErrorForType(typeof(EmptyBenchmark)), logger.GetLog()); + } + else + { + // When args is provided and type is invalid, we get a ValidationFailed summary + // instead of an unhandled exception (fix for issue #2724) + Assert.NotNull(summary); + Assert.Contains("No benchmarks found", summary.Title); + } } #pragma warning restore BDN1000