From e0daacaed3637e39cba9a3403f194fa49ffaeae9 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 18 Oct 2026 00:03:58 +0200 Subject: [PATCH] Source-generated RegEx: net10.0, BenchmarkDotNet 0.15.8, static and per-call compiled benchmarks, plain xUnit asserts Benchmarks return the IsMatch result. Adds StaticRegex and NewCompiledRegex rows, the partial-property form and six tests for the new methods. FluentAssertions removed; test packages on the batch policy. --- .../GlobalUsings.cs | 1 - ...manceWithSourceGeneratedRegEx.Tests.csproj | 11 ++- .../PasswordValidatorTests.cs | 80 +++++++++++++++++-- ...PerformanceWithSourceGeneratedRegEx.csproj | 4 +- .../PasswordValidator.cs | 19 +++++ .../RegexBenchmarks.cs | 14 +++- 6 files changed, 110 insertions(+), 19 deletions(-) delete mode 100644 dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/GlobalUsings.cs diff --git a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/GlobalUsings.cs b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/GlobalUsings.cs deleted file mode 100644 index 46e8b7b3e2..0000000000 --- a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/GlobalUsings.cs +++ /dev/null @@ -1 +0,0 @@ -global using FluentAssertions; \ No newline at end of file diff --git a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/ImprovePerformanceWithSourceGeneratedRegEx.Tests.csproj b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/ImprovePerformanceWithSourceGeneratedRegEx.Tests.csproj index 8ea74ec993..eb93a83b1d 100644 --- a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/ImprovePerformanceWithSourceGeneratedRegEx.Tests.csproj +++ b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/ImprovePerformanceWithSourceGeneratedRegEx.Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable @@ -10,11 +10,10 @@ - - - - - + + + + diff --git a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/PasswordValidatorTests.cs b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/PasswordValidatorTests.cs index c567163b7f..8f5be5e931 100644 --- a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/PasswordValidatorTests.cs +++ b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.Tests/PasswordValidatorTests.cs @@ -13,7 +13,7 @@ public void GivenValidPassword_WhenValidatePasswordWithRegularRegExIsInvoked_The var result = PasswordValidator.ValidatePasswordWithRegularRegEx(ValidPassword); // Assert - result.Should().BeTrue(); + Assert.True(result); } [Fact] @@ -23,7 +23,7 @@ public void GivenInvalidPassword_WhenValidatePasswordWithRegularRegExIsInvoked_T var result = PasswordValidator.ValidatePasswordWithRegularRegEx(InvalidPassword); // Assert - result.Should().BeFalse(); + Assert.False(result); } #endregion @@ -35,7 +35,7 @@ public void GivenValidPassword_WhenValidatePasswordWithCompiledRegExIsInvoked_Th var result = PasswordValidator.ValidatePasswordWithCompiledRegEx(ValidPassword); // Assert - result.Should().BeTrue(); + Assert.True(result); } [Fact] @@ -45,7 +45,7 @@ public void GivenInvalidPassword_WhenValidatePasswordWithCompiledRegExIsInvoked_ var result = PasswordValidator.ValidatePasswordWithCompiledRegEx(InvalidPassword); // Assert - result.Should().BeFalse(); + Assert.False(result); } #endregion @@ -57,7 +57,7 @@ public void GivenValidPassword_WhenValidatePasswordWithSourceGeneratedRegExIsInv var result = PasswordValidator.ValidatePasswordWithSourceGeneratedRegEx(ValidPassword); // Assert - result.Should().BeTrue(); + Assert.True(result); } [Fact] @@ -67,7 +67,73 @@ public void GivenInvalidPassword_WhenValidatePasswordWithSourceGeneratedRegExIsI var result = PasswordValidator.ValidatePasswordWithSourceGeneratedRegEx(InvalidPassword); // Assert - result.Should().BeFalse(); + Assert.False(result); } #endregion -} \ No newline at end of file + + #region ValidatePasswordWithStaticRegEx + [Fact] + public void GivenValidPassword_WhenValidatePasswordWithStaticRegExIsInvoked_ThenTrueIsReturned() + { + // Act + var result = PasswordValidator.ValidatePasswordWithStaticRegEx(ValidPassword); + + // Assert + Assert.True(result); + } + + [Fact] + public void GivenInvalidPassword_WhenValidatePasswordWithStaticRegExIsInvoked_ThenFalseIsReturned() + { + // Act + var result = PasswordValidator.ValidatePasswordWithStaticRegEx(InvalidPassword); + + // Assert + Assert.False(result); + } + #endregion + + #region ValidatePasswordWithNewCompiledRegEx + [Fact] + public void GivenValidPassword_WhenValidatePasswordWithNewCompiledRegExIsInvoked_ThenTrueIsReturned() + { + // Act + var result = PasswordValidator.ValidatePasswordWithNewCompiledRegEx(ValidPassword); + + // Assert + Assert.True(result); + } + + [Fact] + public void GivenInvalidPassword_WhenValidatePasswordWithNewCompiledRegExIsInvoked_ThenFalseIsReturned() + { + // Act + var result = PasswordValidator.ValidatePasswordWithNewCompiledRegEx(InvalidPassword); + + // Assert + Assert.False(result); + } + #endregion + + #region ValidatePasswordWithSourceGeneratedRegExProperty + [Fact] + public void GivenValidPassword_WhenValidatePasswordWithSourceGeneratedRegExPropertyIsInvoked_ThenTrueIsReturned() + { + // Act + var result = PasswordValidator.ValidatePasswordWithSourceGeneratedRegExProperty(ValidPassword); + + // Assert + Assert.True(result); + } + + [Fact] + public void GivenInvalidPassword_WhenValidatePasswordWithSourceGeneratedRegExPropertyIsInvoked_ThenFalseIsReturned() + { + // Act + var result = PasswordValidator.ValidatePasswordWithSourceGeneratedRegExProperty(InvalidPassword); + + // Assert + Assert.False(result); + } + #endregion +} diff --git a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.csproj b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.csproj index 848f901f4f..c96a8eb1e7 100644 --- a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.csproj +++ b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx.csproj @@ -2,13 +2,13 @@ Exe - net8.0 + net10.0 enable enable - + diff --git a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/PasswordValidator.cs b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/PasswordValidator.cs index 9340cbab7c..fb6d09cdf4 100644 --- a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/PasswordValidator.cs +++ b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/PasswordValidator.cs @@ -11,16 +11,35 @@ public static bool ValidatePasswordWithRegularRegEx(string password) return regex.IsMatch(password); } + public static bool ValidatePasswordWithStaticRegEx(string password) + => Regex.IsMatch( + password, + @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$"); + public static bool ValidatePasswordWithCompiledRegEx(string password) => Regex.IsMatch( password, @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$", RegexOptions.Compiled); + public static bool ValidatePasswordWithNewCompiledRegEx(string password) + { + var regex = new Regex( + @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$", + RegexOptions.Compiled); + + return regex.IsMatch(password); + } public static bool ValidatePasswordWithSourceGeneratedRegEx(string password) => PasswordRegEx().IsMatch(password); + public static bool ValidatePasswordWithSourceGeneratedRegExProperty(string password) + => PasswordRegExProperty.IsMatch(password); + [GeneratedRegex(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$")] private static partial Regex PasswordRegEx(); + + [GeneratedRegex(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$")] + private static partial Regex PasswordRegExProperty { get; } } diff --git a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/RegexBenchmarks.cs b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/RegexBenchmarks.cs index b428ecfecf..b86206a54d 100644 --- a/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/RegexBenchmarks.cs +++ b/dotnet-performance/ImprovePerformanceWithSourceGeneratedRegEx/ImprovePerformanceWithSourceGeneratedRegEx/RegexBenchmarks.cs @@ -12,15 +12,23 @@ public class RegexBenchmarks private const string Password = "c0d3-MaZ3-Pa55w0rd"; [Benchmark(Baseline = true)] - public void RegularRegex() + public bool RegularRegex() => PasswordValidator.ValidatePasswordWithRegularRegEx(Password); [Benchmark] - public void CompiledRegex() + public bool StaticRegex() + => PasswordValidator.ValidatePasswordWithStaticRegEx(Password); + + [Benchmark] + public bool CompiledRegex() => PasswordValidator.ValidatePasswordWithCompiledRegEx(Password); [Benchmark] - public void SourceGeneratedRegex() + public bool NewCompiledRegex() + => PasswordValidator.ValidatePasswordWithNewCompiledRegEx(Password); + + [Benchmark] + public bool SourceGeneratedRegex() => PasswordValidator.ValidatePasswordWithSourceGeneratedRegEx(Password); private class StyleConfig : ManualConfig