-
Notifications
You must be signed in to change notification settings - Fork 5
Add missing RandomNumberGenerator polyfills for .NET Core 2.0-3.0, .NET 6.0-8.0 #77
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
Changes from all commits
ae6ff35
2244178
2fe7ebe
606a1ab
bc91cee
67aa26f
7174671
eb2fbd9
608b56e
41d1ed5
8d27fa8
cb920a6
031dc8a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| using System.Security.Cryptography; | ||
| using FluentAssertions; | ||
| using Xunit; | ||
|
|
||
| namespace PolyShim.Tests.Net60; | ||
|
|
||
| public class RandomNumberGeneratorTests | ||
| { | ||
| [Fact] | ||
| public void GetBytes_Static_Test() | ||
| { | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Act | ||
| var data = RandomNumberGenerator.GetBytes(16); | ||
|
|
||
| // Assert | ||
| data.Should().HaveCount(16); | ||
| data.Should().Contain(b => b != 0); | ||
|
Comment on lines
+18
to
+19
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is assert |
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| using System; | ||
| using System.Security.Cryptography; | ||
| using FluentAssertions; | ||
| using Xunit; | ||
|
|
||
| namespace PolyShim.Tests.Net80; | ||
|
|
||
| public class RandomNumberGeneratorTests | ||
| { | ||
| [Fact] | ||
| public void GetHexString_Test() | ||
| { | ||
| // Act & assert | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| RandomNumberGenerator.GetHexString(16).Should().MatchRegex("^[0-9A-F]{16}$"); | ||
| RandomNumberGenerator.GetHexString(16, true).Should().MatchRegex("^[0-9a-f]{16}$"); | ||
| RandomNumberGenerator.GetHexString(15).Should().MatchRegex("^[0-9A-F]{15}$"); | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetString_Test() | ||
| { | ||
| // Arrange | ||
| var choices = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".AsSpan(); | ||
|
|
||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Act | ||
| var str = RandomNumberGenerator.GetString(choices, 16); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is act |
||
|
|
||
| // Assert | ||
| str.Length.Should().Be(16); | ||
|
|
||
| foreach (var ch in str) | ||
| { | ||
| choices.ToArray().Should().Contain(ch); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetItems_Test() | ||
| { | ||
| // Arrange | ||
| var choices = new[] { 1, 2, 3, 4, 5 }.AsSpan(); | ||
|
|
||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Act | ||
| var items = RandomNumberGenerator.GetItems(choices, 3); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is act |
||
|
|
||
| // Assert | ||
| items.Should().HaveCount(3); | ||
|
|
||
| foreach (var item in items) | ||
| { | ||
| choices.ToArray().Should().Contain(item); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetItems_Span_Test() | ||
| { | ||
| // Arrange | ||
| var choices = new[] { 1, 2, 3, 4, 5 }.AsSpan(); | ||
| var destination = new Span<int>(new int[3]); | ||
|
|
||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Act | ||
| RandomNumberGenerator.GetItems(choices, destination); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is act |
||
|
|
||
| // Assert | ||
| destination.Length.Should().Be(3); | ||
|
|
||
| foreach (var item in destination) | ||
| { | ||
| choices.ToArray().Should().Contain(item); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Shuffle_Test() | ||
| { | ||
| // Arrange | ||
| var originalItems = new[] { 1, 2, 3, 4, 5 }; | ||
|
|
||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Act | ||
| var items = new Span<int>((int[])originalItems.Clone()); | ||
| RandomNumberGenerator.Shuffle(items); | ||
|
Comment on lines
+95
to
+96
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is act |
||
|
|
||
| // Assert | ||
| items.Length.Should().Be(originalItems.Length); | ||
| items.ToArray().Should().BeEquivalentTo(originalItems); | ||
|
|
||
| foreach (var item in items) | ||
| { | ||
| originalItems.Should().Contain(item); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| using System; | ||
| using System.Linq; | ||
| using System.Security.Cryptography; | ||
| using FluentAssertions; | ||
| using Xunit; | ||
|
|
||
| namespace PolyShim.Tests.NetCore20; | ||
|
|
||
| public class RandomNumberGeneratorTests | ||
| { | ||
| [Fact] | ||
| public void GetBytes_PartialArray_Test() | ||
| { | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Arrange | ||
| using var rng = RandomNumberGenerator.Create(); | ||
| var data = new byte[20]; | ||
|
Comment on lines
+17
to
+18
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is arrange |
||
|
|
||
| // Act | ||
| rng.GetBytes(data, 5, 10); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is act |
||
|
|
||
| // Assert | ||
| data.Take(5).Should().OnlyContain(b => b == 0); | ||
| data.Skip(5).Take(10).Should().Contain(b => b != 0); | ||
| data.Skip(15).Should().OnlyContain(b => b == 0); | ||
|
Comment on lines
+24
to
+26
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is assert |
||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetBytes_EmptyCount_Test() | ||
| { | ||
| // Arrange | ||
| using var rng = RandomNumberGenerator.Create(); | ||
| var data = new byte[10]; | ||
|
|
||
| // Act | ||
| rng.GetBytes(data, 0, 0); | ||
|
|
||
| // Assert | ||
| data.Should().OnlyContain(b => b == 0); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetNonZeroBytes_Array_Test() | ||
| { | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Arrange | ||
| using var rng = RandomNumberGenerator.Create(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is arrange |
||
| var data = new byte[10]; | ||
|
|
||
| // Act | ||
| rng.GetNonZeroBytes(data); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is act |
||
|
|
||
| // Assert | ||
| data.Should().NotContain((byte)0); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is assert |
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,17 +10,20 @@ public class RandomNumberGeneratorTests | |
| [Fact] | ||
| public void Fill_Span_Test() | ||
| { | ||
| // Arrange | ||
| var span = new Span<byte>(new byte[16]); | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Arrange | ||
| var span = new Span<byte>(new byte[16]); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is arrange |
||
|
|
||
| // Act | ||
| RandomNumberGenerator.Fill(span); | ||
| // Act | ||
| RandomNumberGenerator.Fill(span); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is act |
||
|
|
||
| // Assert | ||
| // Verify that not all bytes are zero (cryptographic RNG should produce non-zero data). | ||
| // Note: Theoretically, a crypto RNG could produce all zeros (probability: 2^-128), | ||
| // but this is astronomically unlikely in practice. | ||
| span.ToArray().Should().Contain(b => b != 0); | ||
| // Assert | ||
| // Verify that not all bytes are zero (cryptographic RNG should produce non-zero data). | ||
| // Note: Theoretically, a crypto RNG could produce all zeros (probability: 2^-128), | ||
| // but this is astronomically unlikely in practice. | ||
| span.ToArray().Should().Contain(b => b != 0); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is assert |
||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
|
|
@@ -33,4 +36,50 @@ public void Fill_EmptySpan_Test() | |
| // Should not throw and should return immediately | ||
| RandomNumberGenerator.Fill(span); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetBytes_Span_Test() | ||
| { | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Arrange | ||
| using var rng = RandomNumberGenerator.Create(); | ||
| var span = new Span<byte>(new byte[16]); | ||
|
|
||
| // Act | ||
| rng.GetBytes(span); | ||
|
|
||
| // Assert | ||
| span.ToArray().Should().Contain(b => b != 0); | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetBytes_EmptySpan_Test() | ||
| { | ||
| // Arrange | ||
| using var rng = RandomNumberGenerator.Create(); | ||
| var span = new Span<byte>(); | ||
|
|
||
| // Act & Assert | ||
| // Should not throw and should return immediately | ||
| rng.GetBytes(span); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetNonZeroBytes_Span_Test() | ||
| { | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Arrange | ||
| using var rng = RandomNumberGenerator.Create(); | ||
| var data = new Span<byte>(new byte[10]); | ||
|
|
||
| // Act | ||
| rng.GetNonZeroBytes(data); | ||
|
|
||
| // Assert | ||
| data.ToArray().Should().NotContain((byte)0); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| using System.Security.Cryptography; | ||
| using FluentAssertions; | ||
| using Xunit; | ||
|
|
||
| namespace PolyShim.Tests.NetCore30; | ||
|
|
||
| public class RandomNumberGeneratorTests | ||
| { | ||
| [Fact] | ||
| public void GetInt32_MaxValue_Test() | ||
| { | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Act | ||
| var value = RandomNumberGenerator.GetInt32(10); | ||
|
|
||
| // Assert | ||
| value.Should().BeInRange(0, 9); | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void GetInt32_Range_Test() | ||
| { | ||
| for (var i = 0; i < 100; i++) | ||
| { | ||
| // Act | ||
| var value = RandomNumberGenerator.GetInt32(10, 20); | ||
|
|
||
| // Assert | ||
| value.Should().BeInRange(10, 19); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #if (NETCOREAPP && !NET6_0_OR_GREATER) || (NETFRAMEWORK) || (NETSTANDARD) | ||
| #nullable enable | ||
| // ReSharper disable RedundantUsingDirective | ||
| // ReSharper disable CheckNamespace | ||
| // ReSharper disable InconsistentNaming | ||
| // ReSharper disable PartialTypeWithSinglePart | ||
|
|
||
| using System; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Security.Cryptography; | ||
|
|
||
| [ExcludeFromCodeCoverage] | ||
| internal static class MemberPolyfills_Net60_RandomNumberGenerator | ||
| { | ||
| extension(RandomNumberGenerator) | ||
| { | ||
| // https://learn.microsoft.com/dotnet/api/system.security.cryptography.randomnumbergenerator.getbytes#system-security-cryptography-randomnumbergenerator-getbytes(system-int32) | ||
| public static byte[] GetBytes(int count) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method was added in net 6 |
||
| { | ||
| var data = new byte[count]; | ||
| RandomNumberGenerator.Fill(data); | ||
| return data; | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
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.
This is act